#include "data_publish.h"
#define METER_SN "bmsmeter" 
#define VPCS_SN "vpcs" //idf real_data

#define PCS_IDENTIFIER "system_status"
#define METER_IDENTIFIER "meter_upload_data"
#define METER_POWRE_REPORT_IDENTIFIER "sanxianggongluxinxi"
#define METER_ENERGY_REPORT_IDENTIFIER "yougongzongdianliang"
#define METER_VOL_CURRENT_IDENTIFIER "sanxiangcv"

void data_publish_to_dev(energy_var_t *var,char *dev_sn,char *port, char *identifier,char *data){
    char *data_tmp = NULL;
    char topic[TOPIC_MAX_LEN] = {0};
    cJSON *tag_data = cJSON_CreateObject();
    cJSON_AddStringToObject(tag_data, "sn", dev_sn);
    cJSON_AddNumberToObject(tag_data, "time", time(NULL));
    cJSON_AddStringToObject(tag_data, "identifier", identifier);
    cJSON_AddNumberToObject(tag_data, "report_period", -1);//NONEED_REPORT，减少流量
    cJSON_AddNumberToObject(tag_data, "data_type", 2);
    cJSON_AddNumberToObject(tag_data, "mi", 0);
    cJSON_AddStringToObject(tag_data, "tag_node", data);
    data_tmp = cJSON_Print(tag_data);        
    // ipc/%s/+/device/+/data/set_rglt_raw
    snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/%s/device/%s/data/service/%s", var->sn_str,port, dev_sn, identifier);
    ipc_session_publish(var->session, topic, (unsigned char*)data_tmp , strlen(data_tmp));
    
    //dbg_syslog(LOG_INFO, "topic:%s", topic);
    cJSON_Delete(tag_data);
    free(data_tmp);
}

void data_report_meter(energy_var_t *var){
    char *data_tmp = NULL;
    cJSON *tag_meter_vol_cur = cJSON_CreateObject();//
    cJSON *tag_energy_report = cJSON_CreateObject();//
    cJSON *tag_power_report = cJSON_CreateObject();//
    eng_ass_data_t *tag = var->eng_ass_data;
    cJSON_AddNumberToObject(tag_meter_vol_cur, "TAG_2716", tag->meter_a_voltage);
    cJSON_AddNumberToObject(tag_meter_vol_cur, "TAG_2717", tag->meter_b_voltage);
    cJSON_AddNumberToObject(tag_meter_vol_cur, "TAG_2718", tag->meter_c_voltage);
    cJSON_AddNumberToObject(tag_meter_vol_cur, "TAG_2719", tag->meter_a_current);
    cJSON_AddNumberToObject(tag_meter_vol_cur, "TAG_271A", tag->meter_b_current);
    cJSON_AddNumberToObject(tag_meter_vol_cur, "TAG_271B", tag->meter_c_current);
    data_tmp = cJSON_PrintUnformatted(tag_meter_vol_cur); 
    data_publish_to_dev(var,var->bmsmeter_sn_str,"VIRTUAL_1",METER_VOL_CURRENT_IDENTIFIER,data_tmp);//
    free(data_tmp);
    cJSON_AddNumberToObject(tag_energy_report, "TAG_2734", tag->meter_positive_energy);
    cJSON_AddNumberToObject(tag_energy_report, "TAG_2739", tag->meter_negtive_energy);
    data_tmp = cJSON_PrintUnformatted(tag_energy_report); 
    data_publish_to_dev(var,var->bmsmeter_sn_str,"VIRTUAL_1",METER_ENERGY_REPORT_IDENTIFIER,data_tmp);//
    free(data_tmp);
    cJSON_AddNumberToObject(tag_power_report, "TAG_2730", tag->meter_reactive_power);
    cJSON_AddNumberToObject(tag_power_report, "TAG_272F", tag->meter_total_power);
    data_tmp = cJSON_PrintUnformatted(tag_power_report); 
    data_publish_to_dev(var,var->bmsmeter_sn_str,"VIRTUAL_1",METER_POWRE_REPORT_IDENTIFIER,data_tmp);//
    // free(data_tmp);
    cJSON_Delete(tag_meter_vol_cur);
    cJSON_Delete(tag_energy_report);
    cJSON_Delete(tag_power_report);
    free(data_tmp);
}
void data_report_vpcs(energy_var_t *var){
    char *data_tmp = NULL; 
    cJSON *tag_data = cJSON_CreateObject();
    eng_ass_data_t *tag = var->eng_ass_data;
    cJSON_AddNumberToObject(tag_data, "pcsalarm", tag->pcs_fault);//
    data_tmp = cJSON_Print(tag_data);
    data_publish_to_dev(var,var->eng_sn_str,"VIRTUAL_1","pcs_fault_alarm",data_tmp);

    free(data_tmp);
    cJSON_AddNumberToObject(tag_data, "pcs_connect_state", tag->pcs_connect_state);
    cJSON_AddNumberToObject(tag_data, "pcs_run_state", tag->pcs_run_state);
    cJSON_AddNumberToObject(tag_data, "pcs_active_power", tag->pcs_active_power);
    cJSON_AddNumberToObject(tag_data, "pcs_reactive_power", tag->pcs_reactive_power);
    cJSON_AddNumberToObject(tag_data, "meter_a_voltage", tag->meter_a_voltage);
    cJSON_AddNumberToObject(tag_data, "meter_b_voltage", tag->meter_b_voltage);
    cJSON_AddNumberToObject(tag_data, "meter_c_voltage", tag->meter_c_voltage);
    cJSON_AddNumberToObject(tag_data, "meter_a_current", tag->meter_a_current);
    cJSON_AddNumberToObject(tag_data, "meter_b_current", tag->meter_b_current);
    cJSON_AddNumberToObject(tag_data, "meter_c_current", tag->meter_c_current);
    cJSON_AddNumberToObject(tag_data, "meter_total_power", tag->meter_total_power);
    cJSON_AddNumberToObject(tag_data, "bms_total_current", tag->bms_total_current);
    cJSON_AddNumberToObject(tag_data, "bms_total_voltage", tag->bms_total_voltage);
    cJSON_AddNumberToObject(tag_data, "bms_work_state", tag->bms_work_state);
    cJSON_AddNumberToObject(tag_data, "bms_cha_discha_state", tag->bms_cha_discha_state);
    cJSON_AddNumberToObject(tag_data, "bms_switch_on_state", tag->bms_switch_on_state);
    cJSON_AddNumberToObject(tag_data, "bms_conn_high_power", tag->bms_conn_high_power);
    cJSON_AddNumberToObject(tag_data, "pcs_remote", tag->pcs_remote);
    cJSON_AddNumberToObject(tag_data, "bms_soc", tag->bms_soc*10);
    cJSON_AddNumberToObject(tag_data, "on_service_state", tag->on_service_state);
    cJSON_AddNumberToObject(tag_data, "expect_run_state", tag->expect_run_state);
    cJSON_AddNumberToObject(tag_data, "expect_relay_state", tag->expect_relay_state);
    data_tmp = cJSON_PrintUnformatted(tag_data);
    data_publish_to_dev(var,var->eng_sn_str,"VIRTUAL_1",PCS_IDENTIFIER,data_tmp);
    cJSON_Delete(tag_data);
    free(data_tmp);
}

//故障上报
void data_report_fault(energy_var_t *var){
    char *data_tmp = NULL;
    
    time_t now_time = time(NULL);
    static time_t former_time = {0};
    eng_ass_data_t tmp = *(var->eng_ass_data);
    static eng_ass_data_t former_var = {0};
    if ((tmp.pcs_fault!=former_var.pcs_fault) || \
    (tmp.fault_level!=former_var.fault_level) || \
    (tmp.pcs_conn_fb_fault!=former_var.pcs_conn_fb_fault) || \
    (tmp.pcs_run_fb_fault!=former_var.pcs_run_fb_fault) || \
    (tmp.pcs_comm_fault!=former_var.pcs_comm_fault) || \
    (tmp.bms_comm_fault!=former_var.bms_comm_fault) || \
    (tmp.meter_comm_fault!=former_var.meter_comm_fault) || (now_time-former_time>30)){
        cJSON *tag_data = cJSON_CreateObject();//
        eng_ass_data_t *tag = var->eng_ass_data;
        cJSON_AddNumberToObject(tag_data, "pcs_fault", tag->pcs_fault);
        cJSON_AddNumberToObject(tag_data, "pcs_comm_fault", tag->pcs_comm_fault);
        cJSON_AddNumberToObject(tag_data, "pcs_conn_fb_fault", tag->pcs_conn_fb_fault);
        cJSON_AddNumberToObject(tag_data, "pcs_run_fb_fault", tag->pcs_run_fb_fault);
        cJSON_AddNumberToObject(tag_data, "meter_comm_fault", tag->meter_comm_fault);
        cJSON_AddNumberToObject(tag_data, "bms_fault", tag->bms_fault);
        cJSON_AddNumberToObject(tag_data, "bms_comm_fault", tag->bms_comm_fault);
        cJSON_AddNumberToObject(tag_data, "fault_level", tag->fault_level);
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->eng_sn_str,"VIRTUAL_1","fault_report",data_tmp);     
        cJSON_Delete(tag_data);
        free(data_tmp);
        former_time = now_time;
    }
    former_var = *(var->eng_ass_data);
}

//故障上报到站控系统
void data_report_to_station_control(energy_var_t *var,int grp_idx){
    char *data_tmp = NULL;
    
    time_t now_time = time(NULL);
    eng_ass_grp_data_t tmp = var->grp[grp_idx].eng_ass_grp_data;
    static eng_ass_grp_data_t former_var[ENG_ASS_GRP_MAX] = {0};
    //eng_ass_data_t *tag = var->eng_ass_data;
    char key[90] = {0};
    if (tmp.pcs_fault!=former_var[grp_idx].pcs_fault){
        cJSON *tag_data = cJSON_CreateObject();
        if (tmp.pcs_fault && (former_var[grp_idx].pcs_fault == 0))
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s", grp_idx+1, "总故障触发");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        else if ((tmp.pcs_fault == 0) && former_var[grp_idx].pcs_fault)
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s", grp_idx+1, "总故障恢复");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        cJSON_AddNumberToObject(tag_data, "result", 0);
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->emsctrl_sn_str,"VINTF_TCP","report_info",data_tmp);
        cJSON_Delete(tag_data);
        free(data_tmp);
        former_var[grp_idx].pcs_fault = var->grp[grp_idx].eng_ass_grp_data.pcs_fault;
    }
    
    if (tmp.pcs_comm_fault!=former_var[grp_idx].pcs_comm_fault)
    {
        cJSON *tag_data = cJSON_CreateObject();
        if (tmp.pcs_comm_fault && (former_var[grp_idx].pcs_comm_fault == 0))
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s", grp_idx+1, "OFFLINE");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        else if ((tmp.pcs_comm_fault == 0) && former_var[grp_idx].pcs_comm_fault)
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s", grp_idx+1, "ONLINE");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        cJSON_AddNumberToObject(tag_data, "result", 0);
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->emsctrl_sn_str,"VINTF_TCP","report_info",data_tmp);
        cJSON_Delete(tag_data);
        free(data_tmp);
        former_var[grp_idx].pcs_fault = var->grp[grp_idx].eng_ass_grp_data.pcs_fault;
    }

    if (tmp.pcs_conn_fb_fault!=former_var[grp_idx].pcs_conn_fb_fault)
    {
        cJSON *tag_data = cJSON_CreateObject();
        if (tmp.pcs_conn_fb_fault && (former_var[grp_idx].pcs_conn_fb_fault == 0))
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s%d,%s%d", grp_idx+1, "并离网异常(1:并网),期望:",var->grp[grp_idx].eng_ass_grp_ctrl.connect,"实际:",var->grp[grp_idx].eng_ass_grp_data.pcs_connect_state);
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        else if ((tmp.pcs_conn_fb_fault == 0) && former_var[grp_idx].pcs_conn_fb_fault)
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s%d", grp_idx+1, "并离网恢复正常,实际:",var->grp[grp_idx].eng_ass_grp_data.pcs_connect_state);
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        cJSON_AddNumberToObject(tag_data, "result", 0);
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->emsctrl_sn_str,"VINTF_TCP","report_info",data_tmp);
        cJSON_Delete(tag_data);
        free(data_tmp);
        former_var[grp_idx].pcs_conn_fb_fault = var->grp[grp_idx].eng_ass_grp_data.pcs_conn_fb_fault;
    }

    if (tmp.pcs_run_fb_fault!=former_var[grp_idx].pcs_run_fb_fault)
    {
        cJSON *tag_data = cJSON_CreateObject();
        if (tmp.pcs_run_fb_fault && (former_var[grp_idx].pcs_run_fb_fault == 0))
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s%d,%s[%d,%d,%d]", grp_idx+1, "运行状态异常,期望(0关1待2开):",var->grp[grp_idx].eng_ass_grp_ctrl.run_state,"实际[关,待,开]:",var->grp[grp_idx].eng_ass_grp_data.pcs_stop_flag,var->grp[grp_idx].eng_ass_grp_data.pcs_standby_flag,var->grp[grp_idx].eng_ass_grp_data.pcs_run_flag);
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        else if ((tmp.pcs_run_fb_fault == 0) && former_var[grp_idx].pcs_run_fb_fault)
        {
            snprintf(key, sizeof(key), "[EMS]PCS%d:%s[%d,%d,%d]", grp_idx+1, "运行状态恢复正常,实际[关,待,开]:",var->grp[grp_idx].eng_ass_grp_data.pcs_stop_flag,var->grp[grp_idx].eng_ass_grp_data.pcs_standby_flag,var->grp[grp_idx].eng_ass_grp_data.pcs_run_flag);
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        cJSON_AddNumberToObject(tag_data, "result", 0);
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->emsctrl_sn_str,"VINTF_TCP","report_info",data_tmp);
        cJSON_Delete(tag_data);
        free(data_tmp);
        former_var[grp_idx].pcs_run_fb_fault = var->grp[grp_idx].eng_ass_grp_data.pcs_run_fb_fault;
    }

    if (tmp.bms_fault!=former_var[grp_idx].bms_fault)
    {
        cJSON *tag_data = cJSON_CreateObject();
        if (tmp.bms_fault && (former_var[grp_idx].bms_fault == 0))
        {
            snprintf(key, sizeof(key), "[EMS]BMS%d:%s", grp_idx+1, "总故障触发");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        else if ((tmp.bms_fault == 0) && former_var[grp_idx].bms_fault)
        {
            snprintf(key, sizeof(key), "[EMS]BMS%d:%s", grp_idx+1, "总故障恢复");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        cJSON_AddNumberToObject(tag_data, "result", 0);
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->emsctrl_sn_str,"VINTF_TCP","report_info",data_tmp);
        cJSON_Delete(tag_data);
        free(data_tmp);
        former_var[grp_idx].bms_fault = var->grp[grp_idx].eng_ass_grp_data.bms_fault;
    }

    if (tmp.bms_comm_fault!=former_var[grp_idx].bms_comm_fault)
    {
        cJSON *tag_data = cJSON_CreateObject();
        if (tmp.bms_comm_fault && (former_var[grp_idx].bms_comm_fault == 0))
        {
            snprintf(key, sizeof(key), "[EMS]BMS%d:%s", grp_idx+1, "OFFLINE");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        else if ((tmp.bms_comm_fault == 0) && former_var[grp_idx].bms_comm_fault)
        {
            snprintf(key, sizeof(key), "[EMS]BMS%d:%s", grp_idx+1, "ONLINE");
            cJSON_AddStringToObject(tag_data, "info",key);
        }
        cJSON_AddNumberToObject(tag_data, "result", 0);
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->emsctrl_sn_str,"VINTF_TCP","report_info",data_tmp);
        cJSON_Delete(tag_data);
        free(data_tmp);
        former_var[grp_idx].bms_comm_fault = var->grp[grp_idx].eng_ass_grp_data.bms_comm_fault;
    }
}

//故障等级上报
void data_report_protect_level(energy_var_t *var){
    cJSON *array = NULL;
    cJSON *item = NULL;
    char *data_tmp = NULL;
    // cJSON *grps_fault_level = cJSON_CreateObject();
    time_t now_time = time(NULL);
    static time_t former_time = {0};
    eng_ass_data_t tmp = *(var->eng_ass_data);
    static eng_ass_data_t former_var = {0};
    if ((tmp.pcs_fault!=former_var.pcs_fault) || \
    (tmp.fault_level!=former_var.fault_level) || \
    (tmp.pcs_conn_fb_fault!=former_var.pcs_conn_fb_fault) || \
    (tmp.pcs_run_fb_fault!=former_var.pcs_run_fb_fault) || \
    (tmp.pcs_comm_fault!=former_var.pcs_comm_fault) || \
    (tmp.bms_comm_fault!=former_var.bms_comm_fault) || \
    (tmp.meter_comm_fault!=former_var.meter_comm_fault) || (now_time-former_time>30)){
        cJSON *tag_data = cJSON_CreateObject();
        eng_ass_data_t *tag = var->eng_ass_data;
        cJSON_AddNumberToObject(tag_data, "fault_level", tag->fault_level);
        cJSON_AddItemToObject(tag_data,"grps_fault_level",array=cJSON_CreateArray());
        for(int i=0;i<var->eng_ass_grp_num;i++){
            cJSON_AddItemToArray(array,item = cJSON_CreateObject());
            cJSON_AddItemToObject(item, "level", cJSON_CreateNumber(var->grp[i].eng_ass_grp_data.fault_level));//内部嵌套键值
        }
        data_tmp = cJSON_PrintUnformatted(tag_data); 
        data_publish_to_dev(var,var->eng_sn_str,"VIRTUAL_1","fault_level_report",data_tmp);//
        cJSON_Delete(tag_data); 
        free(data_tmp);
        former_time = now_time;
    }
    former_var = *(var->eng_ass_data);
}

/**************************************************************************************/
typedef struct report_all_pcs_hold_data_struct
{
    int pcs_fault;           // PCS系统故障
    int pcs_conn_fb_fault;   // PCS并网状态反馈异常
    int pcs_run_fb_fault;    // PCS运行状态反馈异常
    int pcs_online;          // PCS通信状态
    int pcs_limit_power_run; // PCS1限功率运行
    //
    int bms_fault;  // BMS系统故障
    int bms_online; // BMS通信状态
} report_all_pcs_hold_data_struct;

struct data_publish_struct
{
    int report_all_pcs_hold_data_size;
    report_all_pcs_hold_data_struct *report_all_pcs_hold_data;
    //
} data_publish_data;

// 跟新保持数据，如果没有更新返回0
static int report_all_pcs_hold_data_update(energy_var_t *var)
{
    int is_changed = 0;
    if (data_publish_data.report_all_pcs_hold_data_size == var->eng_ass_grp_num)
    {
        report_all_pcs_hold_data_struct *p = data_publish_data.report_all_pcs_hold_data;
        for (int i = 0; i < data_publish_data.report_all_pcs_hold_data_size; i++)
        {
            if (p->pcs_online != var->grp[i].eng_ass_grp_data.dev_sta.pcs_online)
            {
                is_changed = 1;

                p->pcs_online = var->grp[i].eng_ass_grp_data.dev_sta.pcs_online;
            }

            if (p->pcs_fault != var->grp[i].eng_ass_grp_data.pcs_fault)
            {
                is_changed = 1;
                p->pcs_fault = var->grp[i].eng_ass_grp_data.pcs_fault;
            }

            if (p->pcs_conn_fb_fault != var->grp[i].eng_ass_grp_data.pcs_conn_fb_fault)
            {
                is_changed = 1;
                p->pcs_conn_fb_fault = var->grp[i].eng_ass_grp_data.pcs_conn_fb_fault;
            }

            if (p->pcs_run_fb_fault != var->grp[i].eng_ass_grp_data.pcs_run_fb_fault)
            {
                is_changed = 1;
                p->pcs_run_fb_fault = var->grp[i].eng_ass_grp_data.pcs_run_fb_fault;
            }
            //
            if (p->bms_fault != var->grp[i].eng_ass_grp_data.bms_fault)
            {
                is_changed = 1;
                p->bms_fault = var->grp[i].eng_ass_grp_data.bms_fault;
            }

            if (p->bms_online != var->grp[i].eng_ass_grp_data.dev_sta.bms_online)
            {
                is_changed = 1;
                p->bms_online = var->grp[i].eng_ass_grp_data.dev_sta.bms_online;
            }
            if (is_changed == 1)
            {
                data_report_to_station_control(var,i);
            }
            p++;
        }
    }
    else
    {
        dbg_syslog(LOG_ERR, "report_all_pcs_hold_data_update err");
    }

    return is_changed;
}

int data_publish_init(energy_var_t *var)
{
    int grp_size = var->eng_ass_grp_num;
    if (grp_size > 0)
    {
        data_publish_data.report_all_pcs_hold_data_size = grp_size;
        data_publish_data.report_all_pcs_hold_data = (report_all_pcs_hold_data_struct *)calloc(grp_size, sizeof(report_all_pcs_hold_data_struct));
        if (data_publish_data.report_all_pcs_hold_data == NULL)
        {
            data_publish_data.report_all_pcs_hold_data_size = 0;
            dbg_syslog(LOG_ERR, "data_publish_init calloc mem err");
            return -1;
        }
    }
    else
    {
        dbg_syslog(LOG_ERR, "data_publish_init err:eng_ass_grp_num = %d", grp_size);
    }
    return 0;
}
// 所有pcs状态上报
void data_report_all_pcs(energy_var_t *var)
{
    time_t now_time = time(NULL);
    static time_t former_time = {0};
    //
    if ((report_all_pcs_hold_data_update(var) != 0) || (now_time - former_time > 30))
    {
        int grp_size = data_publish_data.report_all_pcs_hold_data_size;
        report_all_pcs_hold_data_struct *p = data_publish_data.report_all_pcs_hold_data;

        char key[32] = {0};
        cJSON *tag_data = cJSON_CreateObject();
        for (int grp_idx = 1; grp_idx <= grp_size; grp_idx++)
        {
            snprintf(key, sizeof(key), "PCS%d%s", grp_idx, "Fault");
            cJSON_AddNumberToObject(tag_data, key, p->pcs_fault);

            snprintf(key, sizeof(key), "PCS%d%s", grp_idx, "ConnFbFault");
            cJSON_AddNumberToObject(tag_data, key, p->pcs_conn_fb_fault);

            snprintf(key, sizeof(key), "PCS%d%s", grp_idx, "RunFbFault");
            cJSON_AddNumberToObject(tag_data, key, p->pcs_run_fb_fault);

            snprintf(key, sizeof(key), "PCS%d%s", grp_idx, "LimitPowerRun");
            cJSON_AddNumberToObject(tag_data, key, p->pcs_limit_power_run);

            snprintf(key, sizeof(key), "PCS%d%s", grp_idx, "CommFault");
            cJSON_AddNumberToObject(tag_data, key, (p->pcs_online != ENG_ASS_DEV_STA_ONLINE) ? 1 : 0);

            //
            snprintf(key, sizeof(key), "BMS%d%s", grp_idx, "Fault");
            cJSON_AddNumberToObject(tag_data, key, p->bms_fault); // BMS系统故障

            snprintf(key, sizeof(key), "BMS%d%s", grp_idx, "CommFault");
            cJSON_AddNumberToObject(tag_data, key, (p->bms_online != ENG_ASS_DEV_STA_ONLINE) ? 1 : 0); // MBMS通讯故障

            p++;
        }
        char *report_str = cJSON_PrintUnformatted(tag_data);
        data_publish_to_dev(var, var->emsctrl_sn_str, "VIRTUAL_1", "alarmList", report_str);
        cJSON_Delete(tag_data);
        free(report_str);
        former_time = now_time;
    }
}
