

#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 <pthread.h>

#include "chargestation.h"

#include "mytimer.h"

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);
    dy_syslog(LOG_DEBUG, "topic:%s", topic);
    ipc_session_publish(session, topic, data, len);
    return 0;
}

static int publish_ext_data(chargestation_mng_var_t *var, ipc_session_t *session, unsigned char *data, int len, char *desSn, CHAR *option)
{
    char topic[TOPIC_MAX_LEN] = {0};
    // ipc/%s/+/device/+/data/set_rglt_raw
    snprintf(topic, TOPIC_MAX_LEN, CH_STATION_TOPIC_PREFIX "%s%s", desSn, option);
    dy_syslog(LOG_DEBUG, "topic:%s", topic);
    ipc_session_publish(session, topic, data, len);
    var->devNodeInfo.extsendcnt++;
    return 0;
}

static int publish_iot_data(unsigned char *gw, unsigned char *porttype, ipc_session_t *session, unsigned char *data, int len, char *desSn, CHAR *identifier)
{
    char topic[TOPIC_MAX_LEN] = {0};
    // ipc/21881B000003/MODBUS_TCP/device/21881B000003_PCS1/data_filtered/service/Read32_40Data1
    snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/%s/device/%s/data_filtered/service/%s", gw, porttype, desSn, identifier);
    dy_syslog(LOG_DEBUG, "topic:%s", topic);
    ipc_session_publish(session, topic, data, len);
    return 0;
}

#define PCS_MI 12323

#define EXT_JSON_PACK_START(type, sn)                           \
    CHAR *data_tmp = NULL;                                      \
    cJSON *tag_data = cJSON_CreateObject();                     \
    cJSON_AddStringToObject(tag_data, "sn", sn);                \
    cJSON_AddNumberToObject(tag_data, "timestamp", time(NULL)); \
    cJSON_AddStringToObject(tag_data, "identifier", type);

#define EXT_JSON_PACK_END(pvar, session, desSn, option)                         \
    data_tmp = cJSON_Print(tag_data);                                           \
    publish_ext_data(pvar, session, data_tmp, strlen(data_tmp), desSn, option); \
    free(data_tmp);                                                             \
    cJSON_Delete(tag_data);

#define IOT_JSON_PACK_START(type, sn)                          \
    CHAR *data_tmp = NULL;                                     \
    cJSON *sub;                                                \
    cJSON *tag_data = cJSON_CreateObject();                    \
    cJSON_AddStringToObject(tag_data, "sn", sn);               \
    cJSON_AddNumberToObject(tag_data, "time", time(NULL));     \
    cJSON_AddStringToObject(tag_data, "identifier", type);     \
    cJSON_AddNumberToObject(tag_data, "mi", var->servInfo.mi); \
    sub = cJSON_CreateObject();                                \
    cJSON_AddItemToObject(tag_data, "tags", sub);

#define IOT_JSON_PACK_END(session, porttype, desSn, identifier)                                      \
    data_tmp = cJSON_Print(tag_data);                                                                \
    publish_iot_data(var->sn_str, porttype, session, data_tmp, strlen(data_tmp), desSn, identifier); \
    free(data_tmp);                                                                                  \
    cJSON_Delete(tag_data);

#define PCS_JSON_PACK_START(type)                               \
    CHAR *data_tmp = NULL;                                      \
    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", type);      \
    cJSON_AddNumberToObject(tag_data, "mi", PCS_MI);

#define PCS_JSON_PACK_END(desSn, session, identifier)                                      \
    data_tmp = cJSON_Print(tag_data);                                                      \
    publish_pcs_data(session, var->sn_str, data_tmp, strlen(data_tmp), desSn, identifier); \
    free(data_tmp);                                                                        \
    cJSON_Delete(tag_data);

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

#define SERVICD_TODEVCONT var->devNodeInfo.servicetodevcont

#define SERVICE_TODEV var->devNodeInfo.pserviceInfoTodev

static int charge_station_cmd_send(chargestation_mng_var_t *var, CHAR *devSn, CHAR *identifier, CHAR *tagname, int val)
{
    cJSON *sub = NULL;
    EXT_JSON_PACK_START(identifier, devSn);
    sub = cJSON_CreateObject();
    cJSON_AddItemToObject(tag_data, "tags", sub);
    cJSON_AddNumberToObject(sub, tagname, val);
    EXT_JSON_PACK_END(var, var->session, devSn, CH_STATION_TOPIC_SET);
}

static int vir_charge_station_mqtt_handle_recv_msg(void *obj, ipc_msg_t *mqtt_msg)
{
    cJSON *node = NULL;
    cJSON *sub = NULL;
    CHAR *tagNode = NULL;
    int i, j, n = 0;
    int find = 0;
    int tmp = -1;
    chargestation_mng_var_t *var = (chargestation_mng_var_t *)obj;
    dy_syslog(LOG_INFO, "topic:%s", mqtt_msg->topic);
    node = cJSON_Parse(mqtt_msg->payload);
    if (!node)
    {
        return E_FALSE;
    }
    GET_JSON_VALUE_INT_LOG(node, "time", var->servInfo.timestamp);
    GET_JSON_VALUE_STRING_LOG(node, "identifier", var->servInfo.identifier);
    GET_JSON_VALUE_STRING_LOG(node, "sn", var->servInfo.devSn);
    dy_syslog(LOG_INFO, "SERVICEUPCONT:%d\r\n", SERVICEUPCONT);
    if (strstr(mqtt_msg->topic, TOPIC_EVT_SET_RGLT))
    {

        for (i = 0; i < SERVICEUPCONT; i++)
        {
            if (strcmp(SERVICE_UP[i].identifier, var->servInfo.identifier) == 0)
            {
                dy_syslog(LOG_INFO, "identifier:%s\r\n", SERVICE_UP[i].identifier);
                for (j = 0; j < var->devNodeInfo.devcont; j++)
                {
                    if (strcmp(var->devNodeInfo.pdevnodecfg[j].devSn, var->servInfo.devSn) == 0)
                    {
                        find = 1;
                        break;
                    }
                }
            }
            if (find)
                charge_station_info_report(var, i, j);
        }
        if (!find)
        {
            for (i = 0; i < SERVICD_TODEVCONT; i++)
            {
                if (strcmp(SERVICE_TODEV[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_TODEV[i].tagNode.nodecont > 0)
                            {
                                for (n = 0; n < SERVICE_TODEV[i].tagNode.nodecont; n++)
                                {
                                    GET_JSON_VALUE_INT_LOG(node, SERVICE_TODEV[i].tagNode.ptagNode[n].tag, tmp);
                                    if (tmp != -1)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].chargeStation.setpower = tmp;
                                        charge_station_cmd_send(var, var->servInfo.devSn, var->servInfo.identifier, SERVICE_TODEV[i].tagNode.ptagNode[n].name, tmp);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    else if (strstr(mqtt_msg->topic, "data/set_rglt_raw"))
    {
        GET_JSON_VALUE_INT_LOG(node, "time", var->servInfo.timestamp);
        GET_JSON_VALUE_INT_LOG(node, "mi", var->servInfo.mi);
        GET_JSON_VALUE_STRING_LOG(node, "identifier", var->servInfo.identifier);
        GET_JSON_VALUE_STRING_LOG(node, "sn", var->servInfo.devSn);

        for (i = 0; i < SERVICD_TODEVCONT; i++)
        {
            if (strcmp(SERVICE_TODEV[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_TODEV[i].tagNode.nodecont > 0)
                        {
                            for (n = 0; n < SERVICE_TODEV[i].tagNode.nodecont; n++)
                            {
                                GET_JSON_VALUE_INT_LOG(node, SERVICE_TODEV[i].tagNode.ptagNode[n].tag, tmp);
                                if (tmp != -1)
                                {
                                    var->devNodeInfo.pdevnodecfg[j].chargeStation.setpower = tmp;
                                    charge_station_cmd_send(var, var->servInfo.devSn, var->servInfo.identifier, SERVICE_TODEV[i].tagNode.ptagNode[n].name, tmp);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return E_TRUE;
}

static void charge_station_info_report(chargestation_mng_var_t *var, int i, int j)
{
    IOT_JSON_PACK_START(SERVICE_UP[i].identifier, var->devNodeInfo.pdevnodecfg[j].devSn)
    {
        int n;
        for (n = 0; n < SERVICE_UP[i].tagNode.nodecont; n++)
        {
            if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "realpower") == 0)
            {
                cJSON_AddNumberToObject(sub, SERVICE_UP[i].tagNode.ptagNode[n].tag, var->devNodeInfo.pdevnodecfg[j].chargeStation.realpower);
            }
            if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "expectpower") == 0)
            {
                cJSON_AddNumberToObject(sub, SERVICE_UP[i].tagNode.ptagNode[n].tag, var->devNodeInfo.pdevnodecfg[j].chargeStation.expectpower);
            }
        }
    }
    IOT_JSON_PACK_END(var->insession, var->devNodeInfo.pdevnodecfg[j].type, var->devNodeInfo.pdevnodecfg[j].devSn, SERVICE_UP[i].identifier);
}

static void charge_station_info_ems_report(chargestation_mng_var_t *var, int i, int j)
{
    CHAR tagNode[64] = {0};
    PCS_JSON_PACK_START(SERVICE_UP[i].inidentifier)
    sprintf(tagNode, "{\"realpower\":%d,\"expectpower\":%d}", var->devNodeInfo.pdevnodecfg[j].chargeStation.realpower, var->devNodeInfo.pdevnodecfg[j].chargeStation.expectpower);
    cJSON_AddStringToObject(tag_data, "tag_node", tagNode);
    if (var->runMode == E_ONIOTBOX_MODE)
    {
        PCS_JSON_PACK_END(var->desSn, var->insession, SERVICE_UP[i].inidentifier);
    }
    else
    {
        PCS_JSON_PACK_END(var->desSn, var->session, SERVICE_UP[i].inidentifier);
    }
}

static int charge_station_exmqtt_handle_recv_msg(void *obj, ipc_msg_t *mqtt_msg)
{
    cJSON *node = NULL;
    cJSON *sub = NULL;
    CHAR *tagNode = NULL;
    int i, n, j = 0;
    int tmp = 0;
    chargestation_mng_var_t *var = (chargestation_mng_var_t *)obj;
    var->devNodeInfo.extreceivecnt++;
    dy_syslog(LOG_INFO, "topic:%s", mqtt_msg->topic);
    node = cJSON_Parse(mqtt_msg->payload);
    if (!node)
    {
        return E_FALSE;
    }
    if (strstr(mqtt_msg->topic, "get/reply"))
    {
        // GET_JSON_VALUE_INT_LOG(node, "mi", var->servInfo.mi);
        GET_JSON_VALUE_INT_LOG(node, "time", var->servInfo.timestamp);
        GET_JSON_VALUE_STRING_LOG(node, "identifier", var->servInfo.identifier);
        GET_JSON_VALUE_STRING_LOG(node, "sn", var->servInfo.devSn);
        dy_syslog(LOG_INFO, "SERVICEUPCONT:%d\r\n", SERVICEUPCONT);
        sub = cJSON_GetObjectItemCaseSensitive(node, "tags");
        if (sub)
        {
            for (i = 0; i < SERVICEUPCONT; i++)
            {
                if (strcmp(SERVICE_UP[i].identifier, var->servInfo.identifier) == 0)
                {
                    dy_syslog(LOG_INFO, "identifier:%s\r\n", SERVICE_UP[i].identifier);
                    for (j = 0; j < var->devNodeInfo.devcont; j++)
                    {
                        if (strcmp(var->devNodeInfo.pdevnodecfg[j].devSn, var->servInfo.devSn) == 0)
                        {
                            dy_syslog(LOG_INFO, "devSn:%s nodecont:%d\r\n", var->devNodeInfo.pdevnodecfg[j].devSn, SERVICE_UP[i].tagNode.nodecont);
                            if (SERVICE_UP[i].tagNode.nodecont > 0)
                            {
                                for (n = 0; n < SERVICE_UP[i].tagNode.nodecont; n++)
                                {
                                    GET_JSON_VALUE_INT_LOG(sub, SERVICE_UP[i].tagNode.ptagNode[n].name, tmp);
                                    if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "expectpower") == 0)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].chargeStation.expectpower = tmp;
                                    }
                                    if (strcmp(SERVICE_UP[i].tagNode.ptagNode[n].name, "realpower") == 0)
                                    {
                                        var->devNodeInfo.pdevnodecfg[j].chargeStation.realpower = tmp;
                                    }
                                }
                            }
                            charge_station_info_report(var, i, j);
                            charge_station_info_ems_report(var, i, j);
                            break;
                        }
                    }
                }
            }
        }
    }
    else if (strstr(mqtt_msg->topic, "set/reply"))
    {
    }
    else
    {
        dy_syslog(LOG_INFO, "topic error");
    }
    if (node)
    {
        cJSON_Delete(node);
    }
    return E_TRUE;
}
static void chstation_subscribe_all(chargestation_mng_var_t *var, ipc_session_t *psession)
{
    CHAR topic[TOPIC_MAX_LEN] = {0};
    int i, j;
    snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/+/device/%s/data/set_rglt_raw", var->sn_str, var->vir_sn_str);
    dy_syslog(LOG_INFO, "topic:%s\r\n", topic);
    ipc_session_subscribe(psession, topic);
    // snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/%s/device/%s/data/%s", var->sn_str, var->port_type, var->vir_sn_str, TOPIC_EVT_SET_RGLT);
    // dy_syslog(LOG_INFO, "topic:%s\r\n", topic);
    // ipc_session_subscribe(psession, topic);
    for (i = 0; i < var->devNodeInfo.devcont; i++)
    {
        snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/%s/device/%s/data/%s", var->sn_str, var->devNodeInfo.pdevnodecfg[i].type, var->devNodeInfo.pdevnodecfg[i].devSn, TOPIC_EVT_SET_RGLT);
        dy_syslog(LOG_INFO, "topic:%s\r\n", topic);
        ipc_session_subscribe(psession, topic);
    }
}

static void chstation_exsubscribe_all(chargestation_mng_var_t *var, ipc_session_t *psession)
{
    CHAR topic[TOPIC_MAX_LEN] = {0};
    int i, j;
    for (i = 0; i < var->devNodeInfo.devcont; i++)
    {
        snprintf(topic, TOPIC_MAX_LEN, CH_STATION_TOPIC_PREFIX "%s" CH_STATION_TOPIC_GET CH_STATION_TOPIC_REPLY, var->devNodeInfo.pdevnodecfg[i].devSn);
        dy_syslog(LOG_INFO, "topic:%s TOPIC_MAX_LEN:%d len:%d", topic, TOPIC_MAX_LEN, strlen(topic));
        ipc_session_subscribe(psession, topic);
        snprintf(topic, TOPIC_MAX_LEN, CH_STATION_TOPIC_PREFIX "%s" CH_STATION_TOPIC_SET CH_STATION_TOPIC_REPLY, var->devNodeInfo.pdevnodecfg[i].devSn);
        dy_syslog(LOG_INFO, "topic:%s TOPIC_MAX_LEN:%d len:%d", topic, TOPIC_MAX_LEN, strlen(topic));
        ipc_session_subscribe(psession, topic);
    }
}

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

    snprintf(clientId, MAX_CLIENT_ID_LEN, "INT_chargestation_%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)
            return -1;
        ipc_session_set_callbacks(var->session, vir_charge_station_mqtt_handle_recv_msg, NULL);
        chstation_subscribe_all(var, var->session);
        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)
            return -1;
        ipc_session_set_callbacks(var->insession, vir_charge_station_mqtt_handle_recv_msg, NULL);
        chstation_subscribe_all(var, var->insession);
        ipc_session_start(var->insession);
        var->session = ipc_session_new(clientId, (void *)var, IPC_DEFAULT);
        dy_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, charge_station_exmqtt_handle_recv_msg, NULL);
        chstation_exsubscribe_all(var, var->session);
        ipc_session_start(var->session);
    }
    return E_TRUE;
}

static void charge_second_period_poll(chargestation_mng_var_t *var)
{
    mytimer_loop();
}

static void charge_station_dev_entry(chargestation_mng_var_t *var)
{
    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)
        {
            dy_syslog(LOG_INFO, "errno %d\n", errno);

            if (errno == EINTR)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else if (ret > 0)
        {
            if (var->second_period_timer > 0 && FD_ISSET(var->second_period_timer, &rset))
            {
                FD_CLR(var->second_period_timer, &rset);
                EMS_TIMER_CONFIRM(var->second_period_timer);

                charge_second_period_poll(var);
            }
        }
    }
}

static int load_charge_station_dev_cfg(chargestation_mng_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)
    {
        dy_syslog(LOG_ERR, "pcfg:%p charge_staton:%p", var, cfg_file);
        return -1;
    }
    pdata = read_file_data(cfg_file);

    if (pdata == NULL)
    {
        dy_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        flag = E_FALSE;
        goto out;
    }
    root = cJSON_Parse(pdata);
    if (!root)
    {
        dy_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);

    if (var->runMode != E_ONGW_MODE)
    {
        nodes = cJSON_GetObjectItemCaseSensitive(root, "mqtt_broker");
        if (!nodes)
        {
            dy_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)
    {
        dy_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)
        {
            dy_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)
    {
        dy_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)
        {
            dy_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++)
        // {
        // dy_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)
    {
        dy_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)
        {
            dy_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);
            GET_JSON_VALUE_INT_LOG(node, "period", var->devNodeInfo.pserviceInfoUP[i].period);
            {
                int j, tagcon = 0;
                cJSON *tagnodes = NULL;
                cJSON *tagnode = NULL;
                tagnodes = cJSON_GetObjectItemCaseSensitive(node, "tagnode");
                if (tagnodes)
                {
                    // todo 是否需要判断加载失败退出
                    tagcon = cJSON_GetArraySize(tagnodes);
                    dy_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);
                    }
                }
            }
        }
        //
        nodes = cJSON_GetObjectItemCaseSensitive(root, "service_todev");
        if (!nodes)
        {
            dy_syslog(LOG_ERR, "get service_todev failed");
            flag = E_FALSE;
            goto out;
        }
        node_cnt = cJSON_GetArraySize(nodes);
        if (node_cnt != 0)
        {
            var->devNodeInfo.pserviceInfoTodev = (SERVICE_INFO_T *)malloc(node_cnt * sizeof(SERVICE_INFO_T));
            if (var->devNodeInfo.pserviceInfoTodev == NULL)
            {
                dy_syslog(LOG_ERR, "malloc pserviceInfoDOWN failed,node_cnt:%d", node_cnt);
                flag = E_FALSE;
                goto out;
            }
            var->devNodeInfo.servicetodevcont = node_cnt;

            for (i = 0; i < node_cnt; i++)
            {
                node = cJSON_GetArrayItem(nodes, i);
                GET_JSON_VALUE_STRING_LOG(node, "identifier", var->devNodeInfo.pserviceInfoTodev[i].identifier);
                GET_JSON_VALUE_STRING_LOG(node, "name", var->devNodeInfo.pserviceInfoTodev[i].name);
                {
                    int j, tagcon = 0;
                    cJSON *tagnodes = NULL;
                    cJSON *tagnode = NULL;
                    tagnodes = cJSON_GetObjectItemCaseSensitive(node, "tagnode");
                    if (!tagnode)
                    {
                        // todo 是否需要判断加载失败退出
                        tagcon = cJSON_GetArraySize(tagnodes);
                        dy_syslog(LOG_ERR, "tagcon:%d", tagcon);
                        var->devNodeInfo.pserviceInfoTodev[i].tagNode.ptagNode = (TAG_NODE_T *)malloc(tagcon * sizeof(TAG_NODE_T));
                        if (var->devNodeInfo.pserviceInfoTodev[i].tagNode.ptagNode == NULL)
                        {
                            flag = E_FALSE;
                            goto out;
                        }
                        var->devNodeInfo.pserviceInfoTodev[i].tagNode.nodecont = tagcon;
                        for (j = 0; j < tagcon; j++)
                        {
                            tagnode = cJSON_GetArrayItem(tagnodes, j);
                            GET_JSON_VALUE_STRING_LOG(tagnode, "tag", var->devNodeInfo.pserviceInfoTodev[i].tagNode.ptagNode[j].tag);
                            GET_JSON_VALUE_STRING_LOG(tagnode, "name", var->devNodeInfo.pserviceInfoTodev[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 int period_charge_station_info(void *var, void *pParam, USHORT len)
{

    CHAR para[TIMER_MAX_PARA_LEN] = {0};
    CHAR *pSn = NULL;
    CHAR *pServic = NULL;
    chargestation_mng_var_t *pvar = (chargestation_mng_var_t *)var;
    memcpy(para, pParam, len);
    pSn = strtok(para, "|");
    pServic = strtok(NULL, "|");
    // dy_syslog(LOG_INFO, "%s->%s", pSn, pServic);
    {
        EXT_JSON_PACK_START(pServic, pSn);
        EXT_JSON_PACK_END(pvar, pvar->session, pSn, CH_STATION_TOPIC_GET);
    }
}

static void charge_coll_timer_init(chargestation_mng_var_t *var)
{
    int i, j, timerid = 0;
    CHAR para[TIMER_MAX_PARA_LEN] = {0};
    dy_syslog(LOG_INFO, "init charge coll timer");
    for (i = 0; i < var->devNodeInfo.devcont; i++)
    {
        for (j = 0; j < var->devNodeInfo.serviceupcont; j++)
        {
            snprintf(para, TIMER_MAX_PARA_LEN, "%s|%s", var->devNodeInfo.pdevnodecfg[i].devSn, var->devNodeInfo.pserviceInfoUP[j].identifier);
            // dy_syslog(LOG_INFO, "%s|%s period:%d\r\n", var->devNodeInfo.pdevnodecfg[i].devSn,
            //           var->devNodeInfo.pserviceInfoUP[j].identifier, var->devNodeInfo.pserviceInfoUP[j].period);
            timerid = mytimer_create(period_charge_station_info, para, strlen(para), var->devNodeInfo.pserviceInfoUP[j].period, E_TIMER_LOOP);
            mytimer_start(timerid);
        }
    }
}

static void charge_station_dev_init(chargestation_mng_var_t *var)
{
    int ret;
    mytimer_init(var);
    ret = load_charge_station_dev_cfg(var, CHARGE_STATION_DEV_FILE);
    if (ret != 0)
    {
        dy_syslog(LOG_INFO, "load_charge_station_dev_cfg fail:file name->%s", CHARGE_STATION_DEV_FILE);
    }
    get_board_sn(var->sn_str); //所有表信息;meter  sn
    dy_syslog(LOG_INFO, "board SN:%s", var->sn_str);

    chstation_dev_mqtt_client_init(var);
    sleep(1);
    var->second_period_timer = my_timer_create();
    if (var->second_period_timer > 0)
    {
        my_timer_set(var->second_period_timer, 1, SECOND_TIME);
    }
    charge_coll_timer_init(var);
}

void main()
{
    chargestation_mng_var_t chargestation_var = {0};
    charge_station_dev_init(&chargestation_var);
    charge_station_dev_entry(&chargestation_var);
}