protocol.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #include "protocol.h"
  2. #include "stdint.h"
  3. #include "stdlib.h"
  4. #include "string.h"
  5. #include "node_message.h"
  6. /*****************************protocol主要为主网关与子节点通讯的协议使用**********************************/
  7. /*****************************其主要作用主网关给子节点轮询发送数据的编码**********************************/
  8. /*****************************子节点解析该主网关发送的数据 **********************************/
  9. /*****************************子节点回应对应的响应 **********************************/
  10. /*****************************子节点回应对应的响应的解析 **********************************/
  11. static volatile int deviceNum = 0; // 记录轮询读取设备的结束位置
  12. static volatile int paramsNum = 0; // 记录轮询读取属性的结束位置
  13. static volatile int startDeviceNum = 0; // 记录轮询读取设备的开始位置
  14. static volatile int startParamsNum = 0; // 记录轮询读取设备属性的开始位置
  15. void insertHexData(uint8_t *String, const uint8_t *hexData, uint8_t insertIndex, uint8_t length);
  16. enum
  17. {
  18. protocol_dlt645_97 = 0x08,
  19. protocol_modbus_read,
  20. protocol_dlt645_07
  21. } PROTOCOL_LENGTH; // 每个协议的数据包长度用于最开始区分不同协议
  22. // 枚举采集数据的存储个数
  23. enum
  24. {
  25. typeInt = 1,
  26. typeFloat,
  27. typeDouble
  28. } DATAType;
  29. // 枚举MODBUS协议具体功能
  30. enum
  31. {
  32. READ_COIL = 0x01,
  33. WRITE_COIL = 0x05,
  34. WRITE_COILS = 0x0F,
  35. READ_REGISTER = 0x03,
  36. WRITE_REFISTER = 0x06,
  37. WRITE_REGISTERS = 0x10
  38. } MODBUS_COMMAND;
  39. // 大小端
  40. typedef enum
  41. {
  42. MModBus_16bitOrder_AB = 1, // 大端
  43. MModBus_16bitOrder_BA,
  44. } MModBus_16bitOrder_t;
  45. /*
  46. *********************************************************************************************************
  47. * 函 数 名: void masterSendNodeString(uint8_t nodeIndex)Index下标从0开始
  48. * 功能说明: 负责取出网关第nodeIndex下的数据组成下发格式的数据,注:此处没有对node是否为NULL进行判断,请确保有该节点的信息
  49. * 形 参:无
  50. * 返 回 值: 0:该节点下已经没有属性需要在去读出了,1:该节点下还拥有其他属性等待读出。
  51. 注:其一次性只能传输20条属性的值若超出其范围还有数据则要多次组成发送
  52. 逻辑:每次调用该函数都会总成一条string,属性足够的时候会组成一条具有20个属性的指令,并记录结束的设备链表位置,属性链表位置,下次再调用从结束位置再开始,到最后可能就组成不了20个属性的string了,此时将开始的设备num,属性都归位
  53. 且也要记录每次开始的设备位置和属性位置,方便接收应答信号的解析
  54. *********************************************************************************************************
  55. */
  56. int masterSendNodeString(uint8_t nodeIndex, uint8_t *string, uint16_t *size)
  57. {
  58. startDeviceNum = deviceNum; // 起始位置等于上次结束的位置
  59. startParamsNum = paramsNum; // 起始位置等于上次结束的位置
  60. int nowDeviceNum = deviceNum;
  61. int nowparamsNum = paramsNum;
  62. GATEWAY_PARAMS *gateway;
  63. gateway = get_gateway_config_params();
  64. // 将当前的节点指针指到需要读取的节点位置
  65. NODE_PARAMS *currentNode = gateway->node_params;
  66. while (nodeIndex)
  67. {
  68. currentNode = currentNode->nextNode;
  69. nodeIndex--;
  70. }
  71. string = malloc(257);
  72. memset(string, 0, 257);
  73. // 将首字符用nodeAdress
  74. string[0] = currentNode->node_address[0];
  75. string[1] = currentNode->node_address[1];
  76. // 找到当前的设备结束位置
  77. DEVICE_PARAMS *currentDevice = currentNode->device_params;
  78. while (!nowDeviceNum)
  79. {
  80. currentDevice = currentDevice->nextDevice;
  81. nowDeviceNum--;
  82. }
  83. PARAMS_PROTOCOL_COMMAND *currentParams = currentDevice->params;
  84. // 移动位置到结束位置属性的下一位
  85. while (!nowparamsNum)
  86. {
  87. currentParams = currentParams->nextParams;
  88. nowparamsNum--;
  89. }
  90. if (currentParams == NULL)
  91. {
  92. currentDevice = currentDevice->nextDevice;
  93. // 判断当前还有没有设备没有读取了
  94. if (currentDevice == NULL) // 且当前链表无后续设备了则跳出循环
  95. {
  96. deviceNum = 0; // 将结束位置全部归0
  97. paramsNum = 0;
  98. return -1;
  99. }
  100. currentParams = currentDevice->params; // 有则更新当前指针位置
  101. nowDeviceNum++;
  102. nowparamsNum = 0;
  103. }
  104. // 最多进行20次循环组成下发数据
  105. int i = 0;
  106. int len = strlen((char *)&string);
  107. do
  108. {
  109. switch (currentDevice->protocol)
  110. {
  111. case MODBUS_READ:
  112. insertHexData(string, (uint8_t *)protocol_modbus_read, len, 1); // 插入modbus长度
  113. len++;
  114. insertHexData(string, &currentParams->node_read_modbus_command->functionCode, len, 1); // 插入读取功能码
  115. len++;
  116. insertHexData(string, &currentParams->node_read_modbus_command->dataType, len, 1); // 插入读取的数据格式
  117. len++;
  118. insertHexData(string, &currentParams->node_read_modbus_command->slaveAddress, len, 1); // 插入modbus从站地址
  119. len++;
  120. insertHexData(string, (uint8_t *)&currentParams->node_read_modbus_command->registerAddress, len, 2); // 插入modbus寄存器地址
  121. len += 2;
  122. insertHexData(string, &currentParams->node_read_modbus_command->decimalPoint, len, 1); // 插入小数点位数
  123. len++;
  124. insertHexData(string, &currentParams->node_read_modbus_command->bigLittleFormat, len, 1); // 插入大小端
  125. len++;
  126. break;
  127. case DLT645_07:
  128. insertHexData(string, (uint8_t *)protocol_dlt645_07, len, 1); // 插入dlt645_07数据长度
  129. len++;
  130. insertHexData(string, (uint8_t *)&currentParams->node_read_dlt645_command->deviceID645, len, 6); // 插入dlt645地址域
  131. len += 6;
  132. insertHexData(string, (uint8_t *)&currentParams->node_read_dlt645_command->Identification, len, 4);
  133. len += 4;
  134. break;
  135. case DLT645_97:
  136. insertHexData(string, (uint8_t *)protocol_dlt645_97, len, 1); // 插入dlt645_97数据长度
  137. len++;
  138. insertHexData(string, (uint8_t *)&currentParams->node_read_dlt645_command->deviceID645, len, 6); // 插入dlt645_97地址域
  139. len += 6;
  140. insertHexData(string, (uint8_t *)&currentParams->node_read_dlt645_command->Identification, len, 2); // 插入dlt645_97数据标识
  141. len += 2;
  142. default:
  143. break;
  144. }
  145. i++;
  146. currentParams = currentParams->nextParams;
  147. // 判断当前设备有没有属性可读了
  148. if (currentParams == NULL)
  149. {
  150. currentDevice = currentDevice->nextDevice;
  151. // 判断当前还有没有设备没有读取了
  152. if (currentDevice == NULL) // 且当前链表无后续设备了则跳出循环
  153. {
  154. deviceNum = 0; // 将结束位置全部归0
  155. paramsNum = 0;
  156. break;
  157. }
  158. currentParams = currentDevice->params; // 有则更新当前指针位置
  159. nowDeviceNum++;
  160. nowparamsNum = 0;
  161. }
  162. nowparamsNum++;
  163. } while (i == 20);
  164. // 更新结束的位置分为两种情况,一种还在当前设备的属性中轮询此时nowDeviceNum没有改变过,另外一种情况设备内的属性
  165. if (nowDeviceNum == 0)
  166. {
  167. deviceNum = startDeviceNum;
  168. paramsNum = startParamsNum + nowparamsNum;
  169. }
  170. else
  171. {
  172. deviceNum = startDeviceNum + nowDeviceNum;
  173. paramsNum = nowparamsNum;
  174. }
  175. *size = len;
  176. }
  177. /*
  178. *********************************************************************************************************
  179. * 函 数 名: void insertHexData(uint8_t *originalString,const uint8_t *hexData,int position)
  180. * 形 参:uint8_t *String需要插入的字符串,hexData插入的hex数据,insertIndex插入的下标位置,length插入的数据长度
  181. * 返 回 值: 无
  182. 注:插入的数据以被插入的字符串都可能包含0x00不要使用strlen
  183. *********************************************************************************************************
  184. */
  185. void insertHexData(uint8_t *String, const uint8_t *hexData, uint8_t insertIndex, uint8_t length)
  186. {
  187. memcpy(String + insertIndex, hexData, length);
  188. }
  189. /*
  190. *********************************************************************************************************
  191. * 函 数 名: uint8_t SlaveProtocolAnalysis(uint8_t *buff,uint16_t len)
  192. * 形 参:uint8_t *buff等待解析的字符串数据,
  193. * 返 回 值: 0:不是该节点的消息,数据没有进行任何处理。1:为该节点信息,接收到要进行的相应的切换工作
  194. 解析这段数据时要先判断是否为该节点的消息,stuct B *p=malloc(sizeof(struct B);
  195. *********************************************************************************************************
  196. */
  197. #ifdef slave
  198. #define LocalAddress 0x1F1A
  199. uint8_t SlaveProtocolAnalysis(uint8_t *buff, uint16_t len)
  200. {
  201. NODE_DEVICE_PARAMS *node_receive_params;
  202. node_receive_params = get_node_receive_params();
  203. uint16_t slaveAdress = buff[0] << 8 || buff[1];
  204. int protocol_location = 2; // 起始的协议所处位置
  205. uint8_t i=0;
  206. while (1)
  207. {
  208. if (slaveAdress == LocalAddress) // 判断此消息是否为该节点的消息,如果不是则跳出
  209. {
  210. switch (buff[protocol_location]) // 读取接收到的数据属于什么协议
  211. {
  212. case protocol_modbus_read:
  213. node_receive_params->params[i].protcol = MODBUS_READ;
  214. node_receive_params->params[i].dlt645_params=NULL;
  215. node_receive_params->params[i].modbus_read=malloc(sizeof(NODE_MODBUS_READ));
  216. node_receive_params->params[i].modbus_write=NULL;
  217. node_receive_params->params[i].modbus_read->functionCode=buff[protocol_location+1]; //读出functionCode
  218. node_receive_params->params[i].modbus_read->dataType=buff[protocol_location+2]; //读出数据格式
  219. node_receive_params->params[i].modbus_read->slaveAddress=buff[protocol_location+3]; //读出从站地址
  220. node_receive_params->params[i].modbus_read->registerAddress=buff[protocol_location+5]<<8||buff[protocol_location+4]; //读出寄存器地址
  221. node_receive_params->params[i].modbus_read->registerLength=buff[protocol_location+7]<<8||buff[protocol_location+6]; //读出要读的寄存器长度
  222. node_receive_params->params[i].modbus_read->precision=buff[protocol_location+8]; //读出小数点精度
  223. node_receive_params->params[i].modbus_read->bigLittleFormat=buff[protocol_location+9]; //读出数据大小端格式
  224. protocol_location += protocol_modbus_read;
  225. break;
  226. case protocol_dlt645_07:
  227. node_receive_params->params[i].protcol = DLT645_07;
  228. node_receive_params->params[i].dlt645_params=malloc(sizeof(NODE_DLT645_PARAMS));;
  229. node_receive_params->params[i].modbus_read=NULL;
  230. node_receive_params->params[i].modbus_write=NULL;
  231. memcpy(node_receive_params->params[i].dlt645_params->deviceType645,buff+protocol_location,6);
  232. memcpy((uint8_t *)&node_receive_params->params[i].dlt645_params->dataType645,buff+protocol_location+6,4);
  233. protocol_location += protocol_dlt645_07;
  234. break;
  235. case protocol_dlt645_97:
  236. node_receive_params->params[i].protcol = DLT645_97;
  237. node_receive_params->params[i].dlt645_params=malloc(sizeof(NODE_DLT645_PARAMS));;
  238. node_receive_params->params[i].modbus_read=NULL;
  239. node_receive_params->params[i].modbus_write=NULL;
  240. memcpy(node_receive_params->params[i].dlt645_params->deviceType645,buff+protocol_location,6);
  241. memcpy((uint8_t *)&node_receive_params->params[i].dlt645_params->dataType645,buff+protocol_location+6,2);
  242. protocol_location += protocol_dlt645_97;
  243. break;
  244. case 0:
  245. return 1;
  246. default:
  247. return 0;
  248. }
  249. }
  250. else
  251. {
  252. node_receive_params->Index=i;//记录本次有多少数据传输过来了
  253. return 0;
  254. }
  255. i++;
  256. if(protocol_location>len) //判断数据解析是否越界了,越界则跳转出
  257. {
  258. return 1;
  259. }
  260. }
  261. }
  262. #endif