#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 "load_meter.h"

// #undef 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

#define SERVICEUPCONT var->devNodeInfo.serviceupcont
#define SERVICEDOWNCONT var->devNodeInfo.servicedowncont
#define SERVICE_DOWN var->devNodeInfo.pserviceInfoDOWN
#define SERVICE_UP var->devNodeInfo.pserviceInfoUP

#define LOAD_METER_CFGFILE "/app/config/ems/load_meter.json"
// #define LOAD_METER_CFGFILE "load_meter.json"
static int load_meter_state_change(void *obj, int state)
{
    load_meter_var_t *var = (load_meter_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, "load_meter");
        ipc_session_publish(var->session, topic, "", 0);
        break;
    }
    return E_TRUE;
}

#define PCS_MI 12323

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_INFO, "topic:%s", topic);
    ipc_session_publish(session, topic, data, len);
    return 0;
}
#define POWER_MAX_VAL 1000

static int load_meter_report_av(load_meter_var_t *var, CHAR *identifier, BYTE type)
{
    CHAR *data_tmp = NULL;
    int i;
    double power = 0;
    cJSON *sub = NULL;
    CHAR tagNode[64] = {0};
    cJSON *tag_data = cJSON_CreateObject();
    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, "{\"AVflag\":%d}", type);
    cJSON_AddStringToObject(tag_data, "tag_node", tagNode);
    // sub = cJSON_CreateObject();
    // cJSON_AddItemToObject(tag_data, "tags", sub);
    // cJSON_AddNumberToObject(sub, "p3", power);
    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 load_meter_report_power(load_meter_var_t *var, CHAR *identifier)
{
    CHAR *data_tmp = NULL;
    int i;
    double power = 0;
    cJSON *sub = NULL;
    CHAR tagNode[64] = {0};
    cJSON *tag_data = cJSON_CreateObject();
    if (var->loadMode == E_LOAD_ALONE)
    {
        for (i = 0; i < var->devNodeInfo.devcont; i++)
        {
            if (strcmp(var->devNodeInfo.pdevnodecfg[i].type, "load") == 0)
            {
                power += var->devNodeInfo.pdevnodecfg[i].loadMeter.p3;
                dbg_syslog(LOG_INFO, "i:>%d,send power:%f", i, var->devNodeInfo.pdevnodecfg[i].loadMeter.p3);
            }
        }
    }
    else
    {
        for (i = 0; i < var->devNodeInfo.devcont; i++)
        {
            if (strcmp(var->devNodeInfo.pdevnodecfg[i].type, "grid") == 0)
            {
                power += var->devNodeInfo.pdevnodecfg[i].loadMeter.p1;
                dbg_syslog(LOG_INFO, "i:>%d,send power:%f", i, var->devNodeInfo.pdevnodecfg[i].loadMeter.p1);
            }
            else if (strcmp(var->devNodeInfo.pdevnodecfg[i].type, "bms") == 0)
            {
                power -= var->devNodeInfo.pdevnodecfg[i].loadMeter.p2;
                dbg_syslog(LOG_INFO, "i:>%d,send power:%f", i, var->devNodeInfo.pdevnodecfg[i].loadMeter.p2);
            }
        }
    }

    if (var->Distribution)
    {
        power = power / var->Distribution;
    }

    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, "{\"p3\":%f}", power);
    cJSON_AddStringToObject(tag_data, "tag_node", tagNode);
    // sub = cJSON_CreateObject();
    // cJSON_AddItemToObject(tag_data, "tags", sub);
    // cJSON_AddNumberToObject(sub, "p3", power);
    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 load_meter_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;
    load_meter_var_t *var = (load_meter_var_t *)obj;
    dbg_syslog(LOG_INFO, "topic:%s", mqtt_msg->topic);
    if (var->runMode == E_ONGW_MODE)
    {

        if (strstr(mqtt_msg->topic, "data/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);
            // sub = cJSON_GetObjectItemCaseSensitive(node, "tags");
            GET_JSON_VALUE_DY_STRING(node, "tag_node", tagNode);
            dbg_syslog(LOG_INFO, "mi:%d timestamp:%d identifier:%s sn:%s SERVICEUPCONT:%d tagNode:%s\r\n", var->servInfo.mi,var->servInfo.timestamp,var->servInfo.identifier,var->servInfo.devSn,SERVICEUPCONT,tagNode);
            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 = POWER_MAX_VAL;
                                            // 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 != POWER_MAX_VAL)
                                            {
                                                if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "p3") == 0)
                                                {
                                                    if (strcmp(var->devNodeInfo.pdevnodecfg[j].type, "grid") == 0)
                                                    {
                                                        var->devNodeInfo.pdevnodecfg[j].loadMeter.p1 = tmp;
                                                    }
                                                    else if (strcmp(var->devNodeInfo.pdevnodecfg[j].type, "bms") == 0)
                                                    {
                                                        var->devNodeInfo.pdevnodecfg[j].loadMeter.p2 = tmp;
                                                    }
                                                    else
                                                    {
                                                        var->devNodeInfo.pdevnodecfg[j].loadMeter.p3 = tmp;
                                                    }
                                                    load_meter_report_power(var, SERVICE_UP[i].inidentifier);
                                                }
                                                else if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "AV") == 0)
                                                {
                                                    if (var->devNodeInfo.pdevnodecfg[j].avcheck)
                                                    {
                                                        if (var->devNodeInfo.pdevnodecfg[j].loadMeter.number == 0)
                                                        {
                                                            var->devNodeInfo.pdevnodecfg[j].loadMeter.av1 = tmp;
                                                            var->devNodeInfo.pdevnodecfg[j].loadMeter.number++;
                                                        }
                                                        else
                                                        {
                                                            var->devNodeInfo.pdevnodecfg[j].loadMeter.av2 = tmp;
                                                            var->devNodeInfo.pdevnodecfg[j].loadMeter.number = 0;
                                                            if (var->devNodeInfo.pdevnodecfg[j].loadMeter.av1 == 0 && var->devNodeInfo.pdevnodecfg[j].loadMeter.av2 == 0)
                                                            {
                                                                if (var->devNodeInfo.pdevnodecfg[j].loadMeter.flag)
                                                                {
                                                                    var->devNodeInfo.pdevnodecfg[j].loadMeter.flag = 0;
                                                                    load_meter_report_av(var, SERVICE_UP[i].inidentifier, 0);
                                                                }
                                                            }
                                                            else if (var->devNodeInfo.pdevnodecfg[j].loadMeter.av1 > 0 && var->devNodeInfo.pdevnodecfg[j].loadMeter.av2 > 0)
                                                            {
                                                                if (!var->devNodeInfo.pdevnodecfg[j].loadMeter.flag)
                                                                {
                                                                    var->devNodeInfo.pdevnodecfg[j].loadMeter.flag = 1;
                                                                    load_meter_report_av(var, SERVICE_UP[i].inidentifier, 1);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
                free(tagNode);
            }
        }
        if (node)
        {
            cJSON_Delete(node);
        }
        if (sub)
        {
            cJSON_Delete(sub);
        }
    }
    else
    {
        if (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, "time", 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);


            sub = cJSON_GetObjectItemCaseSensitive(node, "tags");
            // GET_JSON_VALUE_DY_STRING_LOG(node, "tags", tagNode);
            // 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 = POWER_MAX_VAL;
                                        // 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 != POWER_MAX_VAL)
                                        {
                                            if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "p3") == 0)
                                            {
                                                if (strcmp(var->devNodeInfo.pdevnodecfg[j].type, "grid") == 0)
                                                {
                                                    var->devNodeInfo.pdevnodecfg[j].loadMeter.p1 = tmp;
                                                }
                                                else if (strcmp(var->devNodeInfo.pdevnodecfg[j].type, "bms") == 0)
                                                {
                                                    var->devNodeInfo.pdevnodecfg[j].loadMeter.p2 = tmp;
                                                }
                                                else
                                                {
                                                    var->devNodeInfo.pdevnodecfg[j].loadMeter.p3 = tmp;
                                                }
                                                load_meter_report_power(var, SERVICE_UP[i].inidentifier);
                                            }
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
            }
            //     free(tagNode);
            // }
        }
        if (node)
        {
            cJSON_Delete(node);
        }
    }
    return 0;
}

static void load_meter_subscribe_all(load_meter_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++)
            {
                if ((strcmp(var->devNodeInfo.pdevnodecfg[i].type, "avcheck") == 0) && (strcmp(var->devNodeInfo.pserviceInfoUP[j].name, "AV") == 0))
                {
                    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\r\n", topic);
                    ipc_session_subscribe(var->session, topic);
                }else if((strcmp(var->devNodeInfo.pdevnodecfg[i].type, "avcheck") != 0) && (strcmp(var->devNodeInfo.pserviceInfoUP[j].name, "p3") == 0))
                {
                    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\r\n", topic);
                    ipc_session_subscribe(var->session, topic);
                }
            }
        }
    }
    else if (var->runMode == E_ONIOTBOX_MODE)
    {
        for (i = 0; i < var->devNodeInfo.devcont; i++)
        {
            // snprintf(topic, TOPIC_MAX_LEN, "/ems/%s/service", var->devNodeInfo.pdevnodecfg[i].devSn);  --test
            // snprintf(topic, TOPIC_MAX_LEN, "/sys/%s/device/%s/data/service/+", var->devNodeInfo.pdevnodecfg[i].devGwSn, var->devNodeInfo.pdevnodecfg[i].rmGwSn);
            snprintf(topic, TOPIC_MAX_LEN, "/ems/%s/service", var->devNodeInfo.pdevnodecfg[i].rmGwSn);
            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 load_meter_mqtt_client_init(load_meter_var_t *var)
{
    char clientId[MAX_CLIENT_ID_LEN] = {0};
    snprintf(clientId, MAX_CLIENT_ID_LEN, "INT_load_meter_%s", var->sn_str);
    if (var->runMode == E_ONGW_MODE)
    {
        var->session = ipc_session_new(clientId, (void *)var, IPC_DEFAULT);
        // var->session = ipc_session_new(clientId, (void *)var, IPC_NNG);
        if (var->session == NULL)
        {
            dbg_syslog(LOG_INFO, "runMode session create null\r\n");
            return -1;
        }
        ipc_session_set_callbacks(var->session, load_meter_mqtt_handle_recv_msg, load_meter_state_change);
        load_meter_subscribe_all(var);
        ipc_session_start(var->session);
    }
    else if (var->runMode == E_ONIOTBOX_MODE)
    {
        var->insession = ipc_session_new(clientId, (void *)var, IPC_DEFAULT);
        if (var->insession == NULL)
        {
            dbg_syslog(LOG_INFO, "runMode insession create null\r\n");
            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, load_meter_mqtt_handle_recv_msg, load_meter_state_change);
        load_meter_subscribe_all(var);
        ipc_session_start(var->session);
    }
    else
    {
        dbg_syslog(LOG_INFO, "runMode error:%d\r\n", var->runMode);
        return -1;
    }

    return E_TRUE;
}

static void pcs_dev_subscribe_all(load_meter_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);
    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\r\n", topic);
            ipc_session_subscribe(var->session, topic);
        }
    }
    // snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/+/device/+/data/set_rglt_raw", var->sn_str);
    // dbg_syslog(LOG_INFO, "topic:%s\r\n", topic);
    // ipc_session_subscribe(var->session, topic);
}

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

    snprintf(clientId, MAX_CLIENT_ID_LEN, "INT_pcs_dev_%s", var->sn_str);
    var->session = ipc_session_new(clientId, (void *)var, IPC_DEFAULT);
    // var->session = ipc_session_new(clientId, (void *)var, IPC_NNG);
    if (var->session == NULL)
        return -1;
    ipc_session_set_callbacks(var->session, load_meter_mqtt_handle_recv_msg, load_meter_state_change);
    pcs_dev_subscribe_all(var);
    ipc_session_start(var->session);
    return E_TRUE;
}

static int load_meter_cfg(load_meter_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, "loadMode", var->loadMode);
    GET_JSON_VALUE_INT_LOG(root, "distri", var->Distribution);
    GET_JSON_VALUE_INT_LOG(root, "cont", var->ContNum);
    GET_JSON_VALUE_INT_LOG(root, "runMode", var->runMode);
    if (var->runMode != E_ONGW_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, "devGwSn", var->devNodeInfo.pdevnodecfg[i].devGwSn);
            GET_JSON_VALUE_STRING_LOG(node, "rmGwSn", var->devNodeInfo.pdevnodecfg[i].rmGwSn);
            GET_JSON_VALUE_INT_LOG(node, "avcheck", var->devNodeInfo.pdevnodecfg[i].avcheck);
            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;
        }
        var->devNodeInfo.serviceupcont = node_cnt;
        memset(var->devNodeInfo.pserviceInfoUP, 0, node_cnt * sizeof(SERVICE_INFO_T));
        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);
                        {
                            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);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
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 load_meter_init(void *obj)
{
    load_meter_var_t *var = (load_meter_var_t *)obj;
    load_meter_cfg(var, LOAD_METER_CFGFILE);
    get_board_sn(var->sn_str); //所有表信息;meter  sn
    dbg_syslog(LOG_INFO, "board SN:%s", var->sn_str);
    load_meter_mqtt_client_init(var);
}

static void load_meter_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()
{
    load_meter_var_t load_meter_var = {0};
    lnxall_loglevel_set(LNXALL_LOGNOTICE,1);
    load_meter_init(&load_meter_var);
    load_meter_entry(&load_meter_var);
}