
#include "string.h"
#include <stdlib.h>
#include <stdio.h>   
#include "gateway_message.h"


GATEWAY_PARAMS gateway_config_params = {0};

GATEWAY_PARAMS *get_gateway_config_params()
{
    return &gateway_config_params;
}

void parseStringField(const char *data, const char *field, char *value);
int parseIntField(const char *data, const char *field);
int extract_substring(const char *input_string, const char *start_token, const char *end_token, char *result);
void addSensorListParams(char *paramString, DEVICE_PARAMS *device);
void addCommandListParams(char *paramString, DEVICE_PARAMS *device);
/**
 * @brief  解析输入字符串网关结构体信息，将数据保存
 * @param  char *gatewayString 输入字符串的数据
 * @retval 无
 */
void addGatewayParams(char *gatewayString)
{
		//gateway_config_params.device_params = NULL;
		gateway_config_params.port = parseIntField(gatewayString, "\"port\":");
		gateway_config_params.stopBit = parseIntField(gatewayString, "\"stopBit\":");
		gateway_config_params.dataBits = parseIntField(gatewayString, "\"dataBit\":");
		gateway_config_params.baudrate = parseIntField(gatewayString, "\"baudrate\":");
		gateway_config_params.checkBit = parseIntField(gatewayString, "\"checkBit\":");
		gateway_config_params.inboundTime= parseIntField(gatewayString, "\"inboundTime\":");
		gateway_config_params.comProtocol= parseIntField(gatewayString, "\"comProtocol\":");
		
		parseStringField(gatewayString, "\"host\":\"", (char *)&gateway_config_params.host);
		parseStringField(gatewayString, "\"deviceId\":\"", (char *)&gateway_config_params.deviceId);
		parseStringField(gatewayString, "\"commandTopic\":\"", (char *)&gateway_config_params.commandTopic);
		parseStringField(gatewayString, "\"messageTopic\":\"", (char *)&gateway_config_params.messageTopic);
		parseStringField(gatewayString, "\"username\":\"", (char *)&gateway_config_params.username);
		parseStringField(gatewayString, "\"password\":\"", (char *)&gateway_config_params.passwd);
	
		char *deviceString = strstr(gatewayString,"deviceList");  //移位置到节点数据开始处

		while (1)
    {
        if (deviceString)
        {
           addDevice(deviceString); // 往此地址下挂载设备信息
           deviceString=deviceString;//重新获取设备字符串的位置
					 deviceString = strstr(deviceString, "}"); 
					 deviceString[0]='A';
					 deviceString++;
					 if(deviceString[0]==']')
					 {
					 break;
					 }
        }
        else
        {
            return;
        }
    }
}

/**
 * @brief  解析输入字段的字符串，解析出属于该节点下的设备信息
 * @param  uint8_t *string输入的字符串数据,NODE_PARAMS *node节点信息
 * @retval 无
 */

void addDevice(char *deviceString)
{
    char *paramString = (char *)deviceString; // 属性指针
		DEVICE_PARAMS *newDevicePage = (DEVICE_PARAMS *)mymalloc(SRAMEX, sizeof(DEVICE_PARAMS));    // 创建新设备页
    newDevicePage->nextDevice = NULL;
    newDevicePage->protocol = parseIntField(deviceString, "\"protocol\":");
		newDevicePage->MDBdataType = parseIntField(deviceString, "\"dataType\":");
		newDevicePage->MDBbigLittleFormat = parseIntField(deviceString, "\"bigLittleFormat\":");
		
		parseStringField(deviceString, "\"deviceId\":\"", (char *)&newDevicePage->deviceID);
		
    newDevicePage->params = (PARAMS_PROTOCOL_COMMAND *)mymalloc(SRAMEX,sizeof(PARAMS_PROTOCOL_COMMAND));
		memset(newDevicePage->params, 0, sizeof(PARAMS_PROTOCOL_COMMAND));
    paramString = strstr(paramString, "\"sensorData\":["); // 找到该节点的轮询上发属性
    while (1)                                              // 此处数据是以数组形式存储所以解析方法和上面不一样
    {
        addSensorListParams(paramString, newDevicePage); // 解析一个属性并挂载该属性于该属性下
				paramString=paramString;
        paramString = strstr(paramString, "}");          // 移动到下一条属性
				paramString[0]='A';
        paramString++;
        if (paramString[0] == ']')
        {
            paramString = (char *)deviceString; // 复原指针位置
						break;                              // 找到了结束符，跳出循环
        }
    }
		if(newDevicePage->protocol==MODBUS)  //如果为modbus的话解析写指令
		{
			paramString=deviceString;                                //移动到最开始的地方
			newDevicePage->MDBbigLittleFormat = parseIntField(paramString, "\"bigLittleFormat\":");
      newDevicePage->MDBdataType= parseIntField(paramString, "\"dataType\":");
		  paramString = strstr(paramString, "\"commandData\":["); // 找到其轮询的写命令
			if(paramString!=NULL)
			{
				while(1)
				{
					addCommandListParams(paramString, newDevicePage);
					paramString = strstr(paramString, "}");
				  paramString[0]='A';
					paramString++;
					if (paramString[0] == ']')
					{
						paramString = (char *)deviceString;// 复原指针位置
						break;														 // 找到了结束符，跳出循环
					}
				}
			}
		}
    // 解析下发的mqtt存储信息下发控制指令
		
    // 添加设备页到链表末尾
    if (gateway_config_params.device_params == NULL)
    {
        gateway_config_params.device_params = newDevicePage;
    }
    else
    {
        DEVICE_PARAMS *current = gateway_config_params.device_params;
        while (current->nextDevice != NULL)
        {
            current = current->nextDevice;
        }
        current->nextDevice = newDevicePage;
    }
		//解析modbus command指令将其加载到设备链表中
		
}
/**
 * @brief  解析输入字符串的paramString数据,将数据保存到至该设备结构体下，此处解析sensorList
 * @param  uint8_t *paramString输入的字符串数据,DEVICE_PARAMS *device节点信息
 * @retval 无
 */
void addSensorListParams(char *paramString, DEVICE_PARAMS *device)
{
    switch (device->protocol)
    {
    case DLT645_97:
    case DLT645_07:
		{
        GATEWAY_READ_DLT645_COMMAND *read_dlt645_command = mymalloc(SRAMEX,sizeof(GATEWAY_READ_DLT645_COMMAND));
        read_dlt645_command->Identification = parseIntField(paramString, "\"identifier645\":");
        parseStringField(paramString, "\"identifier\":\"", (char *)&read_dlt645_command->keyword);
        char *string = mymalloc(SRAMEX,13);
        parseStringField(paramString, "\"deviceID645\":\"", string);
        for (int j = 0; j < 6; j++)
        {
          uint8_t byte;
          sscanf((const char *)&string[j * 2], "%2hhx", &byte);
          read_dlt645_command->deviceID645[j]=byte;
        }				
        myfree(SRAMEX, string);
				string = NULL;
        if (device->params->gateway_read_dlt645_command == NULL)
        {
            device->params->gateway_read_dlt645_command = read_dlt645_command;
        }
        else
        {
            GATEWAY_READ_DLT645_COMMAND *current = device->params->gateway_read_dlt645_command;
            while (current->nextParams != NULL)
            {
                current = current->nextParams;
            }
            current->nextParams = read_dlt645_command;
        }
			}
				
        break;
    case MODBUS:
		{
        GATEWAY_READ_MODBUS_COMMAND *read_modbus_command = mymalloc(SRAMEX,sizeof(GATEWAY_READ_MODBUS_COMMAND));
				memset(read_modbus_command, 0, sizeof(GATEWAY_READ_MODBUS_COMMAND));
				parseStringField(paramString,"\"identifier\":\"",(char *)&read_modbus_command->keyword);
        read_modbus_command->decimalPoint = parseIntField(paramString, "\"precise\":");
        read_modbus_command->functionCode = parseIntField(paramString, "\"rFunctionCode\":");
        read_modbus_command->slaveAddress = parseIntField(paramString, "\"slaveAddress\":");
        read_modbus_command->registerAddress = parseIntField(paramString, "\"registerAddress\":");
        read_modbus_command->registerByteNum = parseIntField(paramString, "\"registerByteNum\":");
        
			if (device->params->gateway_read_modbus_command== NULL)
        {
            device->params->gateway_read_modbus_command = read_modbus_command;
        }
        else
        {
            GATEWAY_READ_MODBUS_COMMAND *current = device->params->gateway_read_modbus_command;
            while (current->nextParams != NULL)
            {
                current = current->nextParams;
            }
            current->nextParams = read_modbus_command;
        }
			}
        break;	
			
		case CTJ1883:
		{
        GATEWAY_READ_CJT_COMMAND *read_cjt_command = mymalloc(SRAMEX,sizeof(GATEWAY_READ_CJT_COMMAND));
				memset(read_cjt_command, 0, sizeof(GATEWAY_READ_CJT_COMMAND));
				parseStringField(paramString,"\"identifier\":\"",(char *)&read_cjt_command->keyword);			
				char *string = mymalloc(SRAMEX,15);
        parseStringField(paramString, "\"deviceID188\":\"", string);
        for (int j = 0; j < 7; j++)
        {
          uint8_t byte;
          sscanf((const char *)&string[j * 2], "%2hhx", &byte);
          read_cjt_command->deviceAddress[j]=byte;
        }				
        myfree(SRAMEX, string);
				string = NULL;
        parseStringField(paramString,"\"cmd\":\"",(char *)&read_cjt_command->cmd);
				
				if (device->params->gateway_read_cjt_command== NULL)
        {
            device->params->gateway_read_cjt_command = read_cjt_command;
        }
        else
        {
            GATEWAY_READ_CJT_COMMAND *current = device->params->gateway_read_cjt_command;
            while (current->nextParams != NULL)
            {
                current = current->nextParams;
            }
            current->nextParams = read_cjt_command;
        }
		}
        break;
    default:
        break;
    }
}
/**
 * @brief  解析输入字符串的paramString数据,将数据保存到至该设备结构体下，此处解析commandList
 * @param  uint8_t *paramString输入的字符串数据,DEVICE_PARAMS *device节点信息
 * @retval 无
 */
void addCommandListParams(char *paramString, DEVICE_PARAMS *device)
{
	
 	GATEWAY_WRITE_MODBUS_COMMAND *write_modbus_command=mymalloc(SRAMEX,sizeof(GATEWAY_WRITE_MODBUS_COMMAND));
	memset(write_modbus_command, 0, sizeof(GATEWAY_WRITE_MODBUS_COMMAND));
	parseStringField(paramString,"\"identifier\":\"",(char *)&write_modbus_command->keyword);
	write_modbus_command->functionCode=parseIntField(paramString, "\"wFunctionCode\":");
	write_modbus_command->slaveAddress=parseIntField(paramString, "\"slaveAddress\":");
	write_modbus_command->registerAddress = parseIntField(paramString, "\"registerAddress\":");
	write_modbus_command->registerByteNum = parseIntField(paramString, "\"registerByteNum\":");
	if(device->params->gateway_write_modbus_command == NULL)
	{
		device->params->gateway_write_modbus_command=write_modbus_command;
	}
	else
	{
		GATEWAY_WRITE_MODBUS_COMMAND *current=device->params->gateway_write_modbus_command;
    while (current->nextParams != NULL)
    {
      current = current->nextParams;
    }
    current->nextParams = write_modbus_command;		
	}
}
// 提取int数据
int parseIntField(const char *data, const char *field)
{

    char *ptr = strstr(data, field) + strlen(field);
    int value;
    value = strtol(ptr, &ptr, 10);
    return value;
}

// 提取string字符串
void parseStringField(const char *data, const char *field, char *value)
{
    char *ptr = strstr(data, field) + strlen(field);
    sscanf(ptr, "%[^\"],", value);
}

// 不采用json解析硬解json数据
void processStringJson(uint8_t *data)
{
    GATEWAY_PARAMS *gateway;
    gateway = get_gateway_config_params();
    uint8_t *ptr = (uint8_t *)data;
    parseStringField((char *)&ptr, "\"messageTopic\":\"", (char *)&gateway->messageTopic);
    parseStringField((char *)&ptr, "\"commandTopic\":\"", (char *)&gateway->commandTopic);
    gateway->port = parseIntField((char *)&ptr, "\"port\":\"");
    parseStringField((char *)&ptr, "\"host\":\"", (char *)&gateway->host);
    parseStringField((char *)&ptr, "\"deviceId\":\"", (char *)&gateway->deviceId);
    // 解析最外层数据完成,申请空间存储节点信息

    int nodeNum = 1;
    char *node_index = mymalloc(SRAMEX,10);
    sprintf(node_index, "node_%d", nodeNum);
    strstr(ptr, node_index); // 将指针指向第一个节点
    while (*ptr == NULL)
    {

    }
    myfree(SRAMEX, node_index);
}
/**
 * @brief  从输入的input_string中寻找开始到结束位置的字符串数据，并将数据截取出来，传给result;
 * @param  input_string输入字符串，start_token字符串起始位置，end_token字符串结束位置，result截取出的字符串
 * @retval 0:没有被截取到的字符串。1：有被截取到的字符串。
 */
int extract_substring(const char *input_string, const char *start_token, const char *end_token, char *result)
{
    const char *start_ptr = strstr(input_string, start_token);

    if (start_ptr == NULL)
    {
        return 0; // 未找到起始标记
    }

    start_ptr += strlen(start_token); // 移动指针到起始标记之后

    const char *end_ptr = strstr(start_ptr, end_token);

    if (end_ptr == NULL)
    {
        // 如果未找到结束标记，将从起始标记开始的字符串一直复制到 \0 结束
        strcpy(result, start_ptr);
    }
    else
    {
        // 找到结束标记，计算截取的长度并复制
        size_t length = end_ptr - start_ptr;
        strncpy(result, start_ptr, length);
        result[length] = '\0'; // 添加字符串结束符
    }
    return 1;
}


