#include "string.h" #include #include "protocol.h" #include "malloc.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); void addNode(char *nodestring); void addDevice(char *string, NODE_PARAMS *node); 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 *nodestring 输入字符串的数据 * @retval 无 */ void addGatewayParams(char *gatewayString) { parseStringField(gatewayString, "\"commandTopic\":\"", (char *)&gateway_config_params.commandTopic); parseStringField(gatewayString, "\"messageTopic\":\"", (char *)&gateway_config_params.messageTopic); parseStringField(gatewayString, "\"deviceId\":\"", (char *)&gateway_config_params.deviceId); parseStringField(gatewayString, "\"host\":\"", (char *)&gateway_config_params.host); gateway_config_params.port = parseIntField(gatewayString, "\"port\":"); gateway_config_params.node_params = NULL; gateway_config_params.pollTime = parseIntField(gatewayString, "\"pollTime\":"); char *nodeString = strstr(gatewayString,"nodeList"); //移位置到节点数据开始处 while (1) { addNode(nodeString); nodeString=nodeString; nodeString=strstr(nodeString,"}"); nodeString[0]='A'; nodeString++; if(nodeString[0]==']')//数组结束标志、 { break; } } } /** * @brief 解析输入的字符串节点信息,并将此节点信息挂载在网关结构体的节点下面 * @param char *nodestring * @retval 无 注:node内包含的设备名称device_1在别的节点下也可能包含,所以在解析节点时要先将数据截取出来让匹配不会越界到别的节点 */ void addNode(char *nodestring) { // 新增一个节点的设备并解析最外层的节点属性 char *deviceString = (char *)nodestring; // 用于移位解析device设备信息 NODE_PARAMS *newNode = malloc(sizeof(NODE_PARAMS)); newNode->device_params = NULL; // 先将其设备挂载为NULL newNode->nextNode = NULL; // 下一个设备的挂载为NULL char nodeIdString[5]; parseStringField(nodestring, "\"nodeId\":\"", (char *)&nodeIdString); for (int j = 0; j < 2; j++) { uint8_t byte; sscanf((const char *)&nodeIdString[j * 2], "%2hhx", &byte); newNode->node_address[j]=byte; } newNode->RFFrequency = parseIntField(nodestring, "\"RFFrequency\":"); newNode->SignalBw = parseIntField(nodestring, "\"SignalBw\":"); newNode->SpreadingFactor = parseIntField(nodestring, "\"SpreadingFactor\":"); newNode->ErrorCoding = parseIntField(nodestring, "\"ErrorCoding\":"); deviceString=strstr(nodestring,"deviceList");//移位置到设备数组起始处 while (1) { if (deviceString) { addDevice(deviceString, newNode); // 往此节点下挂载设备信息 deviceString=deviceString;//重新获取设备字符串的位置 deviceString = strstr(deviceString, "}"); deviceString[0]='A'; deviceString++; if(deviceString[0]==']') { break; } } else { return; } /* code */ } // 添加节点到网关链表中 if (gateway_config_params.node_params == NULL) { gateway_config_params.node_params = newNode; } else { NODE_PARAMS *current = gateway_config_params.node_params; while (current->nextNode != NULL) { current = current->nextNode; } current->nextNode = newNode; } } /** * @brief 解析输入字段的字符串,解析出属于该节点下的设备信息 * @param uint8_t *string输入的字符串数据,NODE_PARAMS *node节点信息 * @retval 无 */ void addDevice(char *deviceString, NODE_PARAMS *node) { char *paramString = (char *)deviceString; // 属性指针 // 创建新设备页 DEVICE_PARAMS *newDevicePage = (DEVICE_PARAMS *)malloc(sizeof(DEVICE_PARAMS)); newDevicePage->nextDevice = NULL; parseStringField(deviceString, "\"deviceId\":\"", (char *)&newDevicePage->deviceID); newDevicePage->protocol = parseIntField(deviceString, "\"protocol\":"); newDevicePage->params = (PARAMS_PROTOCOL_COMMAND *)malloc(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 (node->device_params == NULL) { node->device_params = newDevicePage; } else { DEVICE_PARAMS *current = node->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: { NODE_READ_DLT645_COMMAND *read_dlt645_command = malloc(sizeof(NODE_READ_DLT645_COMMAND)); read_dlt645_command->Identification = parseIntField(paramString, "\"identifier645\":"); parseStringField(paramString, "\"identifier\":\"", (char *)&read_dlt645_command->keyword); char *string = mymalloc(SRAMIN, 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(SRAMIN, string); if (device->params->node_read_dlt645_command == NULL) { device->params->node_read_dlt645_command = read_dlt645_command; } else { NODE_READ_DLT645_COMMAND *current = device->params->node_read_dlt645_command; while (current->nextParams != NULL) { current = current->nextParams; } current->nextParams = read_dlt645_command; } } break; case MODBUS: { NODE_READ_MODBUS_COMMAND *read_modbus_command = malloc(sizeof(NODE_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->node_read_modbus_command == NULL) { device->params->node_read_modbus_command = read_modbus_command; } else { NODE_READ_MODBUS_COMMAND *current = device->params->node_read_modbus_command; while (current->nextParams != NULL) { current = current->nextParams; } current->nextParams = read_modbus_command; } } break; default: break; } } /** * @brief 解析输入字符串的paramString数据,将数据保存到至该设备结构体下,此处解析commandList * @param uint8_t *paramString输入的字符串数据,DEVICE_PARAMS *device节点信息 * @retval 无 */ void addCommandListParams(char *paramString, DEVICE_PARAMS *device) { NODE_WRITE_MODBUS_COMMAND *write_modbus_command=malloc(sizeof(NODE_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\":"); if(device->params->node_write_modbus_command == NULL) { device->params->node_write_modbus_command=write_modbus_command; } else { NODE_WRITE_MODBUS_COMMAND *current=device->params->node_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 = malloc(10); sprintf(node_index, "node_%d", nodeNum); strstr(ptr, node_index); // 将指针指向第一个节点 while (*ptr == NULL) { } free(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; }