#include <netinet/ip.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <time.h>
#include "collector-api.h"
#include "utils.h"
#include "main.h"
#include <math.h>
#include "jsonct.h"
#include "../common.h"
#include "ems_ua.h"
#include "open62541.h"
#include "lc_discovery.h"
#include "discover.h"
#include "../mqtt_emms2/mqtt_emms2.h"
#include "../alarm_control/alarm_control.h"
#include "../cmdclient.h"
#include "self_diagnosis.h"
#include "../log_module/log_module.h"
#include "../tag.h"
#include "../proto_forward.h"
#include "../opcua/ua_client.h"
#include "../template_info.h"
#include "../template_info.h"
#include "../multilanguage.h"
#include "../automatic_north/north_automatic.h"
#include "pub_fun.h"
#include "log_upper_data.h"
#include "../bmser/bmser_alarm.h"
#include "slave_ems.h"
#include "g100_protect.h"
#include "ems_activition.h"
#include "lc.h"
#include "../north_mqtt/north_mqtt.h"

#include "microgridtopology.h"
#include "../opt_log.h"
#define UD_LOG_LEVEL "UdLogLv"
#define RETURN(A) {proto_syslog(LOG_ERR,A);return;}
static pthread_t get_cycle_info_tid = PTHREAD_NULL;

SYSTEM_INFO system_info;
bool northcfg_change = false;
extern int north_control;
extern int north_g_reflush_all_plan;
extern int north_conn_status[NORTH_CHANNEL_CONRTOL_CNT];

UA_SERVER_PARAM *get_ua_server_param()
{
    pcs_ctrl_var_t *var = get_pcs_ctrl_var();
    return ((proto_forward_t *)var->device_layer_ptr)->ua_server_param;
}

/******************************************基础的事件功能*****************************************************/
#define EVENT_ONLY 1 //0关闭功能 1开启功能


#if EVENT_ONLY
static UA_StatusCode
addBaseEventType(UA_Server *server,char *eventName,UA_NodeId *eventType,UA_NodeId *outId) {    //创建基础事件类型

    UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
    attr.displayName = UA_LOCALIZEDTEXT("zh_CN", eventName);
    attr.description = UA_LOCALIZEDTEXT("zh_CN", eventName);
    UA_StatusCode retval =  UA_Server_addObjectTypeNode(server, UA_NODEID_NULL,
                                       UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE),
                                       UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
                                       UA_QUALIFIEDNAME(0, eventName),
                                       attr, NULL, eventType);
    if (retval != UA_STATUSCODE_GOOD) 
        proto_syslog(LOG_WARNING,
                       "createEvent failed. StatusCode %s", UA_StatusCode_name(retval));


    retval = UA_Server_createEvent(server, *eventType, outId);
    if (retval != UA_STATUSCODE_GOOD) {
        proto_syslog(LOG_WARNING,
                       "createEvent failed. StatusCode %s", UA_StatusCode_name(retval));
    }
    return retval;
}


static UA_StatusCode
setUpEvent(UA_Server *server, UA_NodeId *outId,char *source,int Severity,char *message) {

    /* Set the Event Attributes */
    /* Setting the Time is required or else the event will not show up in UAExpert! */
    UA_DateTime eventTime = UA_DateTime_now();
    UA_Server_writeObjectProperty_scalar(server, *outId, UA_QUALIFIEDNAME(0, "Time"), 
                                         &eventTime, &UA_TYPES[UA_TYPES_DATETIME]);

    UA_String eventSourceName = UA_STRING(source);
    UA_Server_writeObjectProperty_scalar(server, *outId, UA_QUALIFIEDNAME(0, "SourceName"),
                                         &eventSourceName, &UA_TYPES[UA_TYPES_STRING]);

    UA_Int32 eventSeverity = Severity;
    UA_Server_writeObjectProperty_scalar(server, *outId, UA_QUALIFIEDNAME(0, "Severity"),
                                         &eventSeverity, &UA_TYPES[UA_TYPES_UINT16]);

    UA_LocalizedText eventMessage = UA_LOCALIZEDTEXT("zh_CN", message);
    UA_Server_writeObjectProperty_scalar(server, *outId, UA_QUALIFIEDNAME(0, "Message"),
                                         &eventMessage, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);

    return UA_STATUSCODE_GOOD;
}

static int callTotleEvent(UA_Server *server,UA_NodeId *eventNodeId,char *source,int Severity,char *message)  //修改并触发事件 触发不同事件最好在封装一层
{
    UA_StatusCode retval = setUpEvent(server, eventNodeId,source,Severity,message);
    if(retval != UA_STATUSCODE_GOOD) {
        proto_syslog(LOG_WARNING,
                       "Creating event failed. StatusCode %s", UA_StatusCode_name(retval));
        return -1;
    }

    retval = UA_Server_triggerEvent(server, *eventNodeId,
                                    UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
                                    NULL, UA_FALSE);
    if(retval != UA_STATUSCODE_GOOD){
        proto_syslog(LOG_WARNING, 
                       "Triggering event failed. StatusCode %s", UA_StatusCode_name(retval));
        return -1;
    }
    return 0;
}
#endif

void UA_Event_Init(UA_SERVER_PARAM *ua_param)
{
#if EVENT_ONLY
    if(ua_param->ua_server == NULL)
    {
        proto_syslog(LOG_ERR,
                       "create server before creat event!");
        return;
    }
    addBaseEventType(ua_param->ua_server,"SimpleEventType",&ua_param->eventType,&ua_param->outId);
#endif
}

void callBaseEvent(char *source,int Severity,char *message)
{
    #if EVENT_ONLY
    UA_SERVER_PARAM *param = get_ua_server_param();
    callTotleEvent(param->ua_server,&param->outId,source,Severity,message);
    #endif
}
extern bool pthread_run;
void ems_log_Event(char *message,int Severity)
{
    #if EVENT_ONLY
    if(pthread_run)
    {
        UA_SERVER_PARAM *param = get_ua_server_param();
        callTotleEvent(param->ua_server,&param->outId,"ems_log",Severity,message);
    }
    #endif
}

/***************************************************************************************************/

// TMS配置缓冲 默认如下
/* struct TmsModeMap *TmsModeMapBuff = NULL; */







/*END*/
static void strcatfileinfo(char *file_name, struct lnxall_buff * lbuf)
{
    size_t len;
    char *pdata = NULL;
    pdata = read_file_data(file_name);

    len = (pdata != NULL) ? strlen(pdata) : 0;
    if (len > 0) {
        lbuff_append(lbuf, pdata, (int) len);
    } else {
        lbuff_append(lbuf, "{}", 2);
    }

    if (pdata != NULL) {
        free(pdata);
        pdata = NULL;
    }
}

#define EMS_LOG_LEVEL "EMS_Loglv"
#define PRO_LOG_LEVEL "ProtoLoglv"

int write_cb(char *name, void *value_v)
{
    int *value = value_v;
    ems_syslog(LOG_NOTICE,"write name:%s,value:%d",name,*value);
    if(0 == strcmp(UD_LOG_LEVEL, name))
    {
        ud_log_Level = *value;
        UD_log_update_en();
    }
    if(*value > 7)*value=7;
    if(*value < 1)*value=1;
    if(strcmp(EMS_LOG_LEVEL,name) == 0)
    {
        g_ems_log_level = *value;
    }
    else if(strcmp(PRO_LOG_LEVEL,name) == 0)
    {
        g_proto_log_level = *value;
    }
    return 0;
}

int read_cb(char *name, void *value_v)
{
    int *value = value_v;
    if(strcmp(EMS_LOG_LEVEL,name) == 0)
    {
        *value = g_ems_log_level;
    }
    else if(strcmp(PRO_LOG_LEVEL,name) == 0)
    {
        *value = g_proto_log_level;
    }
    else if(0 == strcmp(UD_LOG_LEVEL, name))
    {
        *value = ud_log_Level;
    }
    //ems_syslog(LOG_NOTICE,"read name:%s,value:%d",name,*value);
    return 0;
}
int read_cb_ems(char *name, void *value_v)
{
    int *value = value_v;
    *value = get_discover_dev_num();
    return 0;
}
int read_total_cb(char *name, void *value_v)
{
    read_cabinet_info_by_name(name,value_v);
    return 0;
}


int read_sim_loc(char *name, void *value_v)
{
    int fd;
    ssize_t ret;
    char tmp_ch[256];
    const char * file = LOCATION_4G_FILEPATH;

    tmp_ch[0] = '\0';
    fd = open(file, O_RDONLY);
    if (fd < 0)
        goto err0;

    ret = read(fd, tmp_ch, sizeof(tmp_ch) - 1);
    if (ret < 0)
        tmp_ch[0] = '\0';
    else
        tmp_ch[ret] = '\0';
    close(fd);
err0:
    strcpy((char *)value_v,tmp_ch);
    return 0;
}

int write_total_cb(char *name, void *value_v)
{
    write_cabinet_info_by_name(name,value_v);
    return 0;
}

static int is_ems_dev(const char *type)
{
    static const char *target_type[] = {"PV", "LOAD", "DG", "TOTAL_PV", "GRID", "TRAS_LV"};
    int count = sizeof(target_type) / sizeof(target_type[0]);
    if (!type) return 0;
    for (int i = 0; i < count; i++)
    {
        if (strstr(type, target_type[i]) != NULL)
        {
            return 1;
        }
    }
    return 0;
}

static void split_dev_cfg(const cJSON *root, cJSON **ems_root, cJSON **lc_root) {
    if (!root || !ems_root || !lc_root) return;

    *ems_root = cJSON_CreateObject();
    *lc_root  = cJSON_CreateObject();

    cJSON *dev_class_ems = cJSON_CreateArray();
    cJSON *dev_class_lc  = cJSON_CreateArray();

    cJSON *dev_class = cJSON_GetObjectItem(root, "dev_class");
    if (!cJSON_IsArray(dev_class)) {
        cJSON_AddItemToObject(*ems_root, "dev_class", dev_class_ems);
        cJSON_AddItemToObject(*lc_root,  "dev_class", dev_class_lc);
        return;
    }

    int dev_class_cnt = cJSON_GetArraySize(dev_class);

    for (int i = 0; i < dev_class_cnt; ++i) {
        const cJSON *type_entry = cJSON_GetArrayItem(dev_class, i);
        if (!cJSON_IsObject(type_entry)) continue;

        const cJSON *type_item = cJSON_GetObjectItem(type_entry, "type");
        const cJSON *devs = cJSON_GetObjectItem(type_entry, "devs");

        cJSON *type_ems = cJSON_CreateObject();
        cJSON *type_lc  = cJSON_CreateObject();
        if (type_item && cJSON_IsString(type_item)) {
            cJSON_AddItemToObject(type_ems, "type", cJSON_Duplicate(type_item, 1));
            cJSON_AddItemToObject(type_lc,  "type", cJSON_Duplicate(type_item, 1));
        } else {
            cJSON_AddItemToObject(type_ems, "type", cJSON_CreateString(""));
            cJSON_AddItemToObject(type_lc,  "type", cJSON_CreateString(""));
        }

        cJSON *ems_devs = cJSON_CreateArray();
        cJSON *lc_devs  = cJSON_CreateArray();

        if (cJSON_IsArray(devs)) {
            int dev_cnt = cJSON_GetArraySize(devs);
            for (int j = 0; j < dev_cnt; ++j) {
                cJSON *dev = cJSON_GetArrayItem(devs, j);
                if (!cJSON_IsObject(dev)) continue;
                const cJSON *no = cJSON_GetObjectItem(dev, "no");
                if (no && cJSON_IsString(no) && is_ems_dev(no->valuestring))
                {
                    cJSON_AddItemToArray(ems_devs, cJSON_Duplicate(dev, 1));
                }
                else
                {
                    cJSON_AddItemToArray(lc_devs, cJSON_Duplicate(dev, 1));
                }
            }
        }
        cJSON_AddItemToObject(type_ems, "devs", ems_devs);
        cJSON_AddItemToObject(type_lc,  "devs", lc_devs);

        cJSON_AddItemToArray(dev_class_ems, type_ems);
        cJSON_AddItemToArray(dev_class_lc,  type_lc);
    }
    cJSON_AddItemToObject(*ems_root, "dev_class", dev_class_ems);
    cJSON_AddItemToObject(*lc_root , "dev_class", dev_class_lc);
}

static int save_device_cfg(cJSON *root) {
    if (!root) return -1;

    char *string = NULL;
    char *string_lc = NULL;
    char *string_ems = NULL;

    if (cabinet_info.en_lc != 0) {
        cJSON *ems_cfg = NULL;
        cJSON *lc_cfg  = NULL;
        split_dev_cfg(root, &ems_cfg, &lc_cfg);

        if (ems_cfg) {
            string_ems = cJSON_Print(ems_cfg);
            if (string_ems) {
                write_file_data(CONFIG_PATH "/" COLLECTOR_DEVICE, string_ems, strlen(string_ems));
                free(string_ems);
            }
            cJSON_Delete(ems_cfg);
        }
        if (lc_cfg) {
            string_lc = cJSON_Print(lc_cfg);
            if (string_lc) {
                write_file_data(CONFIG_PATH "/lc/" COLLECTOR_DEVICE, string_lc, strlen(string_lc));
                write_file_data(CONFIG_PATH "/lc_devs/LC/" COLLECTOR_DEVICE, string_lc, strlen(string_lc));
                free(string_lc);
            }
            cJSON_Delete(lc_cfg);
        }
    } else {
        string = cJSON_Print(root);
        if (string) {
            write_file_data(CONFIG_PATH "/" COLLECTOR_DEVICE, string, strlen(string));
            free(string);
        }
    }
    return 0;
}

static char *get_device_cfg(void)
{
    char *pdata1 = NULL;
    char *pdata2 = NULL;
    if (cabinet_info.en_lc != 0) // 使能了主从一体
    {
        pdata1 = read_file_data(CONFIG_PATH "/" COLLECTOR_DEVICE);
        pdata2 = read_file_data(CONFIG_PATH "/lc/" COLLECTOR_DEVICE);
        if ((pdata1 != NULL) && (pdata2 != NULL))
        {
            cJSON *result1 = cJSON_Parse(pdata1);
            cJSON *result2 = cJSON_Parse(pdata2);
            free(pdata1);
            free(pdata2);
            pdata1 = pdata2 = NULL;
            if ((result1 != NULL) && (result2 != NULL))
            {
                dev_cfg_merge(result1, result2, 1);
                pdata1 = cJSON_Print(result1);
                cJSON_Delete(result1);
                cJSON_Delete(result2);
            }
        }
        }
    else
    {
        pdata1 = read_file_data(CONFIG_PATH "/" COLLECTOR_DEVICE);
    }

    if (pdata1 != NULL)
    {
        return pdata1;
    }
    else
    {
        return strdup("{}");
    }
}

static char *get_4g_status(void)
{
    char *pdata = NULL;
    pdata = read_file_data("/tmp/status_info.json");

    if (pdata != NULL)
    {
        return pdata;
    }
    else
    {
        return strdup("{}");
    }
}


int check_ip_nonnull(char **string)
{
    if (string == NULL || *string == NULL) return -1;

    cJSON *root = cJSON_Parse(*string);
    if (!root) return -2;

    cJSON *devices = cJSON_GetObjectItem(root, "devices");
    if (!cJSON_IsArray(devices)) {
        cJSON_Delete(root);
        return -3;
    }

    int changed = 0;
    int size = cJSON_GetArraySize(devices);
    for (int i = 0; i < size; i++) {
        cJSON *item = cJSON_GetArrayItem(devices, i);
        if (!cJSON_IsObject(item)) continue;

        cJSON *type = cJSON_GetObjectItem(item, "type");
        cJSON *ipaddr = cJSON_GetObjectItem(item, "ipaddr");

        if (type && cJSON_IsString(type) && strcmp(type->valuestring, "vlc") == 0) {
            if (!ipaddr || !cJSON_IsString(ipaddr) || ipaddr->valuestring[0] == '\0') {
                char ipaddr_buf[20] = {0};
                get_localip(get_pcs_ctrl_var()->net_node, ipaddr_buf);
                if (ipaddr) {
                    cJSON_SetValuestring(ipaddr, ipaddr_buf);
                } else {
                    cJSON_AddStringToObject(item, "ipaddr", ipaddr_buf);
                }
                changed = 1;
            }
        }
    }

    if (changed) {
        char *new_str = cJSON_PrintUnformatted(root);
        if (new_str) {
            free(*string);
            *string = new_str;
        }
    }
    cJSON_Delete(root);
    return 0;
}

int set_dido_common_config(cJSON* root);
extern  int check_and_clear_upload_record(char *mqtt_id, cJSON* config);

int update_lc_enble_status(cJSON* root)
{
    char lc_no[16] = {0};
    int disable = 0;
    cJSON *no_item = cJSON_GetObjectItem(root, "no");
    if (no_item && cJSON_IsString(no_item)) {
        strncpy(lc_no, no_item->valuestring, sizeof(lc_no) - 1);
    }
    GET_JSON_VALUE_INT(root, "disable", disable);

    pcs_ctrl_var_t *var = get_pcs_ctrl_var();
    int lc_cnt = var->lc_list_len;
    lc_it *lc_list_tmp = var->lc_list;

    for (int i = 0; i < lc_cnt; i++)
    {
        if (strcmp(lc_list_tmp[i].no, lc_no) == 0)
        {
            lc_list_tmp[i].disabled = disable;
            break;
        }
    }

    char *file_str = read_file_data("/app/config/ems_lc_list.json");
    if (file_str == NULL) {
        proto_syslog(LOG_ERR, "Failed to read /app/config/ems_lc_list.json");
        return -1;
    }
    cJSON *file_json = cJSON_Parse(file_str);
    free(file_str);

    if (!file_json) {
        proto_syslog(LOG_ERR, "Failed to parse ems_lc_list.json");
        return -1;
    }

    cJSON *devices_array = cJSON_GetObjectItem(file_json, "devices");
    if (!cJSON_IsArray(devices_array)) {
        proto_syslog(LOG_ERR, "devices is not an array in ems_lc_list.json");
        cJSON_Delete(file_json);
        return -1;
    }

    int found = 0;
    int arr_size = cJSON_GetArraySize(devices_array);
    for (int i = 0; i < arr_size; i++) {
        cJSON *dev_item = cJSON_GetArrayItem(devices_array, i);
        cJSON *no_item = cJSON_GetObjectItem(dev_item, "no");
        if (no_item && cJSON_IsString(no_item) && strcmp(no_item->valuestring, lc_no) == 0) {
            cJSON *disabled_item = cJSON_GetObjectItem(dev_item, "disabled");
            if (disabled_item) {
                cJSON_SetIntValue(disabled_item, disable);
            } else {
                cJSON_AddNumberToObject(dev_item, "disabled", disable);
            }
            found = 1;
            break;
        }
    }

    if (!found) {
        proto_syslog(LOG_WARNING, "LC no %s not found in ems_lc_list.json", lc_no);
    }

    char *new_file_str = cJSON_Print(file_json);
    if (new_file_str) {
        write_file_data("/app/config/ems_lc_list.json", new_file_str, strlen(new_file_str));
        free(new_file_str);
    } else {
        proto_syslog(LOG_ERR, "Failed to generate new ems_lc_list.json string");
    }

    cJSON_Delete(file_json);
    return 0;
}

int save_ems_string_to_file(char *name ,char *pdata) //返回jsonFormat failure -2没找到名字
{
    int ret = 0;
    cJSON *root = NULL;
    root = json_parse_string_with_comments(pdata);
    if (!root)
    {
        ems_syslog(LOG_ERR, "parse cfg file error");
        ret = -1;
        goto out;
    }
    if (strstr(name,DEVICE_CONFIG_NAME)!=NULL)
    {
        save_device_cfg(root);
    }
    else if (strstr(name,PORT_CONFIG_NAME)!=NULL)
    {
        char *string = cJSON_Print(root);
        if (string)
        {
            ems_syslog(LOG_NOTICE, "port_config string:%s",string);
            write_file_data(DEV_PORT_CFG_FILE, string, strlen(string));
            free(string);
            string=NULL;
        }
        // 处理 DIDO 配置 lc
        set_dido_common_config(root);
    }
    else if (strstr(name,PROPERTY_INFO_NAME)!=NULL)
    {
        char *string = cJSON_Print(root);
        if (string)
        {
            ems_syslog(LOG_NOTICE, PROPERTY_INFO_NAME "string:%s",string);
            write_file_data(CONFIG_PATH"/"PROPERTY, string, strlen(string));
            free(string);
            string=NULL;
        }
    }
    else if (strstr(name,PRICE_INFO_NAME)!=NULL)
    {
        char *string = cJSON_Print(root);
        if (string)
        {
            ems_syslog(LOG_NOTICE, PRICE_INFO_NAME "string:%s",string);
            write_file_data(CONFIG_PATH"/"PRICE, string, strlen(string));
            free(string);
            string=NULL;
        }
    }
    else if (strstr(name,TRIGGER_INFO_NAME)!=NULL)
    {
        char *string = cJSON_Print(root);
        if (string)
        {
            ems_syslog(LOG_NOTICE, TRIGGER_INFO_NAME "string:%s",string);
            write_file_data(TRIGGER_CFG_FILE, string, strlen(string));
            free(string);
            string=NULL;
        }
    }
    else if (strstr(name, TMS_CONFIG_NAME) != NULL) // tms_config
    {
        char *string = cJSON_Print(root);
        if (string) {
            mkdir(ADAPTER_CONFIG_DIR, 0755);
            ems_syslog(LOG_NOTICE, TMS_CONFIG_NAME "string:%s", string);
            write_file_data(ADAPTER_CONFIG_DIR "/" COLLECTOR_TMS_CONFIG, string, strlen(string));
            free(string);
            string = NULL;
        }
    }

    else if (strstr(name, EMS_LC_LIST) != NULL) {
        char * string = cJSON_Print(root);
        if (string != NULL) {
            check_ip_nonnull(&string);
            ems_syslog(LOG_NOTICE, EMS_LC_LIST "string:%s",string);
            write_file_data(CONFIG_PATH "/" EMS_LC_LIST_FILE, string, strlen(string));
            free(string);
            string = NULL;
        }
    }
    else if (strstr(name, EMMS2_CONFIG_NAME) != NULL)
    {
        char* string = cJSON_Print(root);
        if (string != NULL)
        {
            ems_syslog(LOG_NOTICE, EMMS2_CONFIG_NAME "string:%s", string);
            check_and_clear_upload_record(MQTT_EMMS2_STATION_ID, root);
            write_file_data(CONFIG_PATH "/" EMMS2_MQTT_CONFIG, string, strlen(string));
            free(string);
            string = NULL;
        }
    }
    else if (strstr(name, STACTRL_CONFIG_NAME) != NULL)
    {
        char* string = cJSON_Print(root);
        if (string != NULL)
        {
            ems_syslog(LOG_NOTICE, STACTRL_CONFIG_NAME "string:%s", string);
            check_and_clear_upload_record(MQTT_STACTRL_STATION_ID, root);
            write_file_data(CONFIG_PATH "/" STACTRL_MQTT_CONFIG, string, strlen(string));
            free(string);
            string = NULL;
        }
    }
    else if (strstr(name, DEV_GROUP_INFO_NAME) != NULL)
    {
        char *string = cJSON_PrintUnformatted(root);
        write_file_data(CONFIG_PATH "/" DEV_GROUP_INFO_NAME ".json", string, strlen(string));
        free(string);
        ems_syslog(LOG_ERR, "write config file %s success, proto_forward exit!!!!", DEV_GROUP_INFO_NAME);
        exit(0);
        string = NULL;
    }
    else if (strstr(name, DEV_GROUP_CFG) != NULL)
    {
        char *string = cJSON_PrintUnformatted(root);
        write_file_data(DEV_GROUP_CFG_PATH, string, strlen(string));
        free(string);
        string = NULL;
    }
    else if(strstr(name ,CABINET_INFO_NAME) != NULL)
    {
        set_cabinet_info(root, "webui", time(NULL));
    }
    else if(strstr(name ,LC_SET_CABNAME) != NULL)
    {
        set_lc_cabname_info(root);
    }
    else if (strstr(name, EMS_LC_SETIPADDR) != NULL) {
        int dhcp = 0;
        char * sn = NULL;
        char * ipaddr = NULL;
        char * gateway = NULL;

        GET_JSON_VALUE_INT(root, "dhcp", dhcp);
        GET_JSON_VALUE_DY_STRING(root, "ipaddr", ipaddr);
        GET_JSON_VALUE_DY_STRING(root, "gateway", gateway);
        GET_JSON_VALUE_DY_STRING(root, "sn", sn);

        if (sn == NULL || sn[0] == '\0') {
            ems_syslog(LOG_ERR, "Target LC SN not specified");
            goto next;
        }
        if (dhcp != 0 || ipaddr == NULL || gateway == NULL) {
            set_discovery_ipaddr(sn, NULL, NULL);
        } else {
            set_discovery_ipaddr(sn, ipaddr, gateway);
        }
next:
        free(sn);
        free(ipaddr);
        free(gateway);
    }
    else if(strstr(name, "set_lc_enable_status")!=NULL)
    {
        update_lc_enble_status(root);
    }
    else
        ret = -2;

out:
    cJSON_Delete(root);
    return ret;
}

extern int g_proto_log_level;
extern int g_ems_log_level;
int function_data_cmp_string(const function_data *input, const char *str)
{
    if (strlen(str) != input->data_len)
    {
        return -1;
    }
    return memcmp(str, input->data, input->data_len);
}

const char *template_info_path = "/app/template/template_info";
int template_info_init(void)
{
    struct lnxall_buff lbuf;
    lbuff_init(&lbuf, 72 * 1024); // 72k
    lbuff_append(&lbuf, "[" ,1);
    get_all_temp_info(TEMPLATE_DIR, &lbuf);
    template_info_collect(TEMPLATE_DIR, &lbuf);
    if (lbuf.bufptr[lbuf.curlen-1] == ',')
    {
        lbuf.bufptr[lbuf.curlen - 1] = '\0';
        lbuf.curlen--;
    }
    lbuff_append(&lbuf, "]", 1);

    char* old = read_file_data(template_info_path);
    if (old == NULL || strcmp(old, lbuf.bufptr) != 0)
    {
        write_file_data(template_info_path, lbuf.bufptr, lbuf.curlen);
    }

    free(old);
    lbuff_free(&lbuf);
    return 0;
}

int getval_in_file(const char *pattern, char *buf, int len, const char *path)
{
	int error = -1;
	FILE *file;
	char lbuf[256];
	char *pstr;
	int offset = 0;

	file = fopen(path, "r");
	if (file == NULL) {
		error = errno;
		fprintf(stderr, "Error, failed to open %s: %s",
			path, strerror(error));
		fflush(stderr);
		errno = error;
		return -1;
	}

	offset = strlen(pattern);
	if (offset >= len) {
		fclose(file);
		return -1;
	}

    while (fgets(lbuf, sizeof(lbuf), file)) {
        pstr = strstr(lbuf, pattern);
        if (pstr == NULL)
            continue;
        strncpy(buf, pstr + offset, len - 1);
        buf[len - 1] = '\0';
        error = 0;
        break;
    }

    fclose(file);
    return error;
}

char *get_whole_subdomain(void)
{   
    const char *path = "/etc/frpc.toml";
    char serverAddr[32];
    char *subdomain;
    int ret;
    char *pchr;
	char *head = "https://";
    
    subdomain = (char *) calloc(1, 64);
    if (subdomain == NULL) {
        fprintf(stderr, "Error, out of memory");
        fflush(stderr);
        return NULL;
    }
	strcpy(subdomain, head);
    
    ret = getval_in_file("serverAddr = \"", serverAddr, 32, path);
    if (ret == -1) {
		free(subdomain);
        return NULL;
	}
    pchr = strchr(serverAddr, '"');
    if (pchr != NULL)
        pchr[0] = '\0';
    
    ret = getval_in_file("subdomain = \"", subdomain + strlen(head), 16, path);
    if (ret == -1) {
		free(subdomain);
        return NULL;
	}
    pchr = strchr(subdomain, '"');
    if (pchr != NULL) {
        pchr[0] = '.';
		pchr[1] = '\0';
	}
    
    strncat(subdomain, serverAddr, 63 - strlen(subdomain));
	strcat(subdomain, ":50080");
    subdomain[63] = '\0';
    return subdomain;
}

char *get_all_dev_tree(void)
{
    char *ret = NULL;
    cJSON *root = get_dev_tree_from_file(CONFIG_PATH"/"COLLECTOR_DEVICE);
    if (root == NULL)
    {
        return NULL;
    }
    int lc_sum = get_pcs_ctrl_var()->lc_list_len;
    lc_it *lc_list = get_pcs_ctrl_var()->lc_list;
    char *sub_tree = NULL;
    cJSON *sub_tree_obj = NULL;
    cJSON *dev_tree = cJSON_GetObjectItem(root, "dev_tree");
    if (dev_tree != NULL)
    {
        for (int i = 0; i < lc_sum; i++)
        {
            if (lc_list[i].type == eLC_TYPE_VLC)
            {
                char LC_cfg_path[128] = {0};
                snprintf(LC_cfg_path, sizeof(LC_cfg_path), LC_DEVS_DIR"/%s/"COLLECTOR_DEVICE, lc_list[i].no);

                cJSON *VLC_dev_tree = get_dev_tree_from_file(LC_cfg_path);
                if (VLC_dev_tree == NULL)
                {
                    proto_syslog(LOG_ERR, "%s sub_tree is null", lc_list[i].no);
                    continue;
                }
                cJSON_AddStringToObject(VLC_dev_tree, "type", DEV_NO_LC);
                cJSON_AddStringToObject(VLC_dev_tree, "no", lc_list[i].no);
                cJSON_AddStringToObject(VLC_dev_tree, "name", lc_list[i].name);
                cJSON_AddItemToArray(dev_tree, VLC_dev_tree);
            }
            if (lc_list[i].type != eLC_TYPE_EMS)
            {
                continue;
            }
            if (lc_list[i].slave == NULL)
            {
                ems_syslog(LOG_ERR, "%s slave is null", lc_list[i].no);
                continue;
            }
            sub_tree = slave_ems_get_dev_tree(lc_list[i].slave);
            if (sub_tree == NULL)
            {
                proto_syslog(LOG_ERR, "%s sub_tree is null", lc_list[i].no);
                continue;
            }
            //
            sub_tree_obj = cJSON_Parse(sub_tree);
            if (sub_tree_obj == NULL)
            {
                proto_syslog(LOG_ERR, "%s sub_tree_obj is null", lc_list[i].no);
                continue;
            }
            //
            cJSON_AddStringToObject(sub_tree_obj, "type", "LC");
            cJSON_AddStringToObject(sub_tree_obj, "no", lc_list[i].no);
            cJSON_AddStringToObject(sub_tree_obj, "name", lc_list[i].name);
            //
            cJSON_AddItemToArray(dev_tree, sub_tree_obj);
        }
    }
    if (root != NULL)
    {
        ret = cJSON_PrintUnformatted(root);
        cJSON_Delete(root);
    }
    return ret;
}


char *get_all_dev_group_info(void)
{
    char *ret = read_file_data(CONFIG_PATH "/" DEV_GROUP_INFO_NAME ".json");
    return ret;
}

static char *get_group_2_lc(void)
{
    char *group_cfg = read_file_data(DEV_GROUP_CFG_PATH);
    if (group_cfg == NULL)
    {
        return NULL;
    }
    //
    cJSON *obj_cfg = cJSON_Parse(group_cfg);
    free(group_cfg);
    if (obj_cfg == NULL)
    {
        return NULL;
    }
    //
    int it_sum = cJSON_GetArraySize(obj_cfg);
    cJSON *group_2_lc_list = cJSON_CreateArray();
    if (group_2_lc_list == NULL)
    {
        cJSON_Delete(obj_cfg);
        return NULL;
    }
    for (int i = 0; i < it_sum; i++)
    {
        cJSON *obj = cJSON_GetArrayItem(obj_cfg, i);
        if (obj == NULL)
        {
            continue;
        }
        cJSON *group = cJSON_GetObjectItem(obj, "group");
        cJSON *devs = cJSON_GetObjectItem(obj, "devices");
        if (group == NULL || devs == NULL)
        {
            continue;
        }
        //
        int dev_sum = cJSON_GetArraySize(devs);
        const char *pcs_mp_str = NULL;
        const char *bms_mp_str = NULL;

        for (int j = 0; j < dev_sum; j++)
        {
            cJSON *dev = cJSON_GetArrayItem(devs, j);
            if (dev == NULL)
            {
                continue;
            }
            cJSON *type = cJSON_GetObjectItem(dev, "type");
            cJSON *mp   = cJSON_GetObjectItem(dev, "mp");
            if (!cJSON_IsString(type) || !cJSON_IsString(mp))
            {
                continue;
            }

            if (strcmp(type->valuestring, DEV_TYPE_PCS) == 0)
            {
                pcs_mp_str = mp->valuestring;
            }
            else if (strcmp(type->valuestring, "BMS") == 0 && bms_mp_str == NULL)
            {
                bms_mp_str = mp->valuestring;
            }
        }

        if (pcs_mp_str != NULL)
        {
            cJSON *group_2_lc = cJSON_CreateObject();
            if (group_2_lc == NULL)
            {
                continue;
            }
            cJSON_AddItemToObject(group_2_lc, "Group", cJSON_CreateString(group->valuestring));
            cJSON_AddItemToObject(group_2_lc, "LcNo", cJSON_CreateString(pcs_mp_str));
            if (bms_mp_str != NULL)
            {
                cJSON_AddItemToObject(group_2_lc, "SLcNo", cJSON_CreateString(bms_mp_str));
                // get SLcFrpcAddr
                char *frpc_addr = "";
                slave_lc_frpcaddr_t *frpc_list = get_lc_list_frpcaddr();
                int frpc_cnt = get_lc_list_frpcaddr_count();
                if (frpc_list != NULL)
                {
                    for (int k = 0; k < frpc_cnt; k++)
                    {
                        if (strcmp(frpc_list[k].lc_no, bms_mp_str) == 0)
                        {
                            frpc_addr = frpc_list[k].frpcaddr;
                        }
                    }
                }
                cJSON_AddItemToObject(group_2_lc, "SLcFrpcAddr", cJSON_CreateString(frpc_addr));
                //get ipaddr
                pcs_ctrl_var_t *var = get_pcs_ctrl_var();
                int lc_cnt = var->lc_list_len;
                lc_it *lc_list_tmp = var->lc_list;

                for(int i = 0; i < lc_cnt; i++)
                {
                    if (strcmp(lc_list_tmp[i].no, bms_mp_str) == 0)
                    {
                        cJSON_AddItemToObject(group_2_lc, "SLcIpAddr", cJSON_CreateString(lc_list_tmp[i].ipaddr));
                    }
                }
            }
            else
            {
                cJSON_AddItemToObject(group_2_lc, "SLcNo", cJSON_CreateString(""));
                cJSON_AddItemToObject(group_2_lc, "SLcFrpcAddr", cJSON_CreateString(""));
                cJSON_AddItemToObject(group_2_lc, "SLcIpAddr", cJSON_CreateString(""));
            }
            cJSON_AddItemToArray(group_2_lc_list, group_2_lc);
        }
    }
    char *json_str = cJSON_Print(group_2_lc_list);
    cJSON_Delete(group_2_lc_list);
    cJSON_Delete(obj_cfg);
    return json_str;
}

static char *get_dev_tree_and_group_cfg(void)
{
    char *ch = get_all_dev_tree();
    if (ch != NULL)
    {
        cJSON *obj = cJSON_Parse(ch);
        if (obj != NULL)
        {
            char *group_cfg = read_file_data(DEV_GROUP_CFG_PATH);
            if (group_cfg != NULL)
            {
                cJSON *obj_cfg = cJSON_Parse(group_cfg);
                if (obj_cfg != NULL)
                {
                    cJSON_AddItemToObject(obj, "group_info", cJSON_Parse(group_cfg));
                    cJSON_Delete(obj_cfg);
                }
                free(group_cfg);
            }
            else
            {
                cJSON_AddItemToObject(obj, "group_info", cJSON_CreateArray());
            }
            free(ch);
            ch = cJSON_PrintUnformatted(obj);
            cJSON_Delete(obj);
        }
        return ch;
    }
    return NULL;
    
}


int ua_cbget(function_data *input,int input_num,function_data *output,int *output_num)
{
    int len = 0;
    struct lnxall_buff lbuf;

    lbuff_init(&lbuf, 8192);
    if(input_num==0) goto NOFINDE;
    if(function_data_cmp_string(&input[0],TEMP_INFO_NAME) == 0)
    {
        char *temp_info = read_file_data(template_info_path);
        if(temp_info != NULL)
        {
            output[0].data = temp_info;
            output[0].data_len = strlen(temp_info);
            *output_num = 1;
        }
        else
        {
            ems_syslog(LOG_ERR, "get template info return null");
            goto NOFINDE;
        }

        // NOTE: do not forget to free `lbuf:
        lbuff_free(&lbuf);
        return 0;
    }
    else if(function_data_cmp_string(&input[0],DEVICE_CONFIG_NAME) == 0)
    {
        char *ch = get_device_cfg();
        lbuff_append(&lbuf, ch, strlen(ch));
        free(ch);
    }
    else if(function_data_cmp_string(&input[0],"4G") == 0)
    {
        char *ch = get_4g_status();
        lbuff_append(&lbuf, ch, strlen(ch));
        free(ch);
    }
    else if(function_data_cmp_string(&input[0],PORT_CONFIG_NAME) == 0)
    {
        strcatfileinfo(DEV_PORT_CFG_FILE, &lbuf);
    }
    else if(function_data_cmp_string(&input[0],PROPERTY_INFO_NAME) == 0)
    {
        strcatfileinfo(CONFIG_PATH"/"PROPERTY, &lbuf);
    }
    else if(function_data_cmp_string(&input[0],PRICE_INFO_NAME) == 0)
    {
        strcatfileinfo(CONFIG_PATH"/"PRICE, &lbuf);
    }
    else if(function_data_cmp_string(&input[0],TRIGGER_INFO_NAME) == 0)
    {
        strcatfileinfo(TRIGGER_CFG_FILE, &lbuf);
    }
    else if (function_data_cmp_string(&input[0], NODE_SORT) == 0)
    {
        char *p_tmp = get_node_sort(&len);
        if (p_tmp != NULL)
        {
            output[0].data = p_tmp;
            output[0].data_len = len;
            *output_num = 1;

            // NOTE: do not forget to free `lbuf:
            lbuff_free(&lbuf);
            return 0;
        }
        else
        {
            ems_syslog(LOG_ERR, "get_node_sort return null");
            goto NOFINDE;
        }
    }
    else if (function_data_cmp_string(&input[0], TMS_CONFIG_NAME) == 0)
    {
        strcatfileinfo(ADAPTER_CONFIG_DIR "/" COLLECTOR_TMS_CONFIG, &lbuf); // tms_config 配置读取
    }
    else if (function_data_cmp_string(&input[0], AC_CONFIG_NAME) == 0)
    {
        strcatfileinfo(CONFIG_PATH "/" COLLECTOR_AC_CONFIG, &lbuf); // ac_config 配置读取
    }
    else if (function_data_cmp_string(&input[0], EMMS2_CONFIG_NAME) == 0)
    {
        strcatfileinfo(CONFIG_PATH "/" EMMS2_MQTT_CONFIG, &lbuf); // emms2_mqtt.json 配置读取
    }
    else if (function_data_cmp_string(&input[0], STACTRL_CONFIG_NAME) == 0)
    {
        strcatfileinfo(CONFIG_PATH "/" STACTRL_MQTT_CONFIG, &lbuf); // stactrl_mqtt.json 配置读取
    }
    else if (function_data_cmp_string(&input[0], CABINET_INFO_NAME) == 0)
    {
        read_cabinet_info(&lbuf); // stactrl_mqtt.json 配置读取
    }
    else if (function_data_cmp_string(&input[0], SUBDOMAIN_READ) == 0)
    {
		char *domain;
		cJSON *json_fmt = NULL;

		domain = get_whole_subdomain();
		if (domain != NULL)
		{
			json_fmt = cJSON_CreateObject();
			if (json_fmt != NULL)
			{
				cJSON_AddItemToObject(json_fmt, "subdomain", cJSON_CreateString(domain));
				free(domain);
				domain = NULL;
				domain = cJSON_Print(json_fmt);
				cJSON_Delete(json_fmt);
			}

			if (domain != NULL) {
				lbuff_append(&lbuf, domain, strlen(domain));
				free(domain);
				domain = NULL;
			}
		}
    }
    else if (function_data_cmp_string(&input[0], DEV_INFO_CONFIG_NAME) == 0)
    {
        char *ch = get_proto_forward_var()->dev_info_string;
        if (ch != NULL)
        {
            lbuff_append(&lbuf, ch, strlen(ch));
        }
    }
    else if (function_data_cmp_string(&input[0], DEV_TREE_NAME) == 0)
    {
        char *ch = get_dev_tree_and_group_cfg();
        if (ch != NULL)
        {
            lbuff_append(&lbuf, ch, strlen(ch));
            free(ch);
        }
    }
    else if (function_data_cmp_string(&input[0], "g2lc") == 0)
    {
        char *ch = get_group_2_lc();
        if (ch != NULL)
        {
            lbuff_append(&lbuf, ch, strlen(ch));
            free(ch);
        }
    }
    else if (function_data_cmp_string(&input[0], DEV_GROUP_INFO_NAME) == 0)
    {
        char *ch = get_all_dev_group_info();
        if (ch != NULL)
        {
            lbuff_append(&lbuf, ch, strlen(ch));
        }
    }
    else if (function_data_cmp_string(&input[0], "lc_alarmcnt") == 0) 
    {
        char *json_str = make_slave_alarm_info_json();
        if (json_str != NULL) {
            lbuff_append(&lbuf, json_str, strlen(json_str));
            free(json_str);
        } 
        else 
        {
            lbuff_append(&lbuf, "{\"lc_alarmcnt\":[]}",strlen("{\"lc_alarmcnt\":[]}"));
        }
    }
        else 
    {
        int all_info_len = 256;
        char *all_info = NULL;
        if (function_data_cmp_string(&input[0], EMS_LC_SCAN) == 0)
        {
            int devn;
            disc_devinfo *devs;

            devn = 0;
            devs = get_discover_devs(&devn);
            if (devs != NULL)
            {
                all_info_len = 256 * devn;
                all_info = calloc(1, all_info_len);
                if (all_info != NULL)
                {
                    get_discover_devbuf(devs, devn, all_info, all_info_len);
                }
                else
                {
                    len = 0;
                    ems_syslog(LOG_ERR, "calloc return null");
                }
            }
            else
            {
                /* no device found: */
                len = 0;
                all_info = strdup("");
            }
            free_discover_devs(devs, devn);
        }
        else if (function_data_cmp_string(&input[0], EMS_LC_LIST) == 0)
        {
            int devn = 0;
            struct hash_intptr *devs;

            devs = load_discovery_config(&devn);
            if (devs != NULL)
            {
                all_info_len = 256 * devn;
                all_info = calloc(1, all_info_len);
                if (all_info != NULL)
                {
                    get_discover_cfgbuf(devs, devn, all_info, all_info_len);
                    if (cabinet_info.ctrl_mode == EMS_MODE_ZC)
                    {
                        add_frpcaddr_info_to_lc_list(all_info, all_info_len);
                    }
                }
                else
                {
                    len = 0;
                    ems_syslog(LOG_ERR, "calloc return null");
                }
            }
            else
            {
                len = 0;
                all_info = strdup("");
            }
            free_discovery_config(devs);
        }
        else
        {
            goto NOFINDE;
        }
        
        // NOTE: do not forget to free `lbuf:
        lbuff_free(&lbuf);
        output[0].data = strdup(all_info);
        output[0].data_len = strlen(all_info);
        *output_num = 1;
        free(all_info);
        return 0;
    }

    if (lbuf.curlen == 0) {
        lbuff_free(&lbuf);
        output[0].data = strdup("");
        output[0].data_len = 0;
    } else {
        output[0].data = lbuf.bufptr;
        output[0].data_len = lbuf.curlen;
    }
    *output_num = 1;
    return 0;

NOFINDE:
    lbuff_sprintf(&lbuf, "{\"result\":\"error\",\"info\":\"input name list:" EMS_LC_SCAN "," EMS_LC_LIST 
    "," TEMP_INFO_NAME "," PRICE_INFO_NAME "," DEVICE_CONFIG_NAME "," PORT_CONFIG_NAME "," NODE_SORT 
    "," PROPERTY_INFO_NAME "," TRIGGER_INFO_NAME ", " DEV_INFO_CONFIG_NAME ", " EMMS2_CONFIG_NAME 
    "," STACTRL_CONFIG_NAME "," DEV_TREE_NAME "," CABINET_INFO_NAME "\"}");
    output[0].data = lbuf.bufptr;
    output[0].data_len = lbuf.curlen;
    *output_num = 1;

    return 0;
}

#if 1 // 自诊断回调
static self_diagnosis *diagnosis[2];
static int cur_diagnosis_index = 0;
char *creat_ack(const char *opt, int code)
{
    if (diagnosis[cur_diagnosis_index] == NULL)
    {
        code = 999;
    }
    char *ret = NULL;
    cJSON *ack_json = (code == 0) ? self_diagnosis_get_status(diagnosis[cur_diagnosis_index]) : cJSON_CreateObject();
    if (ack_json != NULL)
    {
        cJSON_AddItemToObject(ack_json, "opt", cJSON_CreateString(opt));
        cJSON_AddItemToObject(ack_json, "code", cJSON_CreateNumber(code));
        ret = cJSON_PrintUnformatted(ack_json);
        cJSON_Delete(ack_json);
        return ret;
    }
    return NULL;
}

/*
input  { "no": "LC", "opt": "start" }
input  start

return  999  参数错误
        998  停止失败
        99   opt 错误
        1    new self_diagnosis 失败
        2    开始诊断线程失败
        0    正常
        9999 从机名长度大于缓冲区
*/
static int self_diagnosis_cb_new(function_data* input, int input_num, function_data* output, int* output_num, int diagnosis_index)
{
    output[0].data    = NULL;
    int    code       = 999;
    char*  no      = NULL;
    char*  opt        = NULL;
    cJSON* input_json = NULL;

    if (input_num < 1)
    {
        ems_syslog(LOG_ERR, "self diagnosis error, input_num is %d, should be 1", input_num);
        goto self_diagnosis_cb_end_new;
    }

    cabinet_info_t* config = get_cabinet_info();
    input_json = cJSON_Parse(input[0].data);

    ems_syslog(LOG_DEBUG, "self diagnosis, input json: %s", input[0].data);

    if (input_json != NULL)
    {
        no = cJSON_GetObjectItem(input_json, "no")->valuestring;
        opt   = cJSON_GetObjectItem(input_json, "opt")->valuestring;
        if (no && strlen(no) > SLAVE_NAME_LEN)
        {
            ems_syslog(LOG_ERR, "self diagnosis error, slave no length is %zu, should be less than %d", strlen(no), SLAVE_NAME_LEN);
            goto self_diagnosis_cb_end_new;
        }
    }
    else
    {
        opt = input[0].data;
    }

    if (config->en_lc && NULL == no )
    {
        pcs_ctrl_var_t* var = get_pcs_ctrl_var();
        if(var->lc_list != NULL)
            no = var->lc_list[0].no;
        ems_syslog(LOG_NOTICE, "self diagnosis error, slave no is empty, default slave no is %s", no);
    }

    if (diagnosis_index != cur_diagnosis_index)
    {
        if (diagnosis[cur_diagnosis_index] != NULL)
        {
            if (0 == self_diagnosis_stop(diagnosis[cur_diagnosis_index]))
            {
                self_diagnosis_deinit(diagnosis[cur_diagnosis_index]);
            }
            else
            {
                code = 998;
                goto self_diagnosis_cb_end_new;
            }
        }
        cur_diagnosis_index = diagnosis_index;
    }

    if (opt && strstr(opt, "start"))
    {
        if (diagnosis[cur_diagnosis_index] == NULL)
        {
            if (0 == diagnosis_index)
            {
                server_add_new_log(LOG_CODE_OPC_FACTORY_DIAGNOSIS, "EMS", LOG_MODE_TRIG, 1, NULL);
                diagnosis[cur_diagnosis_index] = factory_diagnosis_new(no);
            }
            else
            {
                server_add_new_log(LOG_CODE_OPC_CAHRGE_DIAGNOSIS, "EMS", LOG_MODE_TRIG, 1, NULL);
                diagnosis[cur_diagnosis_index] = charge_diagnosis_new(no);
            }

            if (diagnosis[cur_diagnosis_index] == NULL)
            {
                ems_syslog(LOG_ERR, "self diagnosis error, new fail");
                code = 1;
            }
        }
        int ret = self_diagnosis_start(diagnosis[cur_diagnosis_index]);
        if (0 == ret)
        {
            code = 0;
        }
        else
        {
            ems_syslog(LOG_ERR, "self diagnosis error, start fail, ret = %d", ret);
            code = 2;
        }
    }
    else if (opt && strstr(opt, "stop"))
    {
        code = self_diagnosis_stop(diagnosis[cur_diagnosis_index]);
        self_diagnosis_stop_handle(diagnosis[cur_diagnosis_index]);
    }
    else if (opt && strstr(opt, "get"))
    {
        code = 0;
    }
    else
    {
        code = 999;
    }

self_diagnosis_cb_end_new:
    output[0].data     = creat_ack(opt, code);
    output[0].data_len = strlen(output[0].data);
    *output_num        = 1;
    if (input_json)
    {
        cJSON_Delete(input_json);
    }
    return 0;
}
#if 0 // not used
static int self_diagnosis_cb(function_data *input, int input_num, function_data *output, int *output_num, int diagnosis_index)
{
    output[0].data = NULL;
    int code = 999;
    char *opt = "NULL";
    if (input_num > 0)
    {
        opt = calloc(1, input[0].data_len + 1);
        if (opt == NULL)
        {
            ems_syslog(LOG_ERR, "calloc error");
            code = 9999;
            goto self_diagnosis_cb_end;
        }
        memcpy(opt, input[0].data, input[0].data_len);
        if (diagnosis_index != cur_diagnosis_index)
        {
            if (diagnosis[cur_diagnosis_index] != NULL)
            {
                if (0 == self_diagnosis_stop(diagnosis[cur_diagnosis_index]))
                {
                    self_diagnosis_deinit(diagnosis[cur_diagnosis_index]);
                }
                else
                {
                    code = 998;
                    goto self_diagnosis_cb_end;
                }
            }
            cur_diagnosis_index = diagnosis_index;
        }

        if (strstr(opt, "start"))
        {
            if (diagnosis[cur_diagnosis_index] == NULL)
            {
                if (diagnosis_index == 0)
                {
                    server_add_new_log(LOG_CODE_OPC_FACTORY_DIAGNOSIS,"EMS",LOG_MODE_TRIG,1,NULL);
                    diagnosis[cur_diagnosis_index] = factory_diagnosis_new(NULL);
                }
                else
                {
                    server_add_new_log(LOG_CODE_OPC_CAHRGE_DIAGNOSIS,"EMS",LOG_MODE_TRIG,1,NULL);
                    diagnosis[cur_diagnosis_index] = charge_diagnosis_new(NULL);
                }
                if (diagnosis[cur_diagnosis_index] == NULL)
                {
                    ems_syslog(LOG_ERR, "self diagnosis new fail");
                    code = 1;
                }
            }
            if (0 != self_diagnosis_start(diagnosis[cur_diagnosis_index]))
            {
                ems_syslog(LOG_ERR, "self diagnosis start fail");
                code = 2;
            }
            else
            {
                code = 0;
            }
        }
        else if (strstr(opt, "get"))
        {
            code = 0;
        }
        else if (strstr(opt, "stop"))
        {
            code = self_diagnosis_stop(diagnosis[cur_diagnosis_index]);
            self_diagnosis_stop_handle(diagnosis[cur_diagnosis_index]);
        }
        else
        {
            code = 99;
        }
    }
    else
    {
        code = 9999;
        output[0].data = creat_ack(opt, code);
        output[0].data_len = strlen(output[0].data);
        *output_num = 1;
        return 0;
    }
self_diagnosis_cb_end:
    output[0].data = creat_ack(opt, code);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    free(opt);
    return 0;
}

int factory_diagnosis(function_data *input, int input_num, function_data *output, int *output_num)
{
    return self_diagnosis_cb(input, input_num, output, output_num, 0);
}

int charge_diagnosis(function_data *input, int input_num, function_data *output, int *output_num)
{
    return self_diagnosis_cb(input, input_num, output, output_num, 1);
}
#endif
int factory_diagnosis_lc_ctrl(function_data* input, int input_num, function_data* output, int* output_num)
{
    return self_diagnosis_cb_new(input, input_num, output, output_num, 0);
}

int charge_diagnosis_lc_ctrl(function_data* input, int input_num, function_data* output, int* output_num)
{
    return self_diagnosis_cb_new(input, input_num, output, output_num, 1);
}

#endif

int ua_getAlarmHistInfo(function_data *input, int input_num, function_data *output, int *output_num)
{
    if (input_num < 2)
    {
        output[0].data     = strdup(_("Please enter the correct page number and page size."));
        output[0].data_len = strlen(output[0].data);
        *output_num = 1;
        return -1;
    }

    int pageId = 0, pageCount = 0;
    pageId = atoi(input[0].data);
    pageCount = atoi(input[1].data);
    struct alarm_history_buf* buf = get_alarm_history_data(pageId, pageCount);
    if (NULL == buf)
    {
        output[0].data     = strdup(_("Error: Failed to get sqlite data!"));
        output[0].data_len = strlen(output[0].data);
        *output_num = 1;
        return -1;
    }

    output[0].data = strdup(buf->buff.bufptr);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;

    lbuff_free(&buf->buff);
    free(buf);
    return 0;
}

int ua_getOptLogInfo(function_data *input, int input_num, function_data *output, int *output_num)
{
    if (input_num < 2)
    {
        output[0].data     = strdup(_("Please enter the correct page number and page size."));
        output[0].data_len = strlen(output[0].data);
        *output_num = 1;
        return -1;
    }

    int pageId = 0, pageCount = 0;
    pageId = atoi(input[0].data);
    pageCount = atoi(input[1].data);

    struct opt_log_buf* buf = get_opt_log_data(pageId, pageCount);
    if (NULL == buf)
    {
        output[0].data     = strdup(_("Error: Failed to get sqlite data!"));
        output[0].data_len = strlen(output[0].data);
        *output_num = 1;
        return -1;
    }

    output[0].data = strdup(buf->buff.bufptr);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;

    lbuff_free(&buf->buff);
    free(buf);
    return 0;
}

int adapter_analysis(char *dev, char *function, double *value)
{
    int ret = -1;
    if(0 == strcmp(function, FUNCTION_SET_POWER))
    {
        ret = pe_set_power(dev, *value);
    }
    else if(0 == strcmp(function, FUNCTION_SET_REPOWER))
    {
        ret = pe_set_repower(dev, *value);
    }
    else if(0 == strcmp(function, FUNCTION_SET_ONOFF))
    {
        ret = pe_set_onoff(dev,(int)(*value));
    }
    else if(0 == strcmp(function, FUNCTION_SET_MODE))
    {
        ret = pe_set_mode(dev, (int)(*value));
    }
    else if(0 == strcmp(function, FUNCTION_SET_CONNECT))
    {
        ret = pe_set_connect(dev, (int)(*value));
    }
    else if(0 == strcmp(function, FUNCTION_GET_POWER))
    {
        ret = pe_get_power(dev, value);
    }
    else if(0 == strcmp(function, FUNCTION_GET_REPOWER))
    {
        ret = pe_get_repower(dev, value);
    }
    else if(0 == strcmp(function, FUNCTION_GET_ONOFF))
    {
        int val = pe_get_onoff(dev);
        if(val < 0)
        {
            ret = val;

            if(ret==-3)
                ret = -2;
        }
        else 
        {
            *value = val;
            ret = 0;

        }
    }
    else if(0 == strcmp(function, FUNCTION_GET_CONNECT))
    {
        int val = pe_get_connect(dev);
        if(val < 0)
        {
            ret = val;
        }
        else 
        {
            if(ret==-3)
                ret = -2;
            *value = val;
            ret = 0;
        }
    }
    return ret;
}

/**
 * @description: 调用设置接口-下层对应用层提供的接口（调用适配器或点位映射）
 * @param {function_data} *input
 * @param {int} input_num
 * @param {function_data} *output
 * @param {int} *output_num
 * @return {*}
 */
int ua_set_function(function_data *input, int input_num, function_data *output, int *output_num)
{
    if (input_num < 3 || input[0].data_len > TAG_NAME_LEN || input[1].data_len > TAG_NAME_LEN || input[2].data_len > TAG_NAME_LEN)
    {
        output[0].data     = strdup(_("Please enter the correct page number and page size."));
        output[0].data_len = strlen(output[0].data);
        *output_num = 1;
        return -1;
    }
    int ret = 0;
    char str[3][TAG_NAME_LEN + 2] = {"", "", ""};
    struct lnxall_buff lbuf;
    lbuff_init(&lbuf, 100);
    
    memcpy(str[0], input[0].data, input[0].data_len);
    memcpy(str[1], input[1].data, input[1].data_len);
    memcpy(str[2], input[2].data, input[2].data_len);
    
    char *endptr;
    double value;

    // 将字符串转换为 double
    value = strtod(str[2], &endptr);

    // 检查转换是否成功
    if (str[2] == endptr || (errno == ERANGE && value == HUGE_VAL && value == -HUGE_VAL)) {
        ret = 1;
        goto END;
    }

    ret = adapter_analysis(str[0], str[1], &value);
    if(ret)
    {
        ret = dev_set_function(str[0], str[1], value);
    }

    if(-1 == ret)
    {
        ret = 2;
        goto END;
    }

    if(-2 == ret)
    {
        ret = 3;
        // goto END;
    }
    
END:
    lbuff_sprintf(&lbuf, "{\"data\":%d,\"info\":%d}", ret, ret);

    output[0].data     = strdup(lbuf.bufptr);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}

/**
 * @description: 调用数据获取接口-下层对应用层提供的接口（调用适配器或点位映射）
 * @param {function_data} *input
 * @param {int} input_num
 * @param {function_data} *output
 * @param {int} *output_num
 * @return {*}
 */
int ua_get_function(function_data *input, int input_num, function_data *output, int *output_num)
{
    if (input_num < 2)
    {
        output[0].data     = strdup(_("Please enter the correct page number and page size."));
        output[0].data_len = strlen(output[0].data);
        *output_num = 1;
        return -1;
    }
    double value = 0;
    int ret = 0;
    struct lnxall_buff lbuf;
    lbuff_init(&lbuf, 100);
    char str[2][TAG_NAME_LEN + 2] = {"", ""};
    
    memcpy(str[0], input[0].data, input[0].data_len);
    memcpy(str[1], input[1].data, input[1].data_len);
    ret = adapter_analysis(str[0], str[1], &value);
    if(ret)
    {
        ret = dev_get_function_double(str[0], str[1], &value);
    }
    if(-1 == ret)
    {
        ret = 2;
        goto END;
    }

    if(-2 == ret)
    {
        ret = 3;
        goto END;
    }

END:
    
    lbuff_sprintf(&lbuf, "{\"data\":%.1lf,\"info\":%d}", value, ret);

    output[0].data     = strdup(lbuf.bufptr);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}


int ua_cbsetgen(function_data *input, int input_num, function_data *output, int *output_num)
{
    int fd;
    char * name, * p;
    char * content;

    fd = -1;
    name = NULL;
    content = NULL;
    if (input_num < 2)
        goto ERR;

    name = (input[0].data != NULL) ? strdup(input[0].data) : NULL;
    if (name == NULL || name[0] == '\0')
        goto ERR;

    content = input[1].data;
    if (content == NULL || content[0] == '\0' || input[1].data_len <= 0)
        goto ERR;

    p = strrchr(name, '/');
    if (p != NULL) {
        *p = '\0';
        /* create directory first, ignore error */
        mkdir(name, 0755);
        *p = '/';
    }

    fd = open(name, O_TRUNC | O_CREAT | O_WRONLY, 0644);
    if (fd < 0) {
        int err = errno;
        ems_syslog(LOG_ERR, "Failed to open '%s': %s", name, strerror(err));
        goto ERR;
    }

    if (write(fd, content, (size_t) input[1].data_len) != (size_t) input[1].data_len) {
        int err = errno;
        ems_syslog(LOG_ERR, "Failed to write '%s': %s", name, strerror(err));
        goto ERR;
    }

    *output_num = 1;
    output[0].data = strdup("{\"result\":\"ok\"}");
    server_add_new_log(LOG_CODE_OPC_WTITE_FILE, "EMS", LOG_MODE_TRIG, 1, name);
    output[0].data_len = strlen(output[0].data);

    close(fd);
    free(name);
    return 0;

ERR:
    output[0].data = strdup("{\"result\":\"error\",\"info\":\"write any configuration file\"}");
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;

    if (fd >= 0)
        close(fd);
    if (name != NULL)
        free(name);
    return 0;
}


static int ua_lcAgentSet(function_data *input,int input_num,function_data *output,int *output_num)
{
    int len, ret, appr, sysr;
    char name[256], * reply;
    char data_tmp[1024];
    const char * cmd = NULL;

    appr = sysr = 0;
    reply = NULL;
    if (input_num <= 0)
        goto ERR;

    len = input[0].data_len;
    if (len <= 0 || len >= sizeof(name))
        len = sizeof(name) - 1;
    memcpy(name, input[0].data, (size_t) len);
    name[len] = '\0';

    len = input[1].data_len;
    if (len <= 0 || len >= sizeof(data_tmp))
        len = sizeof(data_tmp) - 1;
    memcpy(data_tmp, input[1].data, (size_t) len);
    data_tmp[len] = '\0';

    *output_num = 1;

    if (strcmp(data_tmp, LC_AGENT_RESTART) == 0) {
        appr = 1;
        cmd = LC_AGENT_RESTART;
    } else if (strcmp(data_tmp, LC_AGENT_REBOOT) == 0) {
        sysr = 1;
        cmd = LC_AGENT_REBOOT;
    } else if (strcmp(data_tmp, LC_AGENT_UPGRADE) == 0) {
        cmd = LC_AGENT_UPGRADE;
    } else if (strcmp(data_tmp, LC_AGENT_UPGRADEN) == 0) {
        cmd = LC_AGENT_UPGRADEN;
    } else if (strcmp(data_tmp, LC_AGENT_TEMPLATESYNC) == 0) {
        cmd = LC_AGENT_TEMPLATESYNC;
    }

    ret = -1;
    if (cmd != NULL) {
        if (appr == 0 && sysr == 0)
            ret = discovery_device_cmd(name, cmd, &reply);
        else
            ret = discovery_device_reboot(name, sysr, appr);
    }

    if (ret != 0) {
        output[0].data = strdup("{\"result\":\"error\"}");
    } else {
        if (reply != NULL) {
            output[0].data = reply;
            reply = NULL;
        } else
            output[0].data = strdup("{\"result\":\"ok\"}");
    }
    output[0].data_len = strlen(output[0].data);
    free(reply);
    return 0;

ERR:
    sprintf(data_tmp,"{\"result\":\"error\",\"info\":\"input name list:\"" LC_AGENT_RESTART "," LC_AGENT_REBOOT "," LC_AGENT_UPGRADE "," LC_AGENT_UPGRADEN "," LC_AGENT_TEMPLATESYNC "\"}");
    output[0].data = strdup(data_tmp);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    if (reply != NULL)
        free(reply);
    return 0;
}

int ua_cbset(function_data *input,int input_num,function_data *output,int *output_num)
{
    char name[256] = {0};
    StringBuffer *data_tmp = StringBuffer_Create(1024);

    if (input_num <= 0)
        goto ERR;
    memcpy(name, input[0].data, input[0].data_len);
    name[input[0].data_len] = '\0';
    StringBuffer_Append(data_tmp, "%s", input[1].data);

    *output_num = 1;
    if (save_ems_string_to_file(name, data_tmp->buffer_str) < 0)
    {
        goto ERR;
    }
    else
    {
        output[0].data = strdup("{\"result\":\"ok\"}");
    }
    server_add_new_log(LOG_CODE_OPC_WTITE_FILE, "EMS", LOG_MODE_TRIG, 1, name);
    output[0].data_len = strlen(output[0].data);

    StringBuffer_Free(data_tmp);
    return 0;
ERR:
    sprintf(data_tmp->buffer_str,"{\"result\":\"error\",\"info\":\"input name list:"PRICE_INFO_NAME","DEVICE_CONFIG_NAME \
    ","PORT_CONFIG_NAME","PROPERTY_INFO_NAME","TRIGGER_INFO_NAME","EMS_LC_LIST","EMS_LC_SETIPADDR", "EMMS2_CONFIG_NAME" , "STACTRL_CONFIG_NAME \
    ", " DEV_GROUP_INFO_NAME ";input content must be json\"}");
    output[0].data = strdup(data_tmp->buffer_str);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;

    StringBuffer_Free(data_tmp);
    return 0;
}

int ua_dev_message_GFP_T(function_data *input,int input_num,function_data *output,int *output_num)
{
    char name[256] = {0};
    char timeout_s[32] = {0};
    char data_tmp[1024] = {0};
    if((input_num<=0)||(input[0].data_len<=0)||(input[1].data_len<=0)||(input[2].data_len<=0))
    {
       goto ERR;
    }
    memcpy(name,input[0].data,input[0].data_len);
    name[input[0].data_len] = '\0';

    memcpy(timeout_s,input[1].data,input[1].data_len);
    timeout_s[input[1].data_len] = '\0';
       
    memcpy(data_tmp,input[2].data,input[2].data_len);
    data_tmp[input[2].data_len] = '\0';

    *output_num = 1;
    
    unsigned char send_hex[256] = {0};
    int send_hex_len = 0;
    unsigned char recv_hex[256] = {0};

    int tiemout = atoi(timeout_s);
    send_hex_len = GEN_ARRASIC2HEX((unsigned char *)data_tmp,send_hex,strlen(data_tmp));
    if(send_hex_len<=0)
        goto ERR;
    char log_msg_tmp[1024] = {0};
    snprintf(log_msg_tmp,sizeof(log_msg_tmp),"%s",data_tmp);
    int len = send_data_and_get_return_by_dev_no(name,(tiemout==0)?5000:tiemout,send_hex,send_hex_len,recv_hex,sizeof(recv_hex));
    if(len>0)
    {   
        memset(data_tmp,0,sizeof(data_tmp));
        GEN_ARRHEX2ASIC(recv_hex,(unsigned char *)data_tmp,len,' ');
        output[0].data = strdup(data_tmp);
        strcat(log_msg_tmp,",");
        strcat(log_msg_tmp,data_tmp);
        server_add_new_log(LOG_CODE_OPC_GFP,name,LOG_MODE_TRIG,1,log_msg_tmp);
    }
    else if(len==-1)
    {
        output[0].data = strdup(_("Device not found"));
        server_add_new_log(LOG_CODE_OPC_GFP,name,LOG_MODE_TRIG,2,log_msg_tmp);
    }
    else if(len==-2)
    {
        output[0].data = strdup(_("Timeout or port not successfully opened"));
        server_add_new_log(LOG_CODE_OPC_GFP,name,LOG_MODE_TRIG,2,log_msg_tmp);
    }
    output[0].data_len = strlen(output[0].data);
    return 0;

ERR:
    output[0].data     = strdup(_("Parameter error"));
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}

int ua_upgrade(function_data *input,int input_num,function_data *output,int *output_num)
{
    char url[512] = {0};
    if (input_num<1)
    {
        goto ERR;
    }
    
    memcpy(url,input[0].data,input[0].data_len);
    url[input[0].data_len] = '\0';

    *output_num = 2;
    char dataBuff[sizeof(url) + 64] = {0};
    if (strlen(url)>0)
    {
        cmd_call("rm "EMS_UPGRADE_FILE,10,NULL,0);
	    sprintf(dataBuff,"wget %s -O "EMS_UPGRADE_FILE,url);
    }
    else
    {
        goto ERR;
    }

    if(cmd_call(dataBuff,10,NULL,1)!=0) goto ERR;

    output[0].data = strdup("0");
    output[0].data_len = strlen(output[0].data);
    output[1].data     = strdup(_("File retrieval successful"));
    output[1].data_len = strlen(output[1].data);
    server_add_new_log(LOG_CODE_OPC_UPGRADE,"EMS",LOG_MODE_TRIG,1,NULL);
    return 0;
ERR:
    output[0].data = strdup("-1");
    output[0].data_len = strlen(output[0].data);
    output[1].data     = strdup(_("File retrieval failed"));
    output[1].data_len = strlen(output[1].data);
    *output_num = 2;
    return 0;
}

int ua_restart(function_data *input,int input_num,function_data *output,int *output_num)
{
    output[0].data     = strdup(_("The system is restarting."));
    output[0].data_len = strlen(output[0].data);
    server_add_new_log(LOG_CODE_OPC_RESTART,"EMS",LOG_MODE_TRIG,1,NULL);
    get_pcs_ctrl_var()->restart_code = 1;
    *output_num = 1;
    return 0;
}

int reset_g100_state(function_data* input, int input_num, function_data* output, int* output_num)
{
    char result [512] = {0};
    if (input_num == 1 && function_data_cmp_string(&input[0], "reset") == 0)
    {
        g100_protoec_unlock(&g100_protect, result);

    }
    else if (input_num == 1 && function_data_cmp_string(&input[0], "unlock") == 0)
    {
        g100_protoec_admin_unlock(&g100_protect, result);
    }
    else
    {
        output[0].data     = strdup("must be a string in [\"reset\",\"unlock\"]");
        output[0].data_len = strlen(output[0].data);
        *output_num        = 1;
        return 0;
    }
    output[0].data     = strdup(result);
    output[0].data_len = strlen(output[0].data);
    *output_num        = 1;
    return 0;
}

int ua_get_alarm_info(function_data *input,int input_num,function_data *output,int *output_num)
{
    struct lnxall_buff lbuf;
    lbuff_init(&lbuf, 8192);
    lbuff_append(&lbuf, "{", 1);
    get_alarm_string(&lbuf, 1);
    lbuff_append(&lbuf, "}", 1);

    output[0].data = strdup(lbuf.bufptr);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;

    lbuff_free(&lbuf);
    return 0;
}

int ua_get_net_status(function_data *input,int input_num,function_data *output,int *output_num)
{
    char data_dist[1024*16] = {0};
    sprintf(data_dist,"{");
    get_net_string(data_dist+1);
    strcat(data_dist,"}");
    output[0].data = strdup(data_dist);
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}

int ua_get_northcfg(function_data *input,int input_num,function_data *output,int *output_num)
{
    char *data_dist;
    data_dist = read_file_data(N_MQTT_NORTH_CFG_FILE);
    output[0].data = strdup(data_dist);
    output[0].data_len = strlen(output[0].data);
    if (data_dist != NULL) 
    {
        free(data_dist); 
    }
    *output_num = 1;
    return 0;
}

int ua_get_north_conn_status(function_data *input,int input_num,function_data *output,int *output_num)
{
    char protocol[16] = {0};
    char data_tmp[1024*4] = {0};

    if (input_num <= 0)
        goto ERR;
    memcpy(protocol,input[0].data,input[0].data_len);
    protocol[input[0].data_len] = '\0';
    int channel_index = atoi(protocol);
    if(channel_index >= 10 || channel_index < 0)
        goto ERR;
    *output_num = 1;
    sprintf(data_tmp, "{\"result\":\"%d\"}", north_conn_status[channel_index]);
    output[0].data     = strdup(data_tmp);
    output[0].data_len = strlen(output[0].data);
    return 0;

ERR:
    *output_num = 1;
    sprintf(data_tmp,"{\"result\":\"error\"}");
    output[0].data = strdup(data_tmp);
    output[0].data_len = strlen(output[0].data);
    return 0;
}


int formate_exDisk(function_data *input,int input_num,function_data *output,int *output_num)
{
    char tmp_c[256] = {0};
    int ret = 0;
    const char *disk_path = get_disk_path();
    snprintf(tmp_c, sizeof(tmp_c), "df -h |grep %s", disk_path);
    ret = cmd_call(tmp_c,10,NULL,1);
    if (ret==0)
    {
        sprintf(tmp_c,"ssd_format.sh -f -f");
    }
    else
    {
        sprintf(tmp_c,"ssd_format.sh -f");
    }
    ems_syslog(LOG_NOTICE,"ret :%d,tmp_c:%s",ret,tmp_c);
    ret = cmd_call(tmp_c,10,NULL,1);
    ems_syslog(LOG_NOTICE,"ret2 :%d",ret);
    if(ret==0)
        output[0].data = strdup(_("Format successful"));
    else
        output[0].data = strdup(_("Format failed"));
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    server_add_new_log(LOG_CODE_OPC_FORMATE_DISK,"EMS",LOG_MODE_TRIG,1,NULL);
    return 0;
}
int ua_resboot(function_data *input,int input_num,function_data *output,int *output_num)
{
    output[0].data     = strdup(_("The device is restarting."));
    output[0].data_len = strlen(output[0].data);
    server_add_new_log(LOG_CODE_OPC_REBOOT,"EMS",LOG_MODE_TRIG,1,NULL);
    get_pcs_ctrl_var()->reboot_code = REBOOT_VALUE;
    *output_num = 1;
    return 0;
}


int ua_pingnet(function_data *input,int input_num,function_data *output,int *output_num)
{
    char name[256] = {0};
    if (input_num<=0)
    {
        goto ERR;
    }
    
    memcpy(name,input[0].data,input[0].data_len);
    name[input[0].data_len] = '\0';

    *output_num = 1;
    if(Ping_Test_IP(name,5) == 0)
    {
        server_add_new_log(LOG_CODE_OPC_PING,"EMS",LOG_MODE_TRIG,1,name);
        output[0].data = strdup(_("Success"));
    }
    else
    {
        server_add_new_log(LOG_CODE_OPC_PING,"EMS",LOG_MODE_TRIG,2,name);
        output[0].data = strdup(_("Overtime"));
    }
    output[0].data_len = strlen(output[0].data);
    return 0;
ERR:


    
    output[0].data     = strdup(_("Please rnter the correct IP or domain name."));
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}

int force_set_value(function_data *input,int input_num,function_data *output,int *output_num)
{
    char name[256] = {0};
    char value[32] = {0};
    if (input_num<=1)
    {
        goto ERR;
    }
    memcpy(name,input[0].data,input[0].data_len);
    name[input[0].data_len] = '\0';
    memcpy(value,input[1].data,input[1].data_len);
    value[input[1].data_len] = '\0';

    tag_value_t tag_value;
    if (strchr(value,'.')!=NULL)
    {
        tag_value.type = TYPE_TAG_FLOAT;
        tag_value.value.to_float = atof(value);
    }
    else
    {
        tag_value.type = TYPE_TAG_INT;
        tag_value.value.to_int = atoi(value);
    }
    int ret = reflush_data_by_name_force(get_proto_forward_var(),name,&tag_value);
    *output_num = 1;
    if (ret == 0)
    {
        // server_add_new_log(LOG_CODE_OPC_PING,LOG_MODE_TRIG,1,name);
        output[0].data = strdup(_("Success"));
    }
    else
    {
        // server_add_new_log(LOG_CODE_OPC_PING,LOG_MODE_TRIG,2,name);
        output[0].data = strdup(_("Failure"));
    }
    output[0].data_len = strlen(output[0].data);
    return 0;
ERR:
    output[0].data     = strdup(_("Parameter error"));
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}

int cancel_force_set(function_data *input,int input_num,function_data *output,int *output_num)
{
    char name[256] = {0};
    char *tmp = NULL;
    if (input_num>0)
    {
        memcpy(name,input[0].data,input[0].data_len);
        name[input[0].data_len] = '\0';
        tmp = name;
    }
    
    int ret = clean_force_tag(get_proto_forward_var(),tmp);
    *output_num = 1;
    if (ret == 0)
    {
        // server_add_new_log(LOG_CODE_OPC_PING,LOG_MODE_TRIG,1,name);
        output[0].data = strdup(_("Success"));
    }
    else
    {
        // server_add_new_log(LOG_CODE_OPC_PING,LOG_MODE_TRIG,2,name);
        output[0].data = strdup(_("Failure"));
    }
    output[0].data_len = strlen(output[0].data);
    return 0;
}

int change_sys_language(function_data* input, int input_num, function_data* output, int* output_num)
{
    *output_num = 1;
    int ret = 0;
    if (input_num != 1)
    {
        ems_syslog(LOG_ERR, "change_sys_language input_num=%d\n", input_num);
        ret = 1;
    }
    else
    {
        ret = set_sys_language(input[0].data);
    }
    if (ret == 0)
    {
        // server_add_new_log(LOG_CODE_OPC_PING,LOG_MODE_TRIG,1,name);
        output[0].data = strdup(_("Success"));
    }
    else
    {
        output[0].data = strdup(_("Failure"));
    }
    output[0].data_len = strlen(output[0].data);
    return 0;
}
int get_each_tag_force_info(tag_t *tag_this,void *contex)
{
    if (tag_this->force_set_cache.valid == true)
    {
        cJSON_AddNumberToObject((cJSON *)contex,tag_this->dev_tag_name,tag_this->data_type == TYPE_TAG_INT?tag_this->read_cache.to_int:tag_this->read_cache.to_float);
    }
    return 0;
}
int get_force_set_value_list(function_data *input,int input_num,function_data *output,int *output_num)
{
    cJSON *root = cJSON_CreateObject();
    int ret = do_some_action_foreach_tag(get_proto_forward_var(),get_each_tag_force_info,root);
    *output_num = 1;
    if (ret == 0)
    {
        // server_add_new_log(LOG_CODE_OPC_PING,LOG_MODE_TRIG,1,name);
        output[0].data = cJSON_Print(root);  
    }
    else
    {
        // server_add_new_log(LOG_CODE_OPC_PING,LOG_MODE_TRIG,2,name);
        output[0].data = strdup(_("Failure"));
    }
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    output[0].data_len = strlen(output[0].data);
    return 0;
}
int ua_console_cmd(function_data *input,int input_num,function_data *output,int *output_num)
{
    if (input_num<=0)
    {
        goto ERR;
    }
    char *dataBuff = calloc(input[0].data_len+1,1);
    memcpy(dataBuff,input[0].data,input[0].data_len);

    *output_num = 1;
    char *diststring = NULL;
    int ret = cmd_call(dataBuff,10,&diststring,1);
    if (diststring!=NULL)
    {
        char log_msg_tmp[1024*4]={0};
        snprintf(log_msg_tmp,sizeof(log_msg_tmp),"%s,%s",dataBuff,diststring);
        server_add_new_log(LOG_CODE_OPC_CONSOLE,"EMS",LOG_MODE_TRIG,1,log_msg_tmp);
        output[0].data = diststring;
    }
    else
    {
        if (ret < 0)
        {
            server_add_new_log(LOG_CODE_OPC_CONSOLE,"EMS",LOG_MODE_TRIG,2,dataBuff);
            output[0].data = strdup(_("Unknown error"));
        }
        else
        {
            server_add_new_log(LOG_CODE_OPC_CONSOLE,"EMS",LOG_MODE_TRIG,1,dataBuff);
            output[0].data = strdup(_("Success"));
        }
    }
    
    output[0].data_len = strlen(output[0].data);
    return 0;
ERR:
    output[0].data     = strdup(_("Please enter the correct IP or domain name."));
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}

void write_mqtt_cfg(int index, cJSON *mqtt)
{
    char *pdata = NULL;
    cJSON* mqttArray = NULL;
    cJSON* root = NULL;
    pdata = read_file_data(N_MQTT_NORTH_CFG_FILE);
    if (pdata == NULL)
    {
        printf( "read cfg file %s error\n", N_MQTT_NORTH_CFG_FILE);
        goto END;
    }
    root = cJSON_Parse(pdata);
    if (!root) {
        ems_syslog(LOG_ERR, "%s json parse error",N_MQTT_NORTH_CFG_FILE);
        goto END;
    }
    if(index <10)
    {
        mqttArray = cJSON_GetObjectItemCaseSensitive(root, "standard");
        if (!cJSON_IsArray(mqttArray)) {
        ems_syslog(LOG_ERR, "standard is not an array");
        goto END;
        }
        if (cJSON_GetArraySize(mqttArray) == 0) {
            ems_syslog(LOG_ERR, "standard array is empty");
            goto END;
        }
        int found = 0;
        for (int i = 0; i < cJSON_GetArraySize(mqttArray); i++) {
            cJSON* item = cJSON_GetArrayItem(mqttArray, i);
            cJSON* itemIndex = cJSON_GetObjectItemCaseSensitive(item, "index");
            if (cJSON_IsNumber(itemIndex) && itemIndex->valueint == index) {
                ems_syslog(LOG_ERR, "replace object in mqttArray [%d]", index);
                cJSON_ReplaceItemInArray(mqttArray, i, mqtt);
                found = 1;
                break;
            }
        }
        if (!found) {
            ems_syslog(LOG_ERR, "change now mqttArray [%d] object", index);
            cJSON_AddItemToArray(mqttArray, mqtt);
        }
    }
    else
    {
        mqttArray = cJSON_GetObjectItemCaseSensitive(root, "custom");
        if (!cJSON_IsArray(mqttArray)) {
            ems_syslog(LOG_ERR, "custom is not an array");
            goto END;
        }
        if (cJSON_GetArraySize(mqttArray) == 0) {
            ems_syslog(LOG_ERR, "custom array is empty");
            goto END;
        }
        if (cJSON_GetArraySize(mqttArray) < (index+1-10))      // 判断mqtt内是否有当前序号的对象若有两个通道，现在index为1，说明要改第二个通道
        {
            ems_syslog(LOG_ERR, "change now mqttArray [%d] object",index-10);
            cJSON_AddItemToArray(mqttArray, mqtt);
        }
        else
        {
            ems_syslog(LOG_ERR, "replace object in mqttArray [%d]", index-10);
            // cJSON* oldMqtt = cJSON_GetArrayItem(mqttArray, index);
            cJSON_ReplaceItemInArray(mqttArray, index-10, mqtt);
        }
    }
    char* updatedContent = cJSON_Print(root);
    if (updatedContent != NULL) {
        write_file_data(N_MQTT_NORTH_CFG_FILE, updatedContent, strlen(updatedContent));
        free(updatedContent);
    } else {
        ems_syslog(LOG_ERR, "cJSON_Print error");
    }
END:  
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }
}

int delete_mqtt_cfg(int index)
{
    int ret = -1;
    char *pdata = NULL;
    cJSON* mqttArray = NULL;
    cJSON* root = NULL;
    pdata = read_file_data(N_MQTT_NORTH_CFG_FILE);
    if (pdata == NULL)
    {
        printf( "read cfg file %s error\n", N_MQTT_NORTH_CFG_FILE);
        goto END;
    }
    root = cJSON_Parse(pdata);
    if (!root) {
        ems_syslog(LOG_ERR, "%s json parse error",N_MQTT_NORTH_CFG_FILE);
        goto END;
    }
    mqttArray = cJSON_GetObjectItemCaseSensitive(root, "standard");
    if (!cJSON_IsArray(mqttArray)) {
        ems_syslog(LOG_ERR, "standard is not an array");
        goto END;
    }
    if (cJSON_GetArraySize(mqttArray) == 0) {
        ems_syslog(LOG_ERR, "standard array is empty");
        goto END;
    }
    int found = 0;
    for (int i = 0; i < cJSON_GetArraySize(mqttArray); i++) {
        cJSON* item = cJSON_GetArrayItem(mqttArray, i);
        cJSON* itemIndex = cJSON_GetObjectItemCaseSensitive(item, "index");
        if (cJSON_IsNumber(itemIndex) && itemIndex->valueint == index) {
            cJSON_DeleteItemFromArray(mqttArray, i);
            ems_syslog(LOG_ERR, "删除standard数组中 [%d] 通道", index);
            ret = 0;
            found = 1;
            break;
        }
    }
    if (!found) {
        ems_syslog(LOG_ERR, "未找到index为 [%d] 的通道", index);
        ret = -2;
    }
    char* updatedContent = cJSON_Print(root);
    if (updatedContent != NULL) {
        write_file_data(N_MQTT_NORTH_CFG_FILE, updatedContent, strlen(updatedContent));
        free(updatedContent);
    } else {
        ems_syslog(LOG_ERR, "cJSON_Print error");
    }
END:  
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }
    return ret;
}

void write_north_control(int control)
{
    char *pdata = NULL;
    cJSON* root = NULL;
    pdata = read_file_data(N_MQTT_NORTH_CFG_FILE);
    if (pdata == NULL)
    {
        ems_syslog(LOG_ERR,"read cfg file %s error\n", N_MQTT_NORTH_CFG_FILE);
        goto END;
    }
    ems_syslog(LOG_ERR,"before change :%s",pdata);
    root = cJSON_Parse(pdata);
    if (!root) {
        ems_syslog(LOG_ERR, "%s json parse error",N_MQTT_NORTH_CFG_FILE);
        goto END;
    }
    cJSON *north_control_item = cJSON_GetObjectItemCaseSensitive(root, "north_control");
    if (north_control_item) {
        cJSON_SetNumberValue(north_control_item, control);
    } else {
        ems_syslog(LOG_ERR,"north_control field not found");
        goto END;
    }
    
    char* updatedContent = cJSON_Print(root);
    ems_syslog(LOG_ERR,"after change :%s",updatedContent);
    if (updatedContent != NULL) {
        write_file_data(N_MQTT_NORTH_CFG_FILE, updatedContent, strlen(updatedContent));
        free(updatedContent);
    } else {
        ems_syslog(LOG_ERR, "cJSON_Print error");
    }
END:  
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }
}


int ua_change_mqttcfg(function_data *input,int input_num,function_data *output,int *output_num)
{
    char index[10] = {0};
    char data_tmp[1024] = {0};
    cJSON*mqtt = NULL;
    if (input_num <= 0)
        goto ERR;
    memcpy(index, input[0].data, input[0].data_len);
    index[input[0].data_len] = '\0';
    ems_syslog(LOG_ERR, " input[1].data: %s", input[1].data);
    memcpy(data_tmp,input[1].data,input[1].data_len);
    data_tmp[input[1].data_len] = '\0';
    *output_num = 1;
    mqtt = cJSON_Parse(data_tmp);
    if (!mqtt) {
        goto ERR;
    }
    else
    {
        write_mqtt_cfg(atoi(index), mqtt);
    }

    output[0].data = strdup("{\"result\":\"ok\"}");
    output[0].data_len = strlen(output[0].data);
    northcfg_change = true;
    // cJSON_Delete(mqtt);
    return 0;
ERR:
    output[0].data = strdup("输入正确格式的配置");
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    if (mqtt != NULL)
    {
        cJSON_Delete(mqtt);
    }
    return 0;
}

int ua_delete_mqttcfg(function_data *input,int input_num,function_data *output,int *output_num)
{
    char index[10] = {0};
    if (input_num <= 0)
        goto ERR;
    memcpy(index, input[0].data, input[0].data_len);
    index[input[0].data_len] = '\0';
    *output_num = 1;

    int ret = delete_mqtt_cfg(atoi(index));
    if(ret == 0)
    {
        output[0].data = strdup("{\"result\":\"ok\"}");
        output[0].data_len = strlen(output[0].data);
        return 0;
    }
    else if(ret == -1)
    {
        output[0].data = strdup("{\"result\":\"error\"}");
        output[0].data_len = strlen(output[0].data);
        return 0;
    }
    else if(ret == -2)
    {
        output[0].data = strdup("该通道不允许删除");
        output[0].data_len = strlen(output[0].data);
        return 0;
    }
ERR:
    output[0].data = strdup("输入正确格式的配置");
    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}


static int sprint_log_info(ONE_LOG_INFO *log_info,void *contex)
{
    char data_tmp[512]={0};
    snprintf(data_tmp,512,"{\"logCode\":%d,\"entityInstance\":\"%s\",\"value\":%d,\"additionalParam\":\"%s\",\"raiseTime\":%ld},",log_info->log_code,log_info->no,log_info->value,log_info->add,log_info->raiseTime);
    strcat((*(char **)contex),data_tmp);
    return 0;
}

int ua_get_log(function_data *input,int input_num,function_data *output,int *output_num)
{
    if (input_num<2)
    {
        goto ERR;
    }
    char pageSize_c[8] = {0};
    memcpy(pageSize_c,input[0].data,input[0].data_len);
    char pageNum_c[8] = {0};
    memcpy(pageNum_c,input[1].data,input[1].data_len);

    int pageSize = atoi(pageSize_c);
    int pageNum = atoi(pageNum_c);

    char *data_info=calloc(1,1024*10*10);
    sprintf(data_info,"{\"messages\":[");
    client_get_log_with_offset(-1,(pageNum-1)*pageSize+1,pageSize,sprint_log_info,&data_info);
    if (strlen(data_info)>strlen("{\"messages\":["))
    {
        data_info[strlen(data_info)-1] = '\0';
    }
    strcat(data_info,"]}");
    output[0].data = data_info;
    output[0].data_len = strlen(output[0].data);

    char num_cha[10] = {0};
    snprintf(num_cha,sizeof(num_cha),"%d",get_all_log_num());
    output[1].data = strdup(num_cha);
    output[1].data_len = strlen(output[1].data);
    *output_num = 2;
    return 0;
ERR:
    output[0].data = strdup(_("Please enter the correct page number and page size."));
    output[0].data_len = strlen(output[0].data);

    char num_cha1[10] = {0};
    snprintf(num_cha1,sizeof(num_cha1),"%d",get_all_log_num());
    output[1].data = strdup(num_cha1);
    output[1].data_len = strlen(output[1].data);
    *output_num = 2;
    return 0;
}
//--------------------------------------------------------------------------------------------------------------------------------
static const lc_it *get_lc_by_sn_or_no(const char *sn_or_no)
{
    pcs_ctrl_var_t *var = get_pcs_ctrl_var();
    int lc_cnt = var->lc_list_len;
    lc_it *lc_list = var->lc_list;
    for (int i = 0; i < lc_cnt; i++)
    {
        if ((strcmp(lc_list[i].no, sn_or_no) == 0) ||
            (strcmp(lc_list[i].sn, sn_or_no) == 0))
        {
            return (lc_list + i);
        }
    }
    return NULL;
}

static char *read_vlc_cfg(const char *vlc_no, const char *cfg_name)
{
    char buff[128] = {0};
    const char *file_format = NULL;
    struct
    {
        const char *cfg_name;
        const char *file_format;
    } cfg_list[] = {
        {.cfg_name = DEVICE_CONFIG_NAME, .file_format = LC_DEVS_DIR "/%s/" COLLECTOR_DEVICE},
        {.cfg_name = LC_AUTOMATIC_NAME, .file_format = LC_DEVS_DIR "/%s/" AUTOMATIC_FILE_NAME},
    };

    for (int i = 0; i < sizeof(cfg_list) / sizeof(cfg_list[0]); i++)
    {
        if (strcmp(cfg_name, cfg_list[i].cfg_name) == 0)
        {
            file_format = cfg_list[i].file_format;
        }
    }

    if (file_format != NULL)
    {
        snprintf(buff, sizeof(buff), file_format, vlc_no);
        char *content = read_file_data(buff);
        if (content == NULL)
        {
            content = read_file_data(DEF_DEVICE_CONFIG);
        }
        return content;
    }
    else
    {
        proto_syslog(LOG_ERR, "%s config name error:%s", vlc_no, cfg_name);
    }

    return NULL;
}

static int ua_read_lc_cfg(function_data *input, int input_num, function_data *output, int *output_num)
{
    char tmp[32] = {0};
    char url_buff[128] = {0};
    cJSON *info = NULL;
    if (input_num < 2)
    {
        info = cJSON_CreateString(_("This method requires two parameters."));
    }
    else if ((input[0].data_len >= sizeof(tmp)) || (input[1].data_len >= sizeof(tmp)))
    {
        info = cJSON_CreateString(_("Input parameter is too long."));
    }
    else
    {

        strncpy(tmp, input[0].data, input[0].data_len);
        const lc_it *lc = get_lc_by_sn_or_no(tmp);
        if (lc == NULL)
        {
            snprintf(url_buff, sizeof(url_buff), "lc list no find %s", tmp);
            info = cJSON_CreateString(url_buff);
        }
        else
        {
            strncpy(tmp, input[1].data, input[1].data_len);
            tmp[input[1].data_len] = '\0';
            if (lc->type == eLC_TYPE_LC)
            {
                snprintf(url_buff, sizeof(url_buff), "opc.tcp://%s:4841", lc->ipaddr);
                char *ret = ua_client_call_read_cfg(url_buff, tmp);
                if (ret == NULL)
                {
                    info = cJSON_CreateString(_("UA client calling read_cfg error"));
                }
                else
                {
                    output[0].data = ret;
                }
            }
            else
            {
                output[0].data = read_vlc_cfg(lc->no, tmp);
                if (output[0].data == NULL)
                {
                    output[0].data = strdup("null");
                }
            }
        }
    }
    //
    if (info != NULL)
    {
        cJSON *obj = cJSON_CreateObject();
        cJSON_AddItemToObject(obj, "result", cJSON_CreateString("error"));
        cJSON_AddItemToObject(obj, "info", info);
        output[0].data = cJSON_PrintUnformatted(obj);
        cJSON_Delete(obj);
    }

    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}


static char *write_vlc_cfg(const char *vlc_no, const char *cfg_name, char *cfg_value, int len)
{
    char buff[128] = {0};
    char *ret_json = NULL;
    const char *file_format = NULL;
    struct
    {
        const char *cfg_name;
        const char *file_format;
    } cfg_list[] = {
        {.cfg_name = DEVICE_CONFIG_NAME, .file_format = LC_DEVS_DIR "/%s/" COLLECTOR_DEVICE},
        {.cfg_name = LC_AUTOMATIC_NAME, .file_format = LC_DEVS_DIR "/%s/" AUTOMATIC_FILE_NAME},
    };

    for (int i = 0; i < sizeof(cfg_list) / sizeof(cfg_list[0]); i++)
    {
        if (strcmp(cfg_name, cfg_list[i].cfg_name) == 0)
        {
            file_format = cfg_list[i].file_format;
        }
    }

    if (file_format != NULL)
    {
        snprintf(buff, sizeof(buff), file_format, vlc_no);
        proto_syslog(LOG_NOTICE, "%s write %s -> %s", vlc_no, cfg_name, buff);
        if (0 != write_file_data(buff, cfg_value, len))
        {
            proto_syslog(LOG_ERR, "%s write file error:%s", vlc_no, cfg_name);
            if (asprintf(&ret_json, "{\"result\":\"error\", \"info\":\"write %s error\"}", cfg_name) < 0)
            {
                ret_json = strdup("{\"result\":\"error\", \"info\":\"asprintf error\"}");
            }
        }
        else
        {
            ret_json = strdup("{\"result\":\"ok\"}");
        }
    }
    else
    {
        proto_syslog(LOG_ERR, "%s config name error:%s", vlc_no, cfg_name);
        ret_json = strdup("{\"result\":\"error\", \"info\":\"config name error\"}");
    }

    return ret_json;
}

static int ua_write_lc_cfg(function_data *input, int input_num, function_data *output, int *output_num)
{
    char lc_no[16] = {0};
    char cfg_name[32] = {0};
    char url_buff[128] = {0};
    cJSON *info = NULL;
    if (input_num < 2)
    {
        info = cJSON_CreateString(_("This method requires three parameters."));
    }
    else if ((input[0].data_len >= sizeof(lc_no)) || (input[1].data_len >= sizeof(cfg_name)))
    {
        info = cJSON_CreateString(_("Input parameter is too long."));
    }
    else
    {
        memcpy(lc_no, input[0].data, input[0].data_len);
        const lc_it *lc = get_lc_by_sn_or_no(lc_no);
        if (lc == NULL)
        {
            snprintf(url_buff, sizeof(url_buff), "lc list no find %s", lc_no);
            info = cJSON_CreateString(url_buff);
        }
        else
        {
            memcpy(cfg_name, input[1].data, input[1].data_len);
            cfg_name[input[1].data_len] = '\0';
            char *ret = NULL;
            if (lc->type == eLC_TYPE_LC)
            {
                const char *ip = lc->ipaddr;
                snprintf(url_buff, sizeof(url_buff), LC_DEVICE_CFG_DIR "/%s/%s.json", lc_no, cfg_name);
                write_file_data(url_buff, input[2].data, input[2].data_len);
                if (strstr(cfg_name, "port_config") != NULL)
                {
                    char *port_cfg = read_file_data(url_buff);
                    if (port_cfg != NULL)
                    {
                        cJSON *root = cJSON_Parse(port_cfg);
                        if (root != NULL)
                        {
                            snprintf(url_buff, sizeof(url_buff), LC_DEVICE_CFG_DIR "/%s/%s", lc_no, DIDO_TEMPLATE_CONFIG);
                            port_cfg_2_dio_template(root, url_buff);
                            cJSON_Delete(root);
                        }
                        free(port_cfg);
                    }
                }
                //
                snprintf(url_buff, sizeof(url_buff), "opc.tcp://%s:4841", ip);
                ret = ua_client_call_write_cfg(url_buff, cfg_name, input[2].data, input[2].data_len);
                if (ret == NULL)
                {
                    info = cJSON_CreateString(_("UA client calling write_cfg error"));
                }
                else
                {
                    output[0].data = ret;
                }
            }
            else
            {
                ret = write_vlc_cfg(lc->no, cfg_name, input[2].data, input[2].data_len);
                if (ret == NULL)
                {
                    info = cJSON_CreateString(_("vlc calling write_cfg error"));
                }
                else
                {
                    output[0].data = ret;
                }
            }
        }
    }

    if (info != NULL)
    {
        cJSON *obj = cJSON_CreateObject();
        cJSON_AddItemToObject(obj, "result", cJSON_CreateString("error"));
        cJSON_AddItemToObject(obj, "info", info);
        output[0].data = cJSON_PrintUnformatted(obj);
        cJSON_Delete(obj);
    }

    output[0].data_len = strlen(output[0].data);
    *output_num = 1;
    return 0;
}

static int ua_create_northcfg(function_data *input,int input_num,function_data *output,int *output_num)
{
    char protocol[256] = {0};
    char data_tmp[1024*4] = {0};

    if (input_num <= 0)
        return -1;

    memcpy(protocol,input[0].data,input[0].data_len);
    protocol[input[0].data_len] = '\0';
    int pro_typ = atoi(protocol);
    if( pro_typ == N_PROTOCOL_TYPE_NONE)
    {   
        if (strncmp(N_TYPE_MQTT, protocol, strlen(N_TYPE_MQTT)) == 0)
        {
            pro_typ = N_PROTOCOL_TYPE_MQTT;
        }
        else if (strncmp(N_TYPE_MODBUSTCP, protocol, strlen(N_TYPE_MQTT)) == 0)
        {
            pro_typ = N_PROTOCOL_TYPE_MODBUS_TCP;
        }
        else if (strncmp(N_TYPE_IEC104, protocol, strlen(N_TYPE_MQTT)) == 0)
        {
            pro_typ = N_PROTOCOL_TYPE_IEC104;
        }
    }

    *output_num = 1;
    if (create_north_cfg(pro_typ, data_tmp) < 0)
    {
        sprintf(data_tmp, "{\"result\":\"1\",\"path\":\"\"}");
        output[0].data     = strdup(data_tmp);
        output[0].data_len = strlen(output[0].data);
    }
    else{
        output[0].data = strdup(data_tmp);
        output[0].data_len = strlen(output[0].data);
	}
    return 0;
}

static int ua_change_control(function_data *input,int input_num,function_data *output,int *output_num)
{
    char protocol[16] = {0};
    char data_tmp[1024*4] = {0};

    if (input_num <= 0)
        goto ERR;
    memcpy(protocol,input[0].data,input[0].data_len);
    protocol[input[0].data_len] = '\0';
    north_control = atoi(protocol);
    write_north_control(north_control);
    *output_num = 1;
	
    output[0].data = strdup("{\"result\":\"ok\"}");
    output[0].data_len = strlen(output[0].data);

    // 北向投切改变时需要更新策略
    north_g_reflush_all_plan = 1;
    BUSINESS_LOG(BLOG_NOTICE, NORTH_ID_0044, NULL, "[北向]:北向投切改变，改变后投切索引为：[%d]", north_control);
    return 0;
ERR:
    sprintf(data_tmp,"{\"result\":\"error\"}");
    output[0].data = strdup(data_tmp);
    output[0].data_len = strlen(output[0].data);
    return 0;
}

static int recovery_alarm_by_manual(function_data *input,int input_num,function_data *output,int *output_num){
    char result[256] ={0};

    if (input_num < 3){
        snprintf(result,sizeof(result), "{\"result\":\"error\"}");
        goto END;
    }

    char* dev_no      = input[0].data;
    int   alarm_code  = atoi(input[1].data);
    int   reason_code = atoi(input[2].data);

    if (delete_alarm_by_code(dev_no, alarm_code, reason_code) == 0)
    {
        snprintf(result,sizeof(result), "{\"result\":\"ok\"}");
    }
    else
    {
        snprintf(result,sizeof(result), "{\"result\":\"fail\"}");
    }

END:
    *output_num        = 1;
    output[0].data     = strdup(result);
    output[0].data_len = strlen(output[0].data);
    return 0;
}


static int recovery_alarm_by_dev_tag(function_data *input,int input_num,function_data *output,int *output_num){
    char result[256] ={0};

    if (input_num != 2){
        snprintf(result,sizeof(result), "{\"result\":\"error\"}");
        goto END;
    }

    char* dev_no      = input[0].data;
    char*   tag_name  = input[1].data;
    snprintf(result,sizeof(result), "%s.%s", dev_no, tag_name);
    if (delete_alarm_by_tag(result) == 0)
    {
        snprintf(result,sizeof(result), "{\"result\":\"ok\"}");
    }
    else
    {
        snprintf(result,sizeof(result), "{\"result\":\"fail\"}");
    }

END:
    *output_num        = 1;
    output[0].data     = strdup(result);
    output[0].data_len = strlen(output[0].data);
    return 0;
}

static int set_equipment_activition(function_data* input, int input_num, function_data* output, int* output_num)
{
    char result[256] = {0};
    ua_set_activition(result);
    *output_num        = 1;
    output[0].data     = strdup(result);
    output[0].data_len = strlen(output[0].data);
    return 0;
}

static int report_alarm_and_template(function_data* input, int input_num, function_data* output, int* output_num)
{
    cJSON* result = cJSON_CreateObject();
    cJSON* info = NULL;
    if (input_num < 3)
    {
        cJSON_AddItemToObject(result, "result", cJSON_CreateString("error"));
        cJSON_AddItemToObject(result, "message", cJSON_CreateString("input num error"));
        goto ERROR;
    }
    char* mqtt_id = input[0].data;
    char* aot     = input[1].data;
    char* lang    = input[2].data;

    mqtt_emms2_var_t* var = get_mqtt_emms2_var_by_id(mqtt_id);
    if (var == NULL)
    {
        cJSON_AddItemToObject(result, "result", cJSON_CreateString("error"));
        cJSON_AddItemToObject(result, "message", cJSON_CreateString("mqtt id not exist"));
        goto ERROR;
    }

    if (strcmp(aot, FUNCTION_TEMPLATE) == 0)
    {
        if (input_num < 4)
        {
            cJSON_AddItemToObject(result, "result", cJSON_CreateString("error"));
            cJSON_AddItemToObject(result, "message", cJSON_CreateString("input num error"));
            goto ERROR;
        }
        char* dev_no = input[3].data;
        if (upload_template_by_dev_no(var, dev_no, lang, TYPE_POST))
        {
            cJSON_AddItemToObject(result, "result", cJSON_CreateString("fail"));
            cJSON_AddItemToObject(result, "message", cJSON_CreateString("upload template fail"));
            goto ERROR;
        }
    }
    else if (strcmp(aot, FUNCTION_ALARMFILE) == 0)
    {
        if (upload_alarminfo_by_language(var, lang, TYPE_POST))
        {
            cJSON_AddItemToObject(result, "result", cJSON_CreateString("fail"));
            cJSON_AddItemToObject(result, "message", cJSON_CreateString("upload alarm file fail"));
            goto ERROR;
        }
    }
    else
    {
        cJSON_AddItemToObject(result, "result", cJSON_CreateString("error"));
        cJSON_AddItemToObject(result, "message", cJSON_CreateString("function id error"));
        goto ERROR;
    }
    cJSON_AddItemToObject(result, "result", cJSON_CreateString("ok"));
    cJSON_AddItemToObject(result, "message", cJSON_CreateString(""));
    goto END;

ERROR:
    info = cJSON_CreateObject();
    cJSON_AddItemToObject(info, "mqtt_id", cJSON_CreateString("must be "MQTT_EMMS2_STATION_ID " or " MQTT_STACTRL_STATION_ID));
    cJSON_AddItemToObject(info, "functionId", cJSON_CreateString("must be "FUNCTION_ALARMFILE " or " FUNCTION_TEMPLATE));
    cJSON_AddItemToObject(info, "lang", cJSON_CreateString("must be zh_CN or en_US"));
    cJSON_AddItemToObject(info, "dev_no", cJSON_CreateString("When the function is a template, it must exist."));
    cJSON_AddItemToObject(result, "info", info);

END:
    *output_num        = 1;
    output[0].data     = cJSON_PrintUnformatted(result);
    output[0].data_len = strlen(output[0].data);
    cJSON_Delete(result);
    return 0;
}
static int get_bms_alarm_info(function_data* input, int input_num, function_data* output, int* output_num)
{

    if (input_num < 3)
    {
        goto END;
    }

    char* dev_no    = input[0].data;
    int   page_size = atoi(input[1].data);
    int   page_no   = atoi(input[2].data);

    struct lnxall_buff buf;
    lbuff_init(&buf, 1024);
    get_bmser_alarm_buf(&buf, dev_no, page_no, page_size);
END:
    *output_num        = 1;
    output[0].data     = strdup(buf.bufptr);
    output[0].data_len = strlen(output[0].data);
    return 0;
}

//--------------------------------------------------------------------------------------------------------------------------------
extern int cabinet_info_tab_count_g;
extern cabinet_info_tab_t cabinet_info_tab[];
//添加系统信息和子节点信息节点
void add_systrm_info(UA_SERVER_PARAM *ua_param)
{
    if(ua_param == NULL) return;
    char tmp_ch[128] = {0};
    UA_NodeId tmpNodeId1;
    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER);
    if (template_info_init() != 0)
    {
        ems_syslog(LOG_ERR, "template_info_init error");
    }
    ua_add_file(ua_param->ua_server, parentNodeId, &system_info.systemNodeId, "System", _("System"));
    {
        ua_add_file(ua_param->ua_server, system_info.systemNodeId, &system_info.aboutInfo.aboutNodeId, "About", _("About"));
        {
            total_cb_t *total_cb_s=calloc(sizeof(total_cb_t),1);
            total_cb_t *total_cb_is=calloc(sizeof(total_cb_t),1);
            total_cb_t *total_cb_es=calloc(sizeof(total_cb_t),1); 
            total_cb_t *total_loc =calloc(sizeof(total_cb_t),1);
            total_cb_t *total_op =calloc(sizeof(total_cb_t),1);
            
            total_cb_s->onRead = read_sim_cb;
            total_cb_s->onWrite = NULL;
            if (0 != creat_a_rw_string(ua_param, _("SIM card number"), "SIM_No", &system_info.aboutInfo.iccidNodeId, system_info.aboutInfo.aboutNodeId, _("Acquisition failed"), total_cb_s))
            {
                free(total_cb_s);
            }
            
            total_cb_is->onRead = read_sim_In;
            total_cb_is->onWrite = NULL;
            if (0 != creat_a_rw_string(ua_param, _("Internal SIM card number"), "Internal_SIM_No", &system_info.aboutInfo.InternaliccidNodeId, system_info.aboutInfo.aboutNodeId, _("Acquisition failed"), total_cb_is))
            {
                free(total_cb_is);
            }

            total_cb_es->onRead = read_sim_Ex;
            total_cb_es->onWrite = NULL;
            if (0 != creat_a_rw_string(ua_param, _("External SIM card number"), "External_SIM_No", &system_info.aboutInfo.ExternaliccidNodeId, system_info.aboutInfo.aboutNodeId, _("Acquisition failed"), total_cb_es))
            {
                free(total_cb_es);
            }

            total_loc->onRead = read_sim_loc;
            total_loc->onWrite = NULL;
            if (0 != creat_a_rw_string(ua_param, _("Coordinate"), "SIM_Location", &system_info.aboutInfo.simLocNodeId, system_info.aboutInfo.aboutNodeId, _("Acquisition failed"), total_loc))
            {
                free(total_loc);
            }

            total_op->onWrite = NULL;
            total_op->onRead = read_activition_time;
            if (0 != creat_a_rw_string(ua_param, _("Activition State"), "Activition_Time", &system_info.aboutInfo.operationNodeId, system_info.aboutInfo.aboutNodeId, _("Not activition"), total_op))
            {
                free(total_op);
            }

            creat_a_base_string(ua_param, "StationNo", _("Site number"), &system_info.aboutInfo.siteNameNodeId, system_info.aboutInfo.aboutNodeId, cabinet_info.cab_id);

            get_board_sn(tmp_ch);
            creat_a_base_string(ua_param, "DevNo", _("Controller number"), &system_info.aboutInfo.cabNumNodeId, system_info.aboutInfo.aboutNodeId, tmp_ch);

            sprintf(tmp_ch,"%d KWH",cabinet_info.cab_capacity);
            creat_a_base_string(ua_param, "Capacity", _("Installed capacity(kWh)"), &system_info.aboutInfo.cabPowerNodeId, system_info.aboutInfo.aboutNodeId, tmp_ch);

            sprintf(tmp_ch,"%s", SW_VERSION);
            creat_a_base_string(ua_param, "EmsVer", _("EMS version"), &system_info.aboutInfo.versionNodeId, system_info.aboutInfo.aboutNodeId, tmp_ch);

            char gw_sn[SN_MAX_LEN] = {0};
            if (0 == get_product_name(gw_sn))
            {
                sprintf(tmp_ch,"%s", gw_sn);
            }
            else
            {
                sprintf(tmp_ch,"unknown");
            }
            creat_a_base_string(ua_param, "EmsProduct", _("Ems Product"), &system_info.aboutInfo.productNodeId, system_info.aboutInfo.aboutNodeId, tmp_ch);

            const char* model = get_board_name();
            if (model)
            {
                sprintf(tmp_ch, "%s", model);
            }
            else
            {
                sprintf(tmp_ch, "unknown");
            }
            creat_a_base_string(ua_param, "EmsModel", _("Ems Model"), &system_info.aboutInfo.modelNodeId, system_info.aboutInfo.aboutNodeId, tmp_ch);


            total_cb_t *total_cb=calloc(sizeof(total_cb_t),1);  
            total_cb->onRead = read_cb_ems;
            if (0 != add_int_to_node(ua_param->ua_server, system_info.aboutInfo.aboutNodeId, true, &system_info.aboutInfo.localNetEmsSuMNodeId, "CountsOfEMS", _("Number of EMS"), total_cb))
            {
                free(total_cb);
            }
        }

        ua_add_file(ua_param->ua_server, system_info.systemNodeId, &tmpNodeId1, "Config", _("Config"));
        {
            total_cb_t *total_cb_s=calloc(sizeof(total_cb_t),1);  //这里必须分开用 结构体对不同类型会保存一些不同参数 是不共用的
            total_cb_s->onRead = read_total_cb;
            total_cb_s->onWrite = write_total_cb;

            total_cb_t *total_cb_i=calloc(sizeof(total_cb_t),1);  
            total_cb_i->onRead = read_total_cb;
            total_cb_i->onWrite = write_total_cb;
            int total_cb_i_use_num = 0;
            int total_cb_s_use_num = 0;
            cabinet_info_t* pcfg = get_cabinet_info();

            for(int i =0;i<cabinet_info_tab_count_g;i++)
            {
                if (strcmp(cabinet_info_tab[i].cab_key, "location") == 0)
                    continue;
                if(strcmp(cabinet_info_tab[i].cab_type,"string")==0)
                {
                    if (0 == creat_a_rw_string(ua_param,cabinet_info_tab[i].cab_show_name,cabinet_info_tab[i].cab_key, NULL,tmpNodeId1,
                        (char *)pcfg + cabinet_info_tab[i].cab_member_ofs,total_cb_s))
                    {
                        total_cb_s_use_num++;
                    }
                }
                else if(strcmp(cabinet_info_tab[i].cab_type,"int")==0)
                {
                    if (add_int_to_node(ua_param->ua_server,tmpNodeId1,false, NULL,cabinet_info_tab[i].cab_key,cabinet_info_tab[i].cab_show_name,total_cb_i) == 0)
                    {
                        total_cb_i_use_num++;
                    }
                }
            }
            if (total_cb_s_use_num == 0)
            {
                free(total_cb_s);
            }
            if (total_cb_i_use_num == 0)
            {
                free(total_cb_i);
            }
            UA_NodeId_clear(&tmpNodeId1);
        }

        ua_add_file(ua_param->ua_server, system_info.systemNodeId, &system_info.expertInfo.expertNodeId, "Advance", _("Advanced"));
        {
            addDownloadMethod(ua_param,system_info.expertInfo.expertNodeId);
            addUploadMethod(ua_param,system_info.expertInfo.expertNodeId);

            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 0, NAME_TO_ARRAY2{NULL}, 1, NAME_TO_ARRAY2{"result"}, "FormateExDisk", _("Format extended disk"), formate_exDisk);

            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"url"}, 2, NAME_TO_ARRAY2{"code", "result"}, "upgrade", _("Upgrade"), ua_upgrade);

            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 0, NAME_TO_ARRAY2{NULL}, 1, NAME_TO_ARRAY2{"result"}, "Restart", _("Restart the service"), ua_restart);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 0, NAME_TO_ARRAY2{NULL}, 1, NAME_TO_ARRAY2{"result"}, "Reboot", _("Reboot the device"), ua_resboot);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"name"}, 1, NAME_TO_ARRAY2{"result"}, "ReadCfg", _("Read configuration"), ua_cbget);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"pageId", "pageCount"}, 1, NAME_TO_ARRAY2{"result"}, "getAlarmHistInfo", _("Obtain historical alarm information"), ua_getAlarmHistInfo);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"pageId", "pageCount"}, 1, NAME_TO_ARRAY2{"result"}, "getOptLogInfo", _("Obtain operation information"), ua_getOptLogInfo);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 3, NAME_TO_ARRAY2{"dev_no", "function", "set_value"}, 1, NAME_TO_ARRAY2{"result"}, "ua_set_function", _("Write operation interface"), ua_set_function);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"dev_no", "function"}, 1, NAME_TO_ARRAY2{"result"}, "ua_get_function", _("Read operation interface"), ua_get_function);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"mode"}, 1, NAME_TO_ARRAY2{"result"}, "micro_dev_function", _("get dev_info_all data to json"), micro_dev_function);

            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"name", "content"}, 1, NAME_TO_ARRAY2{"result"}, "WriteCfg", _("Write configuration"), ua_cbset);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"name", "content"}, 1, NAME_TO_ARRAY2{"result"}, "WriteAnyCfg", _("Write general configuration"), ua_cbsetgen);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 0, NAME_TO_ARRAY2{NULL}, 1, NAME_TO_ARRAY2{"result"}, "getAlarmInfo", _("Obtain alarm information"), ua_get_alarm_info);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"pageSize", "pageNum"}, 2, NAME_TO_ARRAY2{"logInfo", "allLogNum"}, "getLogInfo", _("Obtain log information"), ua_get_log);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 0, NAME_TO_ARRAY2{NULL}, 1, NAME_TO_ARRAY2{"result"}, "getNetStatus", _("Get network status"), ua_get_net_status);
            add_time_to_node(ua_param->ua_server, system_info.expertInfo.expertNodeId, false, &system_info.expertInfo.timingNodeId, "Timing", _("Time calibration"));
            // addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,1,NAME_TO_ARRAY2 {"par"},1,NAME_TO_ARRAY2 {"result"},"FactoryDiag","出厂设备诊断",factory_diagnosis);
            // addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,1,NAME_TO_ARRAY2 {"par"},1,NAME_TO_ARRAY2 {"result"},"CrgDisDiag","现场充放电诊断",charge_diagnosis);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"par"}, 1, NAME_TO_ARRAY2{"result"}, "FactoryDiag", _("Factory equipment diagnosis"), factory_diagnosis_lc_ctrl);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"par"}, 1, NAME_TO_ARRAY2{"result"}, "CrgDisDiag", _("On site charge and discharge diagnosis"), charge_diagnosis_lc_ctrl);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"command"}, 1, NAME_TO_ARRAY2{"result"}, "cmd", _("Console commands"), ua_console_cmd);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"name", "value"}, 1, NAME_TO_ARRAY2{"result"}, "forceSetValue", _("Mandatory number setting"), force_set_value);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"name"}, 1, NAME_TO_ARRAY2{"result"}, "cancelForceSetValue", _("Cancel mandatory number setting"), cancel_force_set);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 0, NAME_TO_ARRAY2{NULL}, 1, NAME_TO_ARRAY2{"result"}, "forceSetValueList", _("Mandatory number list setting"), get_force_set_value_list);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"lang"}, 1, NAME_TO_ARRAY2{"result"}, "setSystemLanguage", _("Set system language"), change_sys_language);
            addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 1, NAME_TO_ARRAY2{"par"}, 1, NAME_TO_ARRAY2{"result"}, "ResetRefluxState", _("Reset G100 State"), reset_g100_state);

            if (cabinet_info.ctrl_mode == EMS_MODE_ZC)
            {
                addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"name", "command"}, 1, NAME_TO_ARRAY2{"resutl"}, "lcAgentSet", _("Proxy LC control"), ua_lcAgentSet);
                addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 2, NAME_TO_ARRAY2{"no", "cfgName"}, 1, NAME_TO_ARRAY2{"result"}, "ReadLcCfg", _("Read LC configuration"), ua_read_lc_cfg);
                addMethodToNode(ua_param, system_info.expertInfo.expertNodeId, 3, NAME_TO_ARRAY2{"no", "name", "content"}, 1, NAME_TO_ARRAY2{"result"}, "WriteLcCfg", _("Write LC configuration"), ua_write_lc_cfg);
             }
			 
			addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,1,NAME_TO_ARRAY2 {"protocol"},1,NAME_TO_ARRAY2 {"result"},"CreateNorthcfg",_("Generate north configuration"),ua_create_northcfg);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,2,NAME_TO_ARRAY2 {"index","json"},1,NAME_TO_ARRAY2 {"result"},"WriteMQTTcfg",_("Change the configuration of the north channel"),ua_change_mqttcfg);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,1,NAME_TO_ARRAY2 {"index"},1,NAME_TO_ARRAY2 {"result"},"DeleteMQTTcfg",_("Delete the configuration of the north channel"),ua_delete_mqttcfg);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,1,NAME_TO_ARRAY2 {"index"},1,NAME_TO_ARRAY2 {"result"},"ChangeControl",_("Switching"),ua_change_control);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,0,NAME_TO_ARRAY2 {NULL},1,NAME_TO_ARRAY2 {"result"},"GetNorthcfg",_("Get the configuration of the north channel"),ua_get_northcfg);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,3,NAME_TO_ARRAY2 {"entity","alarmCode", "reasonCode"},1,NAME_TO_ARRAY2 {"result"},"DelAlarm",_("Manually delete alarm information"),recovery_alarm_by_manual);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,2,NAME_TO_ARRAY2 {"dev_no","tag_name"},1,NAME_TO_ARRAY2 {"result"},"DelErrorAlarm",_("Manually delete error alarm tag"),recovery_alarm_by_dev_tag);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,3,NAME_TO_ARRAY2 {"entity","pageSize", "pageNum"},1,NAME_TO_ARRAY2 {"result"},"GetBmsAlarm",_("Obtain Bms alarm information"),get_bms_alarm_info);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,4,NAME_TO_ARRAY2 {"mqttId","functionId", "lang", "dev_no"},1,NAME_TO_ARRAY2 {"result"},"UploadTemplateAlarm",_("Upload template or alarm file"),report_alarm_and_template);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,0,NAME_TO_ARRAY2 {NULL},1,NAME_TO_ARRAY2 {"result"},"SetEmsOperation",_("Set Equipment activation"),set_equipment_activition);
            addMethodToNode(ua_param,system_info.expertInfo.expertNodeId,1,NAME_TO_ARRAY2 {"index"},1,NAME_TO_ARRAY2 {"result"},"GetNorthConnStatus",_("Get the connection status of the north channel"),ua_get_north_conn_status);
        }

        ua_add_file(ua_param->ua_server, system_info.systemNodeId, &system_info.stateInfo.stateNodeId, "Status", _("Status"));
        {
            creat_a_base_double(ua_param, "CPU", _("CPU"), &system_info.stateInfo.CPUNodeId, system_info.stateInfo.stateNodeId, _("Not obtained"));
            creat_a_base_string(ua_param, "Memroy", _("Memory"), &system_info.stateInfo.memNodeId, system_info.stateInfo.stateNodeId, _("Not obtained"));
            creat_a_base_string(ua_param, "Flash", _("Hard disk(used/total MB)"), &system_info.stateInfo.diskNodeId, system_info.stateInfo.stateNodeId, _("Not obtained"));
            creat_a_base_string(ua_param, "ExtendDisk", _("Extended disk(used/total MB)"), &system_info.stateInfo.ExdiskNodeId, system_info.stateInfo.stateNodeId, _("Not obtained"));
            creat_a_base_string(ua_param, "InternetConn", _("Network link"), &system_info.stateInfo.NetStaNodeId, system_info.stateInfo.stateNodeId, _("Not obtained"));
            creat_a_base_double(ua_param, "SignalLevel4G", _("4G signal level"), &system_info.stateInfo.SignalLevel4GId, system_info.stateInfo.stateNodeId, _("Not obtained"));
            if (0 == pthread_create(&get_cycle_info_tid,NULL,get_cycle_info,ua_param))
            {
                pthread_setname_np(get_cycle_info_tid, "get cycle info");
            }
            //
            total_cb_t *totle_cb = calloc(sizeof(total_cb_t), 1);
            totle_cb->onRead = read_ems_connect_cb;
            totle_cb->onWrite = NULL;
            if (0 != add_int_to_node(ua_param->ua_server, system_info.stateInfo.stateNodeId, true, &system_info.stateInfo.EsmConnectNodeId,
                            EMS_CONNECT_STATE, _("EMS connection status"), totle_cb))
            {
                free(totle_cb);
            }

            totle_cb = calloc(sizeof(total_cb_t), 1);
            totle_cb->onRead = read_ems_heartbeat_cb;
            totle_cb->onWrite = write_ems_heartbeat_cb;
            if (0 != add_int_to_node(ua_param->ua_server, system_info.stateInfo.stateNodeId, false, &system_info.stateInfo.EmsHeartbeatNodeId,
                            EMS_HEARTBEAT, _("EMS heartbeat"), totle_cb))
            {
                free(totle_cb);
            }
        }

        ua_add_file(ua_param->ua_server, system_info.systemNodeId, &system_info.debugInfo.debugNodeId, "Debug", _("Debugging"));
        {
            addMethodToNode(ua_param, system_info.debugInfo.debugNodeId, 3, NAME_TO_ARRAY2{_("Device No"), _("Timeout period"), _("HEX string")}, 1, NAME_TO_ARRAY2{"HEX_string"}, "BinDataTransf", _("Test binary message"), ua_dev_message_GFP_T);
            addMethodToNode(ua_param, system_info.debugInfo.debugNodeId, 1, NAME_TO_ARRAY2{_("IP or Domain Name")}, 1, NAME_TO_ARRAY2{"result"}, "Ping", _("Test the network(ping)"), ua_pingnet);
            total_cb_t *total_cb=calloc(sizeof(total_cb_t),1);  
            total_cb->onRead = read_cb;
            total_cb->onWrite = write_cb;
            int total_cb_use_num = 0;
            if (add_int_to_node(ua_param->ua_server,system_info.debugInfo.debugNodeId,false,&system_info.debugInfo.emsLogLevelNodeId,
                            EMS_LOG_LEVEL  ,_("EMS log level") ,total_cb) == 0)
            {
                total_cb_use_num++;
            }
            if (add_int_to_node(ua_param->ua_server,system_info.debugInfo.debugNodeId,false,&system_info.debugInfo.protoLogLevelNodeId,
                            PRO_LOG_LEVEL,_("Data acquisition log level"),total_cb) == 0)
            {
                total_cb_use_num++;
            }
            if (add_int_to_node(ua_param->ua_server, system_info.debugInfo.debugNodeId, false, &UD_LOG_UA_NODE,
                            UD_LOG_LEVEL, _("Upper data log level"), total_cb) == 0)
            {
                total_cb_use_num++;
            }

            if (total_cb_use_num == 0)
            {
                free(total_cb);
            }
        }

    }
}
