#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "cJSON.h"

#include "my_public.h"

#include "ess_bms.h"

#define ESS_BMS_CFGFILE "/app/config/ems/ess_bms.json"
// #define ESS_BMS_CFGFILE "ess_bms.json"
#define SERVICEUPCONT var->devNodeInfo.serviceupcont
#define SERVICEDOWNCONT var->devNodeInfo.servicedowncont
#define SERVICE_DOWN var->devNodeInfo.pserviceInfoDOWN
#define SERVICE_UP var->devNodeInfo.pserviceInfoUP
#define PCS_MI 12323

// #define DEBUG
// #ifdef DEBUG
// #undef dy_syslog
// #define dy_syslog(xx, fmt, ...) printf("[%s:%d->%s]" fmt "\r\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
// #else
// #endif

static int ess_bms_state_change(void *obj, int state)
{
    ess_bms_var_t *var = (ess_bms_var_t *)obj;
    char topic[TOPIC_MAX_LEN] = {0};

    switch (state)
    {
    case MQTT_CONNECTED:
        snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/+/device/%s/start", var->sn_str, "ess_bms");
        ipc_session_publish(var->session, topic, "", 0);
        break;
    }
    return E_TRUE;
}

static int publish_pcs_data(ipc_session_t *session, char *sn, unsigned char *data, int len, char *desSn, CHAR *identifier)
{
    char topic[TOPIC_MAX_LEN] = {0};
    // ipc/%s/+/device/+/data/set_rglt_raw
    snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/%s/device/%s/data/service/%s", sn, "aaa", desSn, identifier);
    dbg_syslog(LOG_DEBUG, "topic:%s", topic);
    ipc_session_publish(session, topic, data, len);
    return 0;
}

static int ess_bms_report_soc(ess_bms_var_t *var, CHAR *identifier)
{
    CHAR *data_tmp = NULL;
    int i, soc = 0;
    cJSON *sub = NULL;
    CHAR tagNode[64] = {0};
    cJSON *tag_data = cJSON_CreateObject();
    for (i = 0; i < var->devNodeInfo.devcont; i++)
    {
        soc += var->devNodeInfo.pdevnodecfg[i].essBms.soc;
    }
    if (var->socAverage)
    {
        soc = soc / var->devNodeInfo.devcont;
    }
    cJSON_AddStringToObject(tag_data, "sn", var->sn_str);
    cJSON_AddNumberToObject(tag_data, "timestamp", time(NULL));
    cJSON_AddStringToObject(tag_data, "identifier", identifier);
    cJSON_AddNumberToObject(tag_data, "mi", PCS_MI);
    // sub = cJSON_CreateObject();
    // cJSON_AddItemToObject(tag_data, "tags", sub);
    // cJSON_AddNumberToObject(sub, "soc", soc);
    sprintf(tagNode, "{\"soc\":%d}", soc);
    cJSON_AddStringToObject(tag_data, "tag_node", tagNode);
    data_tmp = cJSON_Print(tag_data);
    if (var->runMode == E_ONGW_MODE)
    {
        publish_pcs_data(var->session, var->sn_str, data_tmp, strlen(data_tmp), var->desSn, identifier);
    }
    else
    {
        publish_pcs_data(var->insession, var->sn_str, data_tmp, strlen(data_tmp), var->desSn, identifier);
    }
    free(data_tmp);
    cJSON_Delete(tag_data);
}

static int ess_bms_report_bmsalarm(ess_bms_var_t *var, CHAR *identifier)
{
    CHAR *data_tmp = NULL;
    CHAR tagNode[64] = {0};
    int i, alarm = 0;
    int chawarn = 0;
    int dischwarn = 0;

    cJSON *sub = NULL;
    cJSON *tag_data = cJSON_CreateObject();
    for (i = 0; i < var->devNodeInfo.devcont; i++)
    {
        alarm |= var->devNodeInfo.pdevnodecfg[i].essBms.alarm;
        chawarn |= var->devNodeInfo.pdevnodecfg[i].essBms.chawarn;
        dischwarn |= var->devNodeInfo.pdevnodecfg[i].essBms.dischwarn;
    }
    cJSON_AddStringToObject(tag_data, "sn", var->sn_str);
    cJSON_AddNumberToObject(tag_data, "timestamp", time(NULL));
    cJSON_AddStringToObject(tag_data, "identifier", identifier);
    cJSON_AddNumberToObject(tag_data, "mi", PCS_MI);
    sprintf(tagNode, "{\"bmsalarm\":%d,\"chawarn\":%d,\"dischwarn\":%d}", alarm, chawarn, dischwarn);
    // sub = cJSON_CreateObject();
    // cJSON_AddItemToObject(tag_data, "tags", sub);
    // cJSON_AddNumberToObject(sub, "bmsalarm", alarm);
    cJSON_AddStringToObject(tag_data, "tag_node", tagNode);
    data_tmp = cJSON_Print(tag_data);
    if (var->runMode == E_ONGW_MODE)
    {
        publish_pcs_data(var->session, var->sn_str, data_tmp, strlen(data_tmp), var->desSn, identifier);
    }
    else
    {
        publish_pcs_data(var->insession, var->sn_str, data_tmp, strlen(data_tmp), var->desSn, identifier);
    }
    free(data_tmp);
    cJSON_Delete(tag_data);
}

static int ess_bms_report_bmsmastswitch(ess_bms_var_t *var, CHAR *identifier)
{
    CHAR *data_tmp = NULL;
    CHAR tagNode[64] = {0};
    int i, mastSwitch = 0;
    cJSON *sub = NULL;
    cJSON *tag_data = cJSON_CreateObject();
    for (i = 0; i < var->devNodeInfo.devcont; i++)
    {
        mastSwitch |= var->devNodeInfo.pdevnodecfg[i].essBms.mastSwitch;
    }
    cJSON_AddStringToObject(tag_data, "sn", var->sn_str);
    cJSON_AddNumberToObject(tag_data, "timestamp", time(NULL));
    cJSON_AddStringToObject(tag_data, "identifier", identifier);
    cJSON_AddNumberToObject(tag_data, "mi", PCS_MI);
    sprintf(tagNode, "{\"mastswitch\":%d}", mastSwitch);
    // sub = cJSON_CreateObject();
    // cJSON_AddItemToObject(tag_data, "tags", sub);
    // cJSON_AddNumberToObject(sub, "bmsalarm", alarm);
    cJSON_AddStringToObject(tag_data, "tag_node", tagNode);
    data_tmp = cJSON_Print(tag_data);
    if (var->runMode == E_ONGW_MODE)
    {
        publish_pcs_data(var->session, var->sn_str, data_tmp, strlen(data_tmp), var->desSn, identifier);
    }
    else
    {
        publish_pcs_data(var->insession, var->sn_str, data_tmp, strlen(data_tmp), var->desSn, identifier);
    }
    free(data_tmp);
    cJSON_Delete(tag_data);
}

static void service_analy_proc(ess_bms_var_t *var, cJSON *sub)
{
    int i, j, n;
    double tmp = 0;
    if (sub)
    {
        for (i = 0; i < SERVICEUPCONT; i++)
        {
            // dbg_syslog(LOG_INFO, "i:%d identifier:%s name:%s", i, SERVICE_UP[i].identifier, SERVICE_UP[i].name);
            if (strcmp(SERVICE_UP[i].identifier, var->servInfo.identifier) == 0)
            {
                for (j = 0; j < var->devNodeInfo.devcont; j++)
                {
                    if (strcmp(var->devNodeInfo.pdevnodecfg[j].devSn, var->servInfo.devSn) == 0)
                    {
                        if (SERVICE_UP[i].tagNode.nodecont > 0)
                        {
                            for (n = 0; n < SERVICE_UP[i].tagNode.nodecont; n++)
                            {
                                tmp = -1;
                                // GET_JSON_VALUE_INT_LOG(sub, SERVICE_UP[i].tagNode.ptagNode[n].tag, tmp);
                                GET_JSON_VALUE_DOUBLE_LOG(sub, SERVICE_UP[i].tagNode.ptagNode[n].tag, tmp)
                                if (tmp != -1)
                                {
                                    if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "soc") == 0)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].essBms.soc = tmp * 10;
                                        ess_bms_report_soc(var, SERVICE_UP[i].inidentifier);
                                    }
                                    else if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "bmsalarm") == 0)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].essBms.alarm = tmp;
                                        ess_bms_report_bmsalarm(var, SERVICE_UP[i].inidentifier);
                                    }
                                    else if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "chawarn") == 0)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].essBms.chawarn = tmp;
                                        ess_bms_report_bmsalarm(var, SERVICE_UP[i].inidentifier);
                                    }
                                    else if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "dischwarn") == 0)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].essBms.dischwarn = tmp;
                                        ess_bms_report_bmsalarm(var, SERVICE_UP[i].inidentifier);
                                    }
                                    else if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "mast_switch") == 0)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].essBms.mastSwitch = tmp;
                                        ess_bms_report_bmsmastswitch(var, SERVICE_UP[i].inidentifier);
                                    }
                                }
                            }
                        }
                        break;
                    }
                }
            }
        }
    }
}

static int ess_bms_mqtt_handle_recv_msg(void *obj, ipc_msg_t *mqtt_msg)
{
    cJSON *node = NULL;
    cJSON *sub = NULL;
    CHAR *tagNode = NULL;
    int i, n, j = 0;
    double tmp = 0;
    ess_bms_var_t *var = (ess_bms_var_t *)obj;
    dbg_syslog(LOG_DEBUG, "topic:%s", mqtt_msg->topic);
    if (strstr(mqtt_msg->topic, "data/service") || strstr(mqtt_msg->topic, "service"))
    {
        node = cJSON_Parse(mqtt_msg->payload);
        if (!node)
        {
            return E_FALSE;
        }
        GET_JSON_VALUE_INT(node, "mi", var->servInfo.mi);
        GET_JSON_VALUE_INT(node, "timestamp", var->servInfo.timestamp);
        GET_JSON_VALUE_STRING(node, "identifier", var->servInfo.identifier);
        GET_JSON_VALUE_STRING(node, "sn", var->servInfo.devSn);
        dbg_syslog(LOG_INFO, "mi:%d timestamp:%d identifier:%s sn:%s SERVICEUPCONT:%d\r\n", var->servInfo.mi,var->servInfo.timestamp,var->servInfo.identifier,var->servInfo.devSn,SERVICEUPCONT);
        if (var->runMode == E_ONGW_MODE)
        {
            GET_JSON_VALUE_DY_STRING_LOG(node, "tag_node", tagNode);
            if (tagNode != NULL)
            {
                sub = cJSON_Parse(tagNode);
            }
        }
        else
        {
            sub = cJSON_GetObjectItemCaseSensitive(node, "tags"); // todo
        }
        service_analy_proc(var, sub);
        // if (tagNode != NULL)
        // {
        //     sub = cJSON_Parse(tagNode);
        //     if (sub)
        //     {
        //         for (i = 0; i < SERVICEUPCONT; i++)
        //         {
        //             //  dbg_syslog(LOG_INFO, "i:%d identifier:%s name:%s",i,SERVICE_UP[i].identifier,SERVICE_UP[i].name);
        //             if (strcmp(SERVICE_UP[i].identifier, var->servInfo.identifier) == 0)
        //             {
        //                 for (j = 0; j < var->devNodeInfo.devcont; j++)
        //                 {
        //                     if (strcmp(var->devNodeInfo.pdevnodecfg[j].devSn, var->servInfo.devSn) == 0)
        //                     {
        //                         if (SERVICE_UP[i].tagNode.nodecont > 0)
        //                         {
        //                             for (n = 0; n < SERVICE_UP[i].tagNode.nodecont; n++)
        //                             {
        //                                 tmp = -1;
        //                                 // GET_JSON_VALUE_INT_LOG(sub, SERVICE_UP[i].tagNode.ptagNode[n].tag, tmp);
        //                                 GET_JSON_VALUE_DOUBLE_LOG(sub, SERVICE_UP[i].tagNode.ptagNode[n].tag, tmp)
        //                                 if (tmp != -1)
        //                                 {
        //                                     if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "soc") == 0)
        //                                     {
        //                                         var->devNodeInfo.pdevnodecfg[j].essBms.soc = tmp * 10;
        //                                         ess_bms_report_soc(var, SERVICE_UP[i].inidentifier);
        //                                     }
        //                                     else if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "bmsalarm") == 0)
        //                                     {
        //                                         var->devNodeInfo.pdevnodecfg[j].essBms.alarm = tmp;
        //                                         ess_bms_report_bmsalarm(var, SERVICE_UP[i].inidentifier);
        //                                     }
        //                                 }
        //                             }
        //                         }
        //                         break;
        //                     }
        //                 }
        //                 // break;
        //             }
        //         }
        //     }
        //     free(tagNode);
        // }
    }
    if (node)
    {
        cJSON_Delete(node);
    }
    if (var->runMode == E_ONGW_MODE)
    {
        if (sub)
        {
            cJSON_Delete(sub);
        }
    }
    if (tagNode)
    {
        free(tagNode);
    }
    return 0;
}

static void ess_bms_subscribe_all(ess_bms_var_t *var)
{
    CHAR topic[TOPIC_MAX_LEN] = {0};
    int i, j;
    // ipc/[GW_SN]/+/device/+/data/raw_data 上行
    // ipc/[GW_SN]/[PORT]/device/[DEV_SN]/data/set_rglt_raw 发送原始数据指令
    // ipc/[GW_SN]/[PORT]/device/[DEV_SN]/data/service/[identifier] 订阅周期性上报的数据  电表功率，负载电表功率，pcs电表功率，pcs告警信息

    // snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/+/device/+/data/service/+", var->sn_str);
    // dbg_syslog(LOG_INFO, "topic:%s\r\n", topic);
    // ipc_session_subscribe(var->session, topic);
    if (var->runMode == E_ONGW_MODE)
    {
        for (i = 0; i < var->devNodeInfo.devcont; i++)
        {
            for (j = 0; j < var->devNodeInfo.serviceupcont; j++)
            {
                snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/+/device/%s/data/service/%s", var->sn_str, var->devNodeInfo.pdevnodecfg[i].devSn, var->devNodeInfo.pserviceInfoUP[j].identifier);
                dbg_syslog(LOG_INFO, "topic:%s TOPIC_MAX_LEN:%d len:%d", topic, TOPIC_MAX_LEN, strlen(topic));
                ipc_session_subscribe(var->session, topic);
            }
        }
    }
    else
    {
        for (i = 0; i < var->devNodeInfo.devcont; i++)
        {
            // for (j = 0; j < var->devNodeInfo.serviceupcont; j++)
            // {
            snprintf(topic, TOPIC_MAX_LEN, "/ems/%s/service", var->devNodeInfo.pdevnodecfg[i].devSn);
            dbg_syslog(LOG_INFO, "topic:%s TOPIC_MAX_LEN:%d len:%d", topic, TOPIC_MAX_LEN, strlen(topic));
            ipc_session_subscribe(var->session, topic);
            // }
        }
    }
}

static int ess_bms_mqtt_client_init(ess_bms_var_t *var)
{
    char clientId[MAX_CLIENT_ID_LEN] = {0};

    snprintf(clientId, MAX_CLIENT_ID_LEN, "INT_ess_bms_%s", var->sn_str);
    if (var->runMode == E_ONGW_MODE)
    {
        var->session = ipc_session_new(clientId, (void *)var, IPC_DEFAULT);
        if (var->session == NULL)
            return -1;
        ipc_session_set_callbacks(var->session, ess_bms_mqtt_handle_recv_msg, ess_bms_state_change);
        ess_bms_subscribe_all(var);
        ipc_session_start(var->session);
    }
    else
    {
        var->insession = ipc_session_new(clientId, (void *)var, IPC_DEFAULT);
        if (var->insession == NULL)
            return -1;
        ipc_session_start(var->insession);

        var->session = ipc_session_new(clientId, (void *)var, IPC_DEFAULT);
        dbg_syslog(LOG_INFO, "hostname:%s port:%d username:%s password:%s", var->mqttBroker.hostname, var->mqttBroker.port, var->mqttBroker.username, var->mqttBroker.password);
        ipc_session_set_address(var->session, var->mqttBroker.hostname, var->mqttBroker.port, var->mqttBroker.username, var->mqttBroker.password);
        ipc_session_set_opts(var->session, MQTT_QOS_LEVLE0, KEEP_ALIVE_MAX);
        ipc_session_set_callbacks(var->session, ess_bms_mqtt_handle_recv_msg, ess_bms_state_change);
        ess_bms_subscribe_all(var);
        ipc_session_start(var->session);
    }

    return E_TRUE;
}

static int load_ess_bms_cfg(ess_bms_var_t *var, const char *cfg_file)
{
    CHAR *pdata = NULL;
    cJSON *root = NULL;
    cJSON *nodes = NULL;
    cJSON *node = NULL;
    cJSON *tmp = NULL;
    int node_cnt = 0, i = 0;
    BYTE flag = E_TRUE;

    if (var == NULL || cfg_file == NULL)
    {
        dbg_syslog(LOG_ERR, "pcfg:%p cfg_file:%p", var, cfg_file);
        return -1;
    }
    pdata = read_file_data(cfg_file);

    if (pdata == NULL)
    {
        dbg_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        flag = E_FALSE;
        goto out;
    }
    root = cJSON_Parse(pdata);
    if (!root)
    {
        dbg_syslog(LOG_ERR, "parse cfg file %s error", cfg_file);
        flag = E_FALSE;
        goto out;
    }
    GET_JSON_VALUE_STRING_LOG(root, "devSn", var->vir_sn_str);
    GET_JSON_VALUE_STRING_LOG(root, "desSn", var->desSn);
    GET_JSON_VALUE_INT_LOG(root, "runMode", var->runMode);
    GET_JSON_VALUE_INT_LOG(root, "socAverage", var->socAverage);
    if (var->runMode == E_ONIOTBOX_MODE)
    {
        nodes = cJSON_GetObjectItemCaseSensitive(root, "mqtt_broker");
        if (!nodes)
        {
            dbg_syslog(LOG_ERR, "get mqtt_broker failed");
            flag = E_FALSE;
            goto out;
        }
        GET_JSON_VALUE_STRING_LOG(nodes, "host", var->mqttBroker.hostname);
        GET_JSON_VALUE_STRING_LOG(nodes, "user", var->mqttBroker.username);
        GET_JSON_VALUE_STRING_LOG(nodes, "passwd", var->mqttBroker.password);
        GET_JSON_VALUE_INT_LOG(nodes, "port", var->mqttBroker.port);
    }

    nodes = cJSON_GetObjectItemCaseSensitive(root, "node");
    if (!nodes)
    {
        dbg_syslog(LOG_ERR, "get node failed");
        flag = E_FALSE;
        goto out;
    }

    node_cnt = cJSON_GetArraySize(nodes);
    if (node_cnt != 0)
    {
        var->devNodeInfo.pdevnodecfg = (DEV_NODE_CFG_T *)malloc(node_cnt * sizeof(DEV_NODE_CFG_T));

        if (var->devNodeInfo.pdevnodecfg == NULL)
        {
            dbg_syslog(LOG_ERR, "malloc pdevnodcfg failed,node_cnt:%d", node_cnt);
            flag = E_FALSE;
            goto out;
        }
        memset(var->devNodeInfo.pdevnodecfg, 0, node_cnt * sizeof(DEV_NODE_CFG_T));
        var->devNodeInfo.devcont = node_cnt;
        for (i = 0; i < node_cnt; i++)
        {
            node = cJSON_GetArrayItem(nodes, i);
            GET_JSON_VALUE_STRING_LOG(node, "devSn", var->devNodeInfo.pdevnodecfg[i].devSn);
            GET_JSON_VALUE_STRING_LOG(node, "type", var->devNodeInfo.pdevnodecfg[i].type);
        }
    }
    nodes = cJSON_GetObjectItemCaseSensitive(root, "service_down");
    if (!nodes)
    {
        dbg_syslog(LOG_ERR, "get service_down failed");
        flag = E_FALSE;
        goto out;
    }
    node_cnt = cJSON_GetArraySize(nodes);
    if (node_cnt != 0)
    {
        var->devNodeInfo.pserviceInfoDOWN = (SERVICE_INFO_T *)malloc(node_cnt * sizeof(SERVICE_INFO_T));
        if (var->devNodeInfo.pserviceInfoDOWN == NULL)
        {
            dbg_syslog(LOG_ERR, "malloc pserviceInfoDOWN failed,node_cnt:%d", node_cnt);
            flag = E_FALSE;
            goto out;
        }
        var->devNodeInfo.servicedowncont = node_cnt;
        for (i = 0; i < node_cnt; i++)
        {
            node = cJSON_GetArrayItem(nodes, i);
            GET_JSON_VALUE_STRING_LOG(node, "identifier", var->devNodeInfo.pserviceInfoDOWN[i].identifier);
            GET_JSON_VALUE_STRING_LOG(node, "name", var->devNodeInfo.pserviceInfoDOWN[i].name);
        }
        // for (i = 0; i < node_cnt; i++)
        // {
        // dbg_syslog(LOG_ERR, "i:%d identifier:%s name:%s",i,SERVICE_DOWN[i].identifier,SERVICE_DOWN[i].name);
        // }
    }
    nodes = cJSON_GetObjectItemCaseSensitive(root, "service_up");
    if (!nodes)
    {
        dbg_syslog(LOG_ERR, "get service_up failed");
        flag = E_FALSE;
        goto out;
    }
    node_cnt = cJSON_GetArraySize(nodes);
    if (node_cnt != 0)
    {
        var->devNodeInfo.pserviceInfoUP = (SERVICE_INFO_T *)malloc(node_cnt * sizeof(SERVICE_INFO_T));

        if (var->devNodeInfo.pserviceInfoUP == NULL)
        {
            dbg_syslog(LOG_ERR, "malloc pserviceInfoDOWN failed,node_cnt:%d", node_cnt);
            flag = E_FALSE;
            goto out;
        }
        memset(var->devNodeInfo.pserviceInfoUP, 0, node_cnt * sizeof(SERVICE_INFO_T));
        var->devNodeInfo.serviceupcont = node_cnt;
        for (i = 0; i < node_cnt; i++)
        {
            node = cJSON_GetArrayItem(nodes, i);
            GET_JSON_VALUE_STRING_LOG(node, "identifier", var->devNodeInfo.pserviceInfoUP[i].identifier);
            GET_JSON_VALUE_STRING_LOG(node, "inidentifier", var->devNodeInfo.pserviceInfoUP[i].inidentifier);
            GET_JSON_VALUE_STRING_LOG(node, "name", var->devNodeInfo.pserviceInfoUP[i].name);
            {
                int j, tagcon = 0;
                cJSON *tagnodes = NULL;
                cJSON *tagnode = NULL;
                tagnodes = cJSON_GetObjectItemCaseSensitive(node, "tagnode");
                if (!tagnode)
                {
                    // todo 是否需要判断加载失败退出
                    tagcon = cJSON_GetArraySize(tagnodes);
                    dbg_syslog(LOG_ERR, "tagcon:%d", tagcon);
                    var->devNodeInfo.pserviceInfoUP[i].tagNode.ptagNode = (TAG_NODE_T *)malloc(tagcon * sizeof(TAG_NODE_T));
                    if (var->devNodeInfo.pserviceInfoUP[i].tagNode.ptagNode == NULL)
                    {
                        flag = E_FALSE;
                        goto out;
                    }
                    var->devNodeInfo.pserviceInfoUP[i].tagNode.nodecont = tagcon;
                    for (j = 0; j < tagcon; j++)
                    {
                        tagnode = cJSON_GetArrayItem(tagnodes, j);
                        GET_JSON_VALUE_STRING_LOG(tagnode, "tag", var->devNodeInfo.pserviceInfoUP[i].tagNode.ptagNode[j].tag);
                        GET_JSON_VALUE_STRING_LOG(tagnode, "name", var->devNodeInfo.pserviceInfoUP[i].tagNode.ptagNode[j].name);
                    }
                }
            }
        }
        // for (i = 0; i < node_cnt; i++)
        // {
        //     dbg_syslog(LOG_ERR, "i:%d identifier:%s name:%s",i,SERVICE_UP[i].identifier,SERVICE_UP[i].name);
        // }
    }

out:
    cJSON_Delete(root);
    if (pdata != NULL)
    {
        free(pdata);
    }
    if (flag == E_FALSE)
    {
        if (var->devNodeInfo.pdevnodecfg != NULL)
        {
            free(var->devNodeInfo.pdevnodecfg);
        }
        if (var->devNodeInfo.pserviceInfoDOWN != NULL)
        {
            free(var->devNodeInfo.pserviceInfoDOWN);
        }
    }
    return 0;
}

static void ess_bms_init(void *obj)
{
    ess_bms_var_t *var = (ess_bms_var_t *)obj;
    load_ess_bms_cfg(var, ESS_BMS_CFGFILE);
    get_board_sn(var->sn_str); //所有表信息;meter  sn
    dbg_syslog(LOG_INFO, "board SN:%s", var->sn_str);
    ess_bms_mqtt_client_init(var);
}

static void ess_bms_entry(void *obj)
{
    int ret = -1, maxfd;
    fd_set rset;
    struct timeval timeout;

    while (1)
    {
        SELECT_INIT();
        // SELECT_ADD_FD(var->second_period_timer);
        timeout.tv_usec = 0;
        timeout.tv_sec = 5;
        ret = select(maxfd + 1, &rset, 0, 0, &timeout);
        if (ret < 0)
        {
            dbg_syslog(LOG_INFO, "errno %d\n", errno);

            if (errno == EINTR)
            {
                continue;
            }
            else
            {
                dbg_syslog(LOG_INFO, "errno---");
                break;
            }
        }
    }
}

void main()
{
    ess_bms_var_t ess_bms_var = {0};
    lnxall_loglevel_set(LNXALL_LOGNOTICE,1);
    ess_bms_init(&ess_bms_var);
    ess_bms_entry(&ess_bms_var);
}