gateway_message.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. #include "string.h"
  2. #include <stdlib.h>
  3. #include "protocol.h"
  4. #include "malloc.h"
  5. #include "gateway_message.h"
  6. GATEWAY_PARAMS gateway_config_params = {0};
  7. GATEWAY_PARAMS *get_gateway_config_params()
  8. {
  9. return &gateway_config_params;
  10. }
  11. void parseStringField(const char *data, const char *field, char *value);
  12. int parseIntField(const char *data, const char *field);
  13. void addNode(char *nodestring);
  14. void addDevice(char *string, NODE_PARAMS *node);
  15. int extract_substring(const char *input_string, const char *start_token, const char *end_token, char *result);
  16. void addSensorListParams(char *paramString, DEVICE_PARAMS *device);
  17. void addCommandListParams(char *paramString, DEVICE_PARAMS *device);
  18. /**
  19. * @brief 解析输入字符串网关结构体信息,将数据保存
  20. * @param char *nodestring 输入字符串的数据
  21. * @retval 无
  22. */
  23. void addGatewayParams(char *gatewayString)
  24. {
  25. parseStringField(gatewayString, "\"commandTopic\":\"", (char *)&gateway_config_params.commandTopic);
  26. parseStringField(gatewayString, "\"messageTopic\":\"", (char *)&gateway_config_params.messageTopic);
  27. parseStringField(gatewayString, "\"deviceId\":\"", (char *)&gateway_config_params.deviceId);
  28. parseStringField(gatewayString, "\"host\":\"", (char *)&gateway_config_params.host);
  29. gateway_config_params.port = parseIntField(gatewayString, "\"port\":");
  30. gateway_config_params.node_params = NULL;
  31. gateway_config_params.pollTime = parseIntField(gatewayString, "\"pollTime\":");
  32. char *nodeString = strstr(gatewayString,"nodeList"); //移位置到节点数据开始处
  33. while (1)
  34. {
  35. addNode(nodeString);
  36. nodeString=nodeString;
  37. nodeString=strstr(nodeString,"}");
  38. nodeString[0]='A';
  39. nodeString++;
  40. if(nodeString[0]==']')//数组结束标志、
  41. {
  42. break;
  43. }
  44. }
  45. }
  46. /**
  47. * @brief 解析输入的字符串节点信息,并将此节点信息挂载在网关结构体的节点下面
  48. * @param char *nodestring
  49. * @retval 无
  50. 注:node内包含的设备名称device_1在别的节点下也可能包含,所以在解析节点时要先将数据截取出来让匹配不会越界到别的节点
  51. */
  52. void addNode(char *nodestring)
  53. {
  54. // 新增一个节点的设备并解析最外层的节点属性
  55. char *deviceString = (char *)nodestring; // 用于移位解析device设备信息
  56. NODE_PARAMS *newNode = malloc(sizeof(NODE_PARAMS));
  57. newNode->device_params = NULL; // 先将其设备挂载为NULL
  58. newNode->nextNode = NULL; // 下一个设备的挂载为NULL
  59. char nodeIdString[5];
  60. parseStringField(nodestring, "\"nodeId\":\"", (char *)&nodeIdString);
  61. for (int j = 0; j < 2; j++)
  62. {
  63. uint8_t byte;
  64. sscanf((const char *)&nodeIdString[j * 2], "%2hhx", &byte);
  65. newNode->node_address[j]=byte;
  66. }
  67. newNode->RFFrequency = parseIntField(nodestring, "\"RFFrequency\":");
  68. newNode->SignalBw = parseIntField(nodestring, "\"SignalBw\":");
  69. newNode->SpreadingFactor = parseIntField(nodestring, "\"SpreadingFactor\":");
  70. newNode->ErrorCoding = parseIntField(nodestring, "\"ErrorCoding\":");
  71. deviceString=strstr(nodestring,"deviceList");//移位置到设备数组起始处
  72. while (1)
  73. {
  74. if (deviceString)
  75. {
  76. addDevice(deviceString, newNode); // 往此节点下挂载设备信息
  77. deviceString=deviceString;//重新获取设备字符串的位置
  78. deviceString = strstr(deviceString, "}");
  79. deviceString[0]='A';
  80. deviceString++;
  81. if(deviceString[0]==']')
  82. {
  83. break;
  84. }
  85. }
  86. else
  87. {
  88. return;
  89. }
  90. /* code */
  91. }
  92. // 添加节点到网关链表中
  93. if (gateway_config_params.node_params == NULL)
  94. {
  95. gateway_config_params.node_params = newNode;
  96. }
  97. else
  98. {
  99. NODE_PARAMS *current = gateway_config_params.node_params;
  100. while (current->nextNode != NULL)
  101. {
  102. current = current->nextNode;
  103. }
  104. current->nextNode = newNode;
  105. }
  106. }
  107. /**
  108. * @brief 解析输入字段的字符串,解析出属于该节点下的设备信息
  109. * @param uint8_t *string输入的字符串数据,NODE_PARAMS *node节点信息
  110. * @retval 无
  111. */
  112. void addDevice(char *deviceString, NODE_PARAMS *node)
  113. {
  114. char *paramString = (char *)deviceString; // 属性指针
  115. // 创建新设备页
  116. DEVICE_PARAMS *newDevicePage = (DEVICE_PARAMS *)malloc(sizeof(DEVICE_PARAMS));
  117. newDevicePage->nextDevice = NULL;
  118. parseStringField(deviceString, "\"deviceId\":\"", (char *)&newDevicePage->deviceID);
  119. newDevicePage->protocol = parseIntField(deviceString, "\"protocol\":");
  120. newDevicePage->params = (PARAMS_PROTOCOL_COMMAND *)malloc(sizeof(PARAMS_PROTOCOL_COMMAND));
  121. paramString = strstr(paramString, "\"sensorData\":["); // 找到该节点的轮询上发属性
  122. while (1) // 此处数据是以数组形式存储所以解析方法和上面不一样
  123. {
  124. addSensorListParams(paramString, newDevicePage); // 解析一个属性并挂载该属性于该属性下
  125. paramString=paramString;
  126. paramString = strstr(paramString, "}"); // 移动到下一条属性
  127. paramString[0]='A';
  128. paramString++;
  129. if (paramString[0] == ']')
  130. {
  131. paramString = (char *)deviceString; // 复原指针位置
  132. break; // 找到了结束符,跳出循环
  133. }
  134. }
  135. if(newDevicePage->protocol==MODBUS) //如果为modbus的话解析写指令
  136. {
  137. paramString=deviceString; //移动到最开始的地方
  138. newDevicePage->MDBbigLittleFormat = parseIntField(paramString, "\"bigLittleFormat\":");
  139. newDevicePage->MDBdataType= parseIntField(paramString, "\"dataType\":");
  140. paramString = strstr(paramString, "\"commandData\":["); // 找到其轮询的写命令
  141. if(paramString!=NULL)
  142. {
  143. while(1)
  144. {
  145. addCommandListParams(paramString, newDevicePage);
  146. paramString = strstr(paramString, "}");
  147. paramString[0]='A';
  148. paramString++;
  149. if (paramString[0] == ']')
  150. {
  151. paramString = (char *)deviceString;
  152. break;
  153. }
  154. }
  155. }
  156. }
  157. // 解析下发的mqtt存储信息下发控制指令
  158. // 添加设备页到链表末尾
  159. if (node->device_params == NULL)
  160. {
  161. node->device_params = newDevicePage;
  162. }
  163. else
  164. {
  165. DEVICE_PARAMS *current = node->device_params;
  166. while (current->nextDevice != NULL)
  167. {
  168. current = current->nextDevice;
  169. }
  170. current->nextDevice = newDevicePage;
  171. }
  172. //解析modbus command指令将其加载到设备链表中
  173. }
  174. /**
  175. * @brief 解析输入字符串的paramString数据,将数据保存到至该设备结构体下,此处解析sensorList
  176. * @param uint8_t *paramString输入的字符串数据,DEVICE_PARAMS *device节点信息
  177. * @retval 无
  178. */
  179. void addSensorListParams(char *paramString, DEVICE_PARAMS *device)
  180. {
  181. switch (device->protocol)
  182. {
  183. case DLT645_97:
  184. case DLT645_07:
  185. {
  186. NODE_READ_DLT645_COMMAND *read_dlt645_command = malloc(sizeof(NODE_READ_DLT645_COMMAND));
  187. read_dlt645_command->Identification = parseIntField(paramString, "\"identifier645\":");
  188. parseStringField(paramString, "\"identifier\":\"", (char *)&read_dlt645_command->keyword);
  189. char *string = mymalloc(SRAMIN, 13);
  190. parseStringField(paramString, "\"deviceID645\":\"", string);
  191. for (int j = 0; j < 6; j++)
  192. {
  193. uint8_t byte;
  194. sscanf((const char *)&string[j * 2], "%2hhx", &byte);
  195. read_dlt645_command->deviceID645[j]=byte;
  196. }
  197. myfree(SRAMIN, string);
  198. if (device->params->node_read_dlt645_command == NULL)
  199. {
  200. device->params->node_read_dlt645_command = read_dlt645_command;
  201. }
  202. else
  203. {
  204. NODE_READ_DLT645_COMMAND *current = device->params->node_read_dlt645_command;
  205. while (current->nextParams != NULL)
  206. {
  207. current = current->nextParams;
  208. }
  209. current->nextParams = read_dlt645_command;
  210. }
  211. }
  212. break;
  213. case MODBUS:
  214. {
  215. NODE_READ_MODBUS_COMMAND *read_modbus_command = malloc(sizeof(NODE_READ_MODBUS_COMMAND));
  216. parseStringField(paramString,"\"identifier\":\"",(char *)&read_modbus_command->keyword);
  217. read_modbus_command->decimalPoint = parseIntField(paramString, "\"precise\":");
  218. read_modbus_command->functionCode = parseIntField(paramString, "\"rFunctionCode\":");
  219. read_modbus_command->slaveAddress = parseIntField(paramString, "\"slaveAddress\":");
  220. read_modbus_command->registerAddress = parseIntField(paramString, "\"registerAddress\":");
  221. read_modbus_command->registerByteNum = parseIntField(paramString, "\"registerByteNum\":");
  222. if (device->params->node_read_modbus_command == NULL)
  223. {
  224. device->params->node_read_modbus_command = read_modbus_command;
  225. }
  226. else
  227. {
  228. NODE_READ_MODBUS_COMMAND *current = device->params->node_read_modbus_command;
  229. while (current->nextParams != NULL)
  230. {
  231. current = current->nextParams;
  232. }
  233. current->nextParams = read_modbus_command;
  234. }
  235. }
  236. break;
  237. default:
  238. break;
  239. }
  240. }
  241. /**
  242. * @brief 解析输入字符串的paramString数据,将数据保存到至该设备结构体下,此处解析commandList
  243. * @param uint8_t *paramString输入的字符串数据,DEVICE_PARAMS *device节点信息
  244. * @retval 无
  245. */
  246. void addCommandListParams(char *paramString, DEVICE_PARAMS *device)
  247. {
  248. NODE_WRITE_MODBUS_COMMAND *write_modbus_command=malloc(sizeof(NODE_WRITE_MODBUS_COMMAND));
  249. parseStringField(paramString,"\"identifier\":\"",(char *)&write_modbus_command->keyword);
  250. write_modbus_command->functionCode=parseIntField(paramString, "\"wFunctionCode\":");
  251. write_modbus_command->slaveAddress=parseIntField(paramString, "\"slaveAddress\":");
  252. write_modbus_command->registerAddress = parseIntField(paramString, "\"registerAddress\":");
  253. if(device->params->node_write_modbus_command == NULL)
  254. {
  255. device->params->node_write_modbus_command=write_modbus_command;
  256. }
  257. else
  258. {
  259. NODE_WRITE_MODBUS_COMMAND *current=device->params->node_write_modbus_command;
  260. while (current->nextParams != NULL)
  261. {
  262. current = current->nextParams;
  263. }
  264. current->nextParams = write_modbus_command;
  265. }
  266. }
  267. // 提取int数据
  268. int parseIntField(const char *data, const char *field)
  269. {
  270. char *ptr = strstr(data, field) + strlen(field);
  271. int value;
  272. value = strtol(ptr, &ptr, 10);
  273. return value;
  274. }
  275. // 提取string字符串
  276. void parseStringField(const char *data, const char *field, char *value)
  277. {
  278. char *ptr = strstr(data, field) + strlen(field);
  279. sscanf(ptr, "%[^\"],", value);
  280. }
  281. // 不采用json解析硬解json数据
  282. void processStringJson(uint8_t *data)
  283. {
  284. GATEWAY_PARAMS *gateway;
  285. gateway = get_gateway_config_params();
  286. uint8_t *ptr = (uint8_t *)data;
  287. parseStringField((char *)&ptr, "\"messageTopic\":\"", (char *)&gateway->messageTopic);
  288. parseStringField((char *)&ptr, "\"commandTopic\":\"", (char *)&gateway->commandTopic);
  289. gateway->port = parseIntField((char *)&ptr, "\"port\":\"");
  290. parseStringField((char *)&ptr, "\"host\":\"", (char *)&gateway->host);
  291. parseStringField((char *)&ptr, "\"deviceId\":\"", (char *)&gateway->deviceId);
  292. // 解析最外层数据完成,申请空间存储节点信息
  293. int nodeNum = 1;
  294. char *node_index = malloc(10);
  295. sprintf(node_index, "node_%d", nodeNum);
  296. strstr(ptr, node_index); // 将指针指向第一个节点
  297. while (*ptr == NULL)
  298. {
  299. }
  300. free(node_index);
  301. }
  302. /**
  303. * @brief 从输入的input_string中寻找开始到结束位置的字符串数据,并将数据截取出来,传给result;
  304. * @param input_string输入字符串,start_token字符串起始位置,end_token字符串结束位置,result截取出的字符串
  305. * @retval 0:没有被截取到的字符串。1:有被截取到的字符串。
  306. */
  307. int extract_substring(const char *input_string, const char *start_token, const char *end_token, char *result)
  308. {
  309. const char *start_ptr = strstr(input_string, start_token);
  310. if (start_ptr == NULL)
  311. {
  312. return 0; // 未找到起始标记
  313. }
  314. start_ptr += strlen(start_token); // 移动指针到起始标记之后
  315. const char *end_ptr = strstr(start_ptr, end_token);
  316. if (end_ptr == NULL)
  317. {
  318. // 如果未找到结束标记,将从起始标记开始的字符串一直复制到 \0 结束
  319. strcpy(result, start_ptr);
  320. }
  321. else
  322. {
  323. // 找到结束标记,计算截取的长度并复制
  324. size_t length = end_ptr - start_ptr;
  325. strncpy(result, start_ptr, length);
  326. result[length] = '\0'; // 添加字符串结束符
  327. }
  328. return 1;
  329. }