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

#include "supec5100.h"

#define SUPEC5100_APP_KEY "PqPDtu78j2dGyq3u"

supec5100_var_t gvar = {0};

gw_port_e ports[] = {VINTF_TCP};
static int get_rt_data_from_json_str(pp_regulate_signal_t *regulate_data, char *json_str)
{
    int ret = 0;

    cJSON *root = cJSON_Parse(json_str);
    if (root)
    {
        char *payload = NULL;
        char *buf = NULL;
        int len;
        char *tmp;

        buf = (char *)malloc(MAXBUF);
        if (buf == NULL)
        {
            dy_syslog(LOG_ERR, "malloc failed");
            ret = -1;
            goto out;
        }

        GET_JSON_VALUE_STRING(root, "port", buf);
        regulate_data->port = port_char2enum(buf);
        GET_JSON_VALUE_INT(root, "mi", regulate_data->mi);
        GET_JSON_VALUE_INT(root, "len", regulate_data->len);
        GET_JSON_VALUE_STRING(root, "src_identifier", regulate_data->src_identifier);
        GET_JSON_VALUE_STRING(root, "sn", regulate_data->sn);
        GET_JSON_VALUE_STRING(root, "dtu_sn", regulate_data->dtu_sn);

        GET_JSON_VALUE_STRING(root, "data_b64", buf);
        //len = b64_decode(tmp, buf, MAXBUF);
        //free(tmp);
        //dy_syslog(LOG_DEBUG, "len:%d, regulate_data->len:%d", len, regulate_data->len);
        //ASSERT(len == regulate_data->len);
        len = strlen(buf);
        regulate_data->data = malloc(len);
        if (regulate_data->data == NULL)
        {
            dy_syslog(LOG_ERR, "malloc fail len:%d", len);
            free(buf);
            goto out;
        }
        memcpy(regulate_data->data, buf, len);
        free(buf);
    }
    else
    {
        dy_syslog(LOG_ERR, "json parse error");
        ret = -1;
    }

out:
    cJSON_Delete(root);

    return ret;
}

static void data_report(supec5100_var_t *var, pp_real_time_data_t *real_data, char *result_data, int len)
{
	tag_table_t ptag = {0};
	tag_table_t ptag_post = {0};
					
	strcpy(ptag.sn, real_data->sn);
	ptag.mi = real_data->mi;		
	strncpy(ptag.identifier, real_data->src_identifier, strlen(real_data->src_identifier));
	ptag.report_period = 0;
	ptag.data_type = DATA_TYPE_SERVICE;
	ptag.tag_node = calloc((len)+1, 1);
	memcpy(ptag.tag_node, result_data, len);
	ptag.time = time(NULL);

	memcpy(&ptag_post, &ptag, sizeof(tag_table_t));
	strcpy(ptag_post.identifier, "post");
	ptag_post.data_type = DATA_TYPE_PROPERTY;
	ptag_post.tag_node = calloc((len)+1, 1);
	memcpy(ptag_post.tag_node, result_data, len);

	dy_syslog(LOG_DEBUG, "parse result_data:%s post:%s", ptag.tag_node, ptag_post.tag_node);
    if (ptag.tag_node != NULL)
    {
		ptag.port = real_data->port;
        pp_send_tag_data(var->session, &ptag);
        free(ptag.tag_node);
    }
    if (ptag_post.tag_node != NULL)
    {
		ptag_post.port = real_data->port;
        pp_send_tag_data(var->session, &ptag_post);
        free(ptag_post.tag_node);
    }
}

int supec5100_cmd_reply(supec5100_var_t *var, pp_regulate_signal_t *regulate_data, int status)
{
    pp_real_time_data_t real_data = {0};

	cJSON *node = cJSON_CreateObject();
    cJSON_AddNumberToObject(node, "status", status);
    char *data = cJSON_Print(node);
    cJSON_Delete(node);
	
    real_data.port = TCP_CLIENT;
    real_data.len = strlen(data);
    real_data.mi = regulate_data->mi;
    strcpy(real_data.sn, regulate_data->sn);
    strncpy(real_data.src_identifier, regulate_data->src_identifier, sizeof(real_data.src_identifier));
	data_report(var, &real_data, data, real_data.len);

    return 0;
}

int supec5100_send_msg(supec5100_var_t *var, connect_config_t *connect_cfg, char *buf, int len, char *identfier)
{
	int ret = 0;
	
	dy_syslog_hex(LOG_DEBUG, buf, len, "identfier %d len %d			网关->[%s]		", identfier,len,connect_cfg->addr);
	ret = dy_socket_session_snd(connect_cfg->socket_client, buf, len);

	//store the identifier
    {
        char key_str[64] = {0};
        regulate_cmd_backup_t fields;

        strcpy(fields.src_identifier, identfier);
        strcpy(fields.sn, connect_cfg->sn);
        fields.mi = 0;

		sprintf(key_str, "%s", connect_cfg->sn);
        var->identifier_backup.insert(&var->identifier_backup, key_str, &fields, sizeof(fields));
    }
    flush_device_status_by_sn(var->ds, ACTION_SND, connect_cfg->sn);

	return ret;
}

static int supec5100_start_collecting(supec5100_var_t *var, connect_config_t *connect_cfg, supec5100_node_config_t *node, pp_regulate_signal_t *regulate_data)
{
	int ret = 0;
	int j,k;
	
	for(j=0; j<node->start_collecting->cmd_cnt; j++)
	{
		ret += supec5100_send_msg(var, connect_cfg, node->start_collecting->cmd[j].cmd, node->start_collecting->cmd[j].cmd_len, node->start_collecting->cmd[j].name);
		usleep(40000);
	}
	supec5100_cmd_reply(var, regulate_data, ret);
	if(ret)
	{
		dy_syslog(LOG_DEBUG, "start_collecting ret %d fail", ret);
		goto _out;
	}
	
	dy_syslog(LOG_DEBUG, "start_collecting cmd_cnt %d DetectionTimes %d...", node->start_collecting->cmd_cnt,node->DetectionTimes);
	connect_cfg->opt_step = 1;			
	for(k=0; k<node->DetectionTimes; k++)
	{
		for(j=0; j<node->test_step->cmd_cnt; j++)
		{
			if(connect_cfg->end_collecting)
			{
				dy_syslog(LOG_DEBUG, "====end_collecting...===");
				goto _out;
			}
			supec5100_send_msg(var, connect_cfg, node->test_step->cmd[j].cmd, node->test_step->cmd[j].cmd_len, node->test_step->cmd[j].name);
			usleep(node->test_step->cmd[j].Time*1000000);
		}
		dy_syslog(LOG_DEBUG, "====k %d test_step cmd_cnt %d...", k,node->test_step->cmd_cnt);
	}
_out:
	connect_cfg->opt_step = 0;
	supec5100_send_msg(var, connect_cfg, node->EndCollecting, strlen(node->EndCollecting), "EndCollecting");
	if(!connect_cfg->end_collecting)
	{
		supec5100_send_msg(var, connect_cfg, node->EndCollecting, strlen(node->EndCollecting), "EndCollecting");
	}
	supec5100_cmd_reply(var, regulate_data, 2);
}

static int supec5100_start_cleaning(supec5100_var_t *var, connect_config_t *connect_cfg, supec5100_node_config_t *node, pp_regulate_signal_t *regulate_data)
{
	int ret = 0;
	
	cJSON *root = cJSON_Parse(regulate_data->data);
    if (root)
    {
    	int j;
        char parameter[64] = {0};

        GET_JSON_VALUE_STRING(root, "parameter", parameter);
		if(strcmp(parameter, "A") == 0)
		{
			for(j=0; j<node->device_cleaning.start_cleaning_A->cmd_cnt; j++)
			{
				ret += supec5100_send_msg(var, connect_cfg, node->device_cleaning.start_cleaning_A->cmd[j].cmd, node->device_cleaning.start_cleaning_A->cmd[j].cmd_len, "cmd");
				usleep(50000);
			}
		}
		else if(strcmp(parameter, "B") == 0)
		{
			for(j=0; j<node->device_cleaning.start_cleaning_B->cmd_cnt; j++)
			{
				ret += supec5100_send_msg(var, connect_cfg, node->device_cleaning.start_cleaning_B->cmd[j].cmd, node->device_cleaning.start_cleaning_B->cmd[j].cmd_len, "cmd");
				usleep(50000);
			}
		}
		else
			ret = -1;
    }
	
	cJSON_Delete(root);
	return ret;

}

static int supec5100_start_checking(supec5100_var_t *var, connect_config_t *connect_cfg, supec5100_node_config_t *node, pp_regulate_signal_t *regulate_data)
{
	int ret = 0;
	
	cJSON *root = cJSON_Parse(regulate_data->data);
    if (root)
    {
    	int j;
        char parameter[64] = {0};

        GET_JSON_VALUE_STRING(root, "parameter", parameter);
		if(strcmp(parameter, "PumpStart") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.PumpStart.cmd, node->self_checking.PumpStart.cmd_len, "PumpStart");
		}
		else if(strcmp(parameter, "PumpStop") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.PumpStop.cmd, node->self_checking.PumpStop.cmd_len, "PumpStop");
		}
		else if(strcmp(parameter, "InjectionValve1A") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.InjectionValve1A.cmd, node->self_checking.InjectionValve1A.cmd_len, "InjectionValve1A");
		}
		else if(strcmp(parameter, "InjectionValve1B") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.InjectionValve1B.cmd, node->self_checking.InjectionValve1B.cmd_len, "InjectionValve1B");
		}
		else if(strcmp(parameter, "InjectionValve2A") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.InjectionValve2A.cmd, node->self_checking.InjectionValve2A.cmd_len, "InjectionValve2A");
		}
		else if(strcmp(parameter, "InjectionValve2B") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.InjectionValve2B.cmd, node->self_checking.InjectionValve2B.cmd_len, "InjectionValve2B");
		}
		else if(strcmp(parameter, "TemperatureControl1") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.TemperatureControl1.cmd, node->self_checking.TemperatureControl1.cmd_len, "TemperatureControl1");
		}
		else if(strcmp(parameter, "TemperatureControl2") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.TemperatureControl2.cmd, node->self_checking.TemperatureControl2.cmd_len, "TemperatureControl2");
		}
		else if(strcmp(parameter, "LightDetectorOpen") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.LightDetectorOpen.cmd, node->self_checking.LightDetectorOpen.cmd_len, "LightDetectorOpen");
		}
		else if(strcmp(parameter, "LightDetectorClose") == 0)
		{
			ret = supec5100_send_msg(var, connect_cfg, node->self_checking.LightDetectorClose.cmd, node->self_checking.LightDetectorClose.cmd_len, "LightDetectorClose");
		}
		else
			ret = -1;
    }
	
	cJSON_Delete(root);

	return ret;
}

static int supec5100_mqtt_handle_recv_msg(void *obj, ipc_msg_t *mqtt_msg)
{
    supec5100_var_t *var = (supec5100_var_t *)obj;

    dy_syslog(LOG_DEBUG, " MQTT client: received MQTT topic:%s payload length:%d payload:%s",
              mqtt_msg->topic, mqtt_msg->payloadLen, mqtt_msg->payload);
    if (strstr(mqtt_msg->topic, TOPIC_SEND_RGLT_SIGNAL_RAW_DATA))
    {
    	int ret = 0;
		pp_regulate_signal_t regulate_data = {0};

	    ret = get_rt_data_from_json_str(&regulate_data, mqtt_msg->payload);
	    if (ret < 0)
	    {
	        dy_syslog(LOG_ERR, "parse real data structure failed");
	    }

		supec5100_data_list_t *supec5100_data = calloc(sizeof(supec5100_data_list_t), 1);
		if(supec5100_data)
		{
			memcpy(&supec5100_data->regulate_data, &regulate_data, sizeof(regulate_data));
			list_add_tail(&supec5100_data->list, &var->data_list);
		}

		connect_config_t *connect_cfg = NULL;	
		list_for_each_entry(connect_cfg, &var->connect_list, list)
		{
			dy_syslog(LOG_DEBUG, "sn(%d %d) src_identifier:%s", connect_cfg->sn, regulate_data.sn, regulate_data.src_identifier);
			if(strcmp(connect_cfg->sn, regulate_data.sn) == 0)
			{
				if(!strlen(connect_cfg->TestMethod))
				{
					cJSON *root = cJSON_Parse(regulate_data.data);
				    if (root)
				    {
				        GET_JSON_VALUE_STRING(root, "TestMethod", connect_cfg->TestMethod);
						cJSON_Delete(root);
				    }
				}
				dy_syslog(LOG_DEBUG, "sn(%d %d) src_identifier:%s TestMethod:%s", connect_cfg->sn, regulate_data.sn, regulate_data.src_identifier,connect_cfg->TestMethod);
				if(strcmp(regulate_data.src_identifier, "EndCollecting") == 0)
				{
					connect_cfg->end_collecting = 1;
				}
			}
		}
    }
}

static int supec5100_mqtt_msg_timer(supec5100_var_t *var)
{
	TIMER_CONFIRM(var->mqtt_msg_timer);
    supec5100_data_list_t *send_data = NULL;
	socket_state_e state;
    list_for_each_entry(send_data, &var->data_list, list)
    {
        connect_config_t *connect_cfg = NULL;	
		list_for_each_entry(connect_cfg, &var->connect_list, list)
		{
			dy_syslog(LOG_DEBUG, "sn(%d %d) src_identifier:%s", connect_cfg->sn, send_data->regulate_data.sn, send_data->regulate_data.src_identifier);
			if(strcmp(connect_cfg->sn, send_data->regulate_data.sn) == 0)
			{
				dy_syslog(LOG_DEBUG, "sn(%d %d) src_identifier:%s", connect_cfg->sn, send_data->regulate_data.sn, send_data->regulate_data.src_identifier);
								
				int i;
				int ret = 0;
				supec5100_node_config_t *node = NULL;
				for(i=0; i<var->supec5100_config->node_cnt; i++)
				{
					if(strcmp(var->supec5100_config->node[i].TestMethod, connect_cfg->TestMethod) == 0)
					{
						node = &var->supec5100_config->node[i];
						break;
					}
				}

				state = dy_socket_session_get_state(connect_cfg->socket_client);
				if (state != SOCKET_CONNECTED || node == NULL)
					break;

				if(strcmp(send_data->regulate_data.src_identifier, "StartCollecting") == 0)
				{
					supec5100_start_collecting(var, connect_cfg, node, &send_data->regulate_data);
				}
				else if(strcmp(send_data->regulate_data.src_identifier, "EndCollecting") == 0)
				{
					connect_cfg->end_collecting = 0;
					ret = supec5100_send_msg(var, connect_cfg, node->EndCollecting, strlen(node->EndCollecting), "EndCollecting");
					supec5100_cmd_reply(var, &send_data->regulate_data, ret);
				}
				else if(strcmp(send_data->regulate_data.src_identifier, "StartCleaning") == 0)
				{
					ret = supec5100_start_cleaning(var, connect_cfg, node, &send_data->regulate_data);
					supec5100_cmd_reply(var, &send_data->regulate_data, ret);	
				}
				else if(strcmp(send_data->regulate_data.src_identifier, "EndCleaning") == 0)
				{
					ret = supec5100_send_msg(var, connect_cfg, node->EndCleaning, strlen(node->EndCleaning), "EndCleaning");
					supec5100_cmd_reply(var, &send_data->regulate_data, ret);
				}
				else if(strcmp(send_data->regulate_data.src_identifier, "SelfChecking") == 0)
				{
					ret = supec5100_start_checking(var, connect_cfg, node, &send_data->regulate_data);
					supec5100_cmd_reply(var, &send_data->regulate_data, ret);
				}
				#if 0
				dy_syslog_hex(LOG_DEBUG, regulate_data.data, regulate_data.len, "len %d			网关->[%s]		", regulate_data.len,connect_cfg->socket_client.socket_server_addr);
				dy_socket_session_snd(&connect_cfg->socket_client, regulate_data.data, regulate_data.len);

				//store the identifier
			    {
			        char key_str[64] = {0};
			        regulate_cmd_backup_t fields;

			        strcpy(fields.src_identifier, regulate_data.src_identifier);
			        strcpy(fields.sn, regulate_data.sn);
			        fields.mi = regulate_data.mi;

					sprintf(key_str, "%s", regulate_data.sn);
			        var->identifier_backup.insert(&var->identifier_backup, key_str, &fields, sizeof(fields));
			    }
			    flush_device_status_by_sn(var->ds, ACTION_SND, regulate_data.sn);
				#endif
			}
		}

		list_del(&send_data->list);
		if (send_data->regulate_data.data)
	    	free(send_data->regulate_data.data);
		free(send_data);		
		break;
    }

	return 0;
}


static void supec5100_loop(supec5100_var_t *var)
{
    int ret = -1, maxfd;
    fd_set  rset;
    struct timeval timeout;

    while (1)
    {
        SELECT_INIT();
        SELECT_ADD_FD(var->mqtt_msg_timer);
        timeout.tv_usec = 0;
        timeout.tv_sec = 10;
        ret = select(maxfd + 1, &rset, 0, 0, &timeout);
        if (ret < 0)
        {
            printf("errno %d\n", errno);
            if (errno == EINTR)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else if (ret == 0)
        {
        }
        else
        {
            if (var->mqtt_msg_timer > 0 && FD_ISSET(var->mqtt_msg_timer, &rset))
            {
                FD_CLR(var->mqtt_msg_timer, &rset);
				//supec5100_heartbeat_timer(var);
				supec5100_mqtt_msg_timer(var);
            }
        }
    }
}

static void supec5100_subscribe_all(supec5100_var_t *var)
{
    ipc_session_t *ipc_session = var->session;
    char topic[TOPIC_MAX_LEN] = {0};
    int i = 0;

	snprintf(topic, TOPIC_MAX_LEN, "ipc/+/%s/device/+/data/%s", SUPEC5100_APP_KEY, TOPIC_SEND_RGLT_SIGNAL_RAW_DATA);
    ipc_session_subscribe(ipc_session, topic);
}

// 建立与内部broker之间的MQTT连接
static int supec5100_mqtt_client_init(supec5100_var_t *var)
{
    char clientId[MAX_CLIENT_ID_LEN] = {0};

    snprintf(clientId, MAX_CLIENT_ID_LEN, "%s", var->proc_name);
    var->session = ipc_session_new(clientId, (void*)var, IPC_DEFAULT);
    if (var->session == NULL) return -1;

    ipc_session_set_callbacks(var->session, supec5100_mqtt_handle_recv_msg, NULL);
    supec5100_subscribe_all(var);
    ipc_session_start(var->session);
}

int supec5100_data_report(supec5100_var_t *var, char *sn, double light)
{
    pp_real_time_data_t real_data = {0};

	cJSON *node = cJSON_CreateObject();
    cJSON_AddNumberToObject(node, "light_intensity", light);
    char *data = cJSON_Print(node);
    cJSON_Delete(node);
	
    real_data.port = TCP_CLIENT;
    real_data.len = strlen(data);
    real_data.mi = 0;
    strcpy(real_data.sn, sn);
    strncpy(real_data.src_identifier, "RealtimeData", sizeof(real_data.src_identifier));
	data_report(var, &real_data, data, real_data.len);
	
    flush_device_status_by_sn(var->ds, ACTION_RCV, real_data.sn);

    return 0;
}

static int socket_handle_rcv_msg(void *obj, char *buf, int len)
{
	char topic[TOPIC_MAX_LEN] = {0};
	connect_config_t *connect_cfg = (connect_config_t *)obj;
    supec5100_var_t *var = connect_cfg->var;
    int mi = time(NULL);

    dy_syslog_hex(LOG_DEBUG, buf, len, "len %d			网关<-[%s]		", len, connect_cfg->addr);
	if(connect_cfg->opt_step == 1 && strstr(buf, "#RLI,"))
	{
		char *light_str = buf;
		light_str = strtok(buf, ",");
		while(light_str != NULL)
		{
			dy_syslog(LOG_DEBUG, "light_str:%s", light_str);
			if(!strstr(light_str, "#RLI"))
			{
				double light;
				sscanf(light_str, "%lf", &light);
				dy_syslog(LOG_DEBUG, "light_str:%s light:%f", light_str,light);
				supec5100_data_report(var, connect_cfg->sn, light);
				break;
			}
			light_str = strtok(NULL, ",");
		}
	}

	flush_device_status_by_sn(var->ds, ACTION_SND, connect_cfg->sn);
	return 0;
}

static int connect_state_change(void *obj, socket_state_e state)
{
    connect_config_t *connect_cfg = (connect_config_t *)obj;
    supec5100_var_t *var = connect_cfg->var;

	dy_syslog(LOG_DEBUG, "connect_state_change state %d", state);
	if(state == SOCKET_DISCONNECTED)
		connect_cfg->last_send = 0;
	
	return 0;
}

int del_space(char *src)
{
	char *pTmp = src;
	unsigned int iSpace = 0;
	
	while (*src != '\0')
	{
		if (*src != ' ')
		{
			*pTmp++ = *src;
		}
		else
		{
			iSpace++;
		}
		
		src++;
	}
	
	*pTmp = '\0';
	return iSpace;
}

int del_colon(char *src)
{
	char *pTmp = src;
	unsigned int iSpace = 0;
	
	while (*src != '\0')
	{
		if (*src != ':')
		{
			*pTmp++ = *src;
		}
		else
		{
			iSpace++;
		}
		
		src++;
	}
	
	*pTmp = '\0';
	return iSpace;
}


int supec5100_load_tcp_nodes(supec5100_var_t *var)
{
    int k;

    //建立TCP连接
    for (k = 0; k < var->nodes_cfg_table->node_cnt; k++)
    {
    	dy_syslog(LOG_DEBUG, "sn:%s app_key:%s", var->nodes_cfg_table->node[k].sn,var->nodes_cfg_table->node[k].app_key);
    	if(strcmp(var->nodes_cfg_table->node[k].app_key, SUPEC5100_APP_KEY) == 0)
		{
			connect_config_t *connect_cfg = calloc(1, sizeof(connect_config_t));
			connect_cfg->type == SOCKET_TCP;
			connect_cfg->addr = strdup(var->nodes_cfg_table->node[k].tcp_ip_addr);
			connect_cfg->port = var->nodes_cfg_table->node[k].tcp_port;
			strcpy(connect_cfg->sn, var->nodes_cfg_table->node[k].sn);

			cJSON *node = cJSON_Parse(var->nodes_cfg_table->node[k].ext_data);
		    if (node)
		    {
		    	GET_JSON_VALUE_STRING(node, "TestMethod", connect_cfg->TestMethod);
				cJSON_Delete(node);
		    }
			
			dy_syslog(LOG_INFO,"==sn:%s socket_addr:%s port:%d TestMethod:%s==",connect_cfg->sn,connect_cfg->addr,
				connect_cfg->port,connect_cfg->TestMethod);
			list_add_tail(&connect_cfg->list, &var->connect_list);
		}
    }
}

static void config_get_cmd(cJSON *node, char *item_name, general_cmd_t *cmd)
{
	char buff[200];
	
	GET_JSON_VALUE_STRING(node, item_name, buff);
    del_colon(buff);
	cmd->cmd_len = strlen(buff)/2;
	cmd->cmd = calloc(1, cmd->cmd_len);
	str2hex(cmd->cmd, buff, cmd->cmd_len);
	dy_syslog_hex(LOG_DEBUG, cmd->cmd, cmd->cmd_len, "item_name:%s cmd_len:%d", item_name, cmd->cmd_len);
}

static int supec5100_load_conf(supec5100_var_t *var, char *cfg_file)
{
    char *data = NULL;
    cJSON *root = NULL;
    cJSON *nodes = NULL;
    cJSON *node  = NULL;
    //nodes_cfg_table_t *nodes_cfg = NULL;
    int node_cnt = 0;
    int i = 0, ret = 0, m;
    char buff[200];
    int addr[8];
    int size = 0;

	dy_syslog(LOG_DEBUG, "supec5100_load_conf");

    data = read_file_data(cfg_file);
    if (data == NULL)
    {
        dy_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        ret = -1;
        goto out;
    }

    root = cJSON_Parse(data);
    if (!root)
    {
        dy_syslog(LOG_ERR, "parse cfg file %s error", cfg_file);
        ret = -1;
        goto out;
    }
    nodes = cJSON_GetObjectItem(root, "supec5100_node_cfg");
    if (!nodes)
    {
        dy_syslog(LOG_ERR, "get supec5100_node_cfg failed");
        ret = -1;
        goto out;
    }

    node_cnt = cJSON_GetArraySize(nodes);
    size = sizeof(supec5100_config_t) + node_cnt * sizeof(supec5100_node_config_t);
	var->supec5100_config = calloc(1, size);
    if (var->supec5100_config == NULL)
    {
        dy_syslog(LOG_ERR, "malloc failed, node_cnt:%d size:%d", node_cnt, size);
        ret = -1;
        goto out;
    }

    for (i = 0; i < node_cnt ; i++)
    {
        node = cJSON_GetArrayItem(nodes, i);
        if (node)
        {
            GET_JSON_VALUE_STRING(node, "TestMethod", var->supec5100_config->node[i].TestMethod);
			GET_JSON_VALUE_INT(node, "DetectionTimes", var->supec5100_config->node[i].DetectionTimes);
            GET_JSON_VALUE_STRING(node, "T2", buff);
			sscanf(buff, "%d", &var->supec5100_config->node[i].T2);
            GET_JSON_VALUE_STRING(node, "PeekStartTime", buff);
			sscanf(buff, "%d", &var->supec5100_config->node[i].PeekStartTime);
            GET_JSON_VALUE_STRING(node, "T1", buff);
			sscanf(buff, "%d", &var->supec5100_config->node[i].T1);
            GET_JSON_VALUE_STRING(node, "FitData", var->supec5100_config->node[i].FitData);
            GET_JSON_VALUE_STRING(node, "AutoRevise", buff);
			sscanf(buff, "%d", &var->supec5100_config->node[i].AutoRevise);
            GET_JSON_VALUE_STRING(node, "PeekValley", buff);
			sscanf(buff, "%d", &var->supec5100_config->node[i].PeekValley);
            GET_JSON_VALUE_STRING(node, "IntegralTime", buff);
			sscanf(buff, "%d", &var->supec5100_config->node[i].IntegralTime);
			GET_JSON_VALUE_STRING(node, "PeekIntervarTime", buff);
			sscanf(buff, "%d", &var->supec5100_config->node[i].PeekIntervarTime);
			
			GET_JSON_VALUE_STRING(node, "EndCleaning", buff);
			del_colon(buff);			
			str2hex(var->supec5100_config->node[i].EndCleaning, buff, strlen(buff)/2);
			dy_syslog_hex(LOG_DEBUG, var->supec5100_config->node[i].EndCleaning, strlen(buff)/2,
						"EndCleaning cmd_len:%d", strlen(buff)/2);

			GET_JSON_VALUE_STRING(node, "EndCollecting", buff);
			del_colon(buff);			
			str2hex(var->supec5100_config->node[i].EndCollecting, buff, strlen(buff)/2);
			dy_syslog_hex(LOG_DEBUG, var->supec5100_config->node[i].EndCollecting, strlen(buff)/2,
						"EndCollecting cmd_len:%d", strlen(buff)/2);
					
            cJSON *StartCleaning = cJSON_GetObjectItem(node, "StartCleaning");		
            if (StartCleaning && cJSON_GetArraySize(StartCleaning))
            {
            	cJSON *A = cJSON_GetObjectItem(StartCleaning, "A");	

				var->supec5100_config->node[i].device_cleaning.start_cleaning_A = calloc(1, sizeof(start_cleaning_t) + cJSON_GetArraySize(A) * sizeof(general_cmd_t));
				var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd_cnt = cJSON_GetArraySize(A);
                
				for (m = 0; m < var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd_cnt; m++)
                {
                    cJSON *param = cJSON_GetArrayItem(A, m);
                    if (param)
                    {
                        GET_JSON_VALUE_STRING(param, "cmd", buff);
                        del_colon(buff);
						
						var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd_len = strlen(buff)/2;
						var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd = calloc(1, var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd_len);
						str2hex(var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd, buff, var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd_len);
						dy_syslog_hex(LOG_DEBUG, var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd, var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd_len,
									"start_cleaning_A cmd_len:%d", var->supec5100_config->node[i].device_cleaning.start_cleaning_A->cmd[m].cmd_len);
                    }
                }

				cJSON *B = cJSON_GetObjectItem(StartCleaning, "B");	

				var->supec5100_config->node[i].device_cleaning.start_cleaning_B = calloc(1, sizeof(start_cleaning_t) + cJSON_GetArraySize(B) * sizeof(general_cmd_t));
				var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd_cnt = cJSON_GetArraySize(B);
                
				for (m = 0; m < var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd_cnt; m++)
                {
                    cJSON *param = cJSON_GetArrayItem(B, m);
                    if (param)
                    {
                        GET_JSON_VALUE_STRING(param, "cmd", buff);
                        del_colon(buff);
						
						var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd_len = strlen(buff)/2;
						var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd = calloc(1, var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd_len);
						str2hex(var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd, buff, var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd_len);
						dy_syslog_hex(LOG_DEBUG, var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd, var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd_len,
									"start_cleaning_B cmd_len:%d", var->supec5100_config->node[i].device_cleaning.start_cleaning_B->cmd[m].cmd_len);
                    }
                }
            }

			cJSON *SelfChecking = cJSON_GetObjectItem(node, "SelfChecking");			
            if (SelfChecking && cJSON_GetArraySize(SelfChecking))
            {
            	config_get_cmd(SelfChecking, "PumpStart", &var->supec5100_config->node[i].self_checking.PumpStart);
				config_get_cmd(SelfChecking, "PumpStop", &var->supec5100_config->node[i].self_checking.PumpStop);
				config_get_cmd(SelfChecking, "InjectionValve1A", &var->supec5100_config->node[i].self_checking.InjectionValve1A);
				config_get_cmd(SelfChecking, "InjectionValve1B", &var->supec5100_config->node[i].self_checking.InjectionValve1B);
				config_get_cmd(SelfChecking, "InjectionValve2A", &var->supec5100_config->node[i].self_checking.InjectionValve2A);
				config_get_cmd(SelfChecking, "InjectionValve2B", &var->supec5100_config->node[i].self_checking.InjectionValve2B);
				config_get_cmd(SelfChecking, "TemperatureControl1", &var->supec5100_config->node[i].self_checking.TemperatureControl1);
				config_get_cmd(SelfChecking, "TemperatureControl2", &var->supec5100_config->node[i].self_checking.TemperatureControl2);
				config_get_cmd(SelfChecking, "LightDetectorOpen", &var->supec5100_config->node[i].self_checking.LightDetectorOpen);
				config_get_cmd(SelfChecking, "LightDetectorClose", &var->supec5100_config->node[i].self_checking.LightDetectorClose);
            }

            cJSON *params = cJSON_GetObjectItem(node, "StartCollecting");
            if (params)
            {
                var->supec5100_config->node[i].start_collecting = calloc(1, sizeof(start_collecting_t) + cJSON_GetArraySize(params) * sizeof(general_cmd_t));
				var->supec5100_config->node[i].start_collecting->cmd_cnt = cJSON_GetArraySize(params);
                
				for (m = 0; m < var->supec5100_config->node[i].start_collecting->cmd_cnt; m++)
                {
                    cJSON *param = cJSON_GetArrayItem(params, m);
                    if (param)
                    {
                        GET_JSON_VALUE_STRING(param, "cmd", buff);
                        del_colon(buff);
						var->supec5100_config->node[i].start_collecting->cmd[m].cmd_len = strlen(buff)/2;
						var->supec5100_config->node[i].start_collecting->cmd[m].cmd = calloc(1, var->supec5100_config->node[i].start_collecting->cmd[m].cmd_len);
						str2hex(var->supec5100_config->node[i].start_collecting->cmd[m].cmd, buff, var->supec5100_config->node[i].start_collecting->cmd[m].cmd_len);
						dy_syslog_hex(LOG_DEBUG, var->supec5100_config->node[i].start_collecting->cmd[m].cmd, var->supec5100_config->node[i].start_collecting->cmd[m].cmd_len,
									"StartCollecting cmd_len:%d", var->supec5100_config->node[i].start_collecting->cmd[m].cmd_len);
                    }
                }
            }

			cJSON *Step = cJSON_GetObjectItem(node, "Step");
            if (Step)
            {
                var->supec5100_config->node[i].test_step = calloc(1, sizeof(test_step_t) + cJSON_GetArraySize(Step) * sizeof(general_cmd_t));
				var->supec5100_config->node[i].test_step->cmd_cnt = cJSON_GetArraySize(Step);
                
				for (m = 0; m < var->supec5100_config->node[i].test_step->cmd_cnt; m++)
                {
                    cJSON *param = cJSON_GetArrayItem(Step, m);
                    if (param)
                    {
                    	GET_JSON_VALUE_STRING(param, "Time", buff);
						sscanf(buff, "%d", &var->supec5100_config->node[i].test_step->cmd[m].Time);
						
                        GET_JSON_VALUE_STRING(param, "cmd", buff);
                        del_colon(buff);						
						var->supec5100_config->node[i].test_step->cmd[m].cmd_len = strlen(buff)/2;
						var->supec5100_config->node[i].test_step->cmd[m].cmd = calloc(1, var->supec5100_config->node[i].test_step->cmd[m].cmd_len);
						str2hex(var->supec5100_config->node[i].test_step->cmd[m].cmd, buff, var->supec5100_config->node[i].test_step->cmd[m].cmd_len);
						dy_syslog_hex(LOG_DEBUG, var->supec5100_config->node[i].start_collecting->cmd[m].cmd, var->supec5100_config->node[i].start_collecting->cmd[m].cmd_len,
									"Step %d Time %d cmd_len:%d", m,var->supec5100_config->node[i].test_step->cmd[m].Time,var->supec5100_config->node[i].start_collecting->cmd[m].cmd_len);
                    }
                }
            }
        }
    }

    var->supec5100_config->node_cnt = node_cnt;

out:
    cJSON_Delete(root);
    if (data != NULL)
    {
        free(data);
    }
    if (var->supec5100_config == NULL)
    {
        //分配node cnt等于0的node_cfg出来
        var->supec5100_config = calloc(1, sizeof(supec5100_config_t));
        var->supec5100_config->node_cnt = 0;
    }

    return ret;
}

static int supec5100_init(supec5100_var_t *var)
{
	
	INIT_LIST_HEAD(&var->connect_list);
	INIT_LIST_HEAD(&var->data_list);
	
    get_board_sn(var->sn_str);
    get_process_name(var->proc_name);

    if (load_nodes_cfg(&var->nodes_cfg_table, NODES_CFG_PATH) == -1)
    {
        dy_syslog(LOG_ERR, "load nodes cfg fail");
    }
	if (load_templates_cfg(&var->template_table, TEMPLATES_CFG_PATH) == -1)
    {
        dy_syslog(LOG_ERR, "load template cfg fail");
    }

	if (access(SUPEC5100_CFG, F_OK) != -1)
    {
        supec5100_load_conf(var, SUPEC5100_CFG);
    }
	dy_syslog(LOG_DEBUG, "node_cnt:%d", var->supec5100_config->node_cnt);
	dev_status_init(&var->ds, var->nodes_cfg_table, var->template_table, ports, ARRAY_SIZE(ports));
    node_sta_recovery(var->ds, TCP_CLIENT_NODE_STATUS_BAK_FILE);

    kv_array_init(&var->identifier_backup, 32);

    supec5100_mqtt_client_init(var);	
    supec5100_load_tcp_nodes(var);

	connect_config_t *connect_cfg = NULL;	
	list_for_each_entry(connect_cfg, &var->connect_list, list)
	{
		var->node_cnt++;
		connect_cfg->socket_client = dy_socket_session_init(connect_cfg->type, connect_cfg->addr,
                                                                connect_cfg->port,
                                                                socket_handle_rcv_msg,
                                                                connect_state_change,
                                                                (void *)connect_cfg);
	}

    var->mqtt_msg_timer = my_timer_create();
    if (var->mqtt_msg_timer > 0)
    {
    	if(var->node_cnt)
			my_timer_set(var->mqtt_msg_timer, 3, 300);
		else
        	my_timer_set(var->mqtt_msg_timer, 3, 100000);
    }

    dy_syslog(LOG_INFO, "init done, board SN:%s", var->sn_str);

    return 0;
}

int main(int argc, char *argv[])
{
    supec5100_var_t *var = &gvar;

    memset(var, 0, sizeof(supec5100_var_t));

    supec5100_init(var);
    supec5100_loop(var);

    return 0;
}
