wcs.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*******************************************************************************************
  2. * @file wcs.c
  3. *
  4. * @brief wcs协议解析
  5. *
  6. * (c) Copyright 2021, Shandong Huali electromechanical Co., Ltd..
  7. * This is protected by international copyright laws. Knowledge of the
  8. * source code may not be used to write a similar product. This file may
  9. * only be used in accordance with a license and should not be redistributed
  10. * in any way. We appreciate your understanding and fairness.
  11. *
  12. *
  13. * @author Simon
  14. * @date Created: 2021.06.16-T18:02:42+0800
  15. *
  16. *******************************************************************************************/
  17. #include "rtthread.h"
  18. #include "board.h"
  19. #include "lwip/netdb.h"
  20. #include "wcs.h"
  21. #define DBG_TAG "wcs"
  22. #define DBG_LVL DBG_INFO
  23. #include <rtdbg.h>
  24. enum
  25. {
  26. DEV_TYPE_NONE,
  27. DEV_TYPE_SHUTTLE,
  28. DEV_TYPE_PALLET,
  29. DEV_TYPE_OTHER,
  30. };
  31. typedef struct
  32. {
  33. uint16_t tag;
  34. uint16_t msg_len;
  35. uint8_t dev_type;
  36. uint8_t dev_no;
  37. uint8_t mode;
  38. uint8_t map_ver;
  39. uint8_t task_no;
  40. uint8_t task_type;
  41. }wcs_frame_head_t;
  42. typedef struct
  43. {
  44. uint16_t msg_len;
  45. uint16_t crc;
  46. uint16_t tag;
  47. }wcs_frame_tail_t;
  48. typedef struct __attribute__((__packed__))
  49. {
  50. uint8_t seg_no;
  51. wcs_point_t point[1];
  52. }wcs_seg_t;
  53. typedef struct __attribute__((__packed__))
  54. {
  55. uint8_t seg_no;
  56. uint8_t cmd_no;
  57. uint8_t cmd;
  58. uint32_t cmd_param;
  59. uint8_t area_no;
  60. uint16_t auth;
  61. }wcs_cmd_req_t;
  62. typedef struct __attribute__((__packed__))
  63. {
  64. uint8_t x;
  65. uint8_t y;
  66. uint8_t z;
  67. // uint8_t action;
  68. }wcs_location_t;
  69. typedef struct __attribute__((__packed__))
  70. {
  71. uint8_t task_result;
  72. uint8_t cmd_no;
  73. uint8_t cmd_exe_result;
  74. uint32_t cmd_exe_param;
  75. wcs_location_t location;
  76. uint8_t seg_no;
  77. uint16_t seg_target;
  78. uint32_t barcode;
  79. uint8_t car_status;
  80. uint8_t pallet_status;
  81. uint8_t reserve_status;
  82. uint8_t dir;
  83. uint8_t vol;
  84. uint8_t warning;
  85. uint8_t res[3];
  86. }wcs_ack_t;
  87. const static uint16_t wcs_polynom = 0xA001;
  88. static uint8_t wcs_clear_ack = 0;
  89. void ll_get_point(wcs_point_t *point);
  90. uint8_t ll_get_seg(void);
  91. uint16_t ll_get_target(void);
  92. uint8_t ll_get_car_status(void);
  93. uint8_t ll_get_dtc(void);
  94. uint8_t ll_get_pallet(void);
  95. uint8_t ll_get_battery(void);
  96. uint8_t ll_get_reserve(void);
  97. uint8_t ll_get_dir(void);
  98. int cmd_work_result(uint8_t *cmd_no);
  99. int cmd_parser(uint8_t cmd_no, uint8_t cmd, uint32_t *param);
  100. void cmd_set_clear_indication(void (*clear_func)(void));
  101. int sch_trajectory(uint8_t task_id, uint8_t seg_no, wcs_point_t *point);
  102. int sch_target(uint8_t task_id, uint8_t seg_no);
  103. int sch_get_status(void);
  104. void be_send(void *buf, int sz);
  105. static uint16_t wcs_crc16(uint8_t *ptr, uint16_t len)
  106. {
  107. uint8_t i;
  108. uint16_t crc = 0xffff;
  109. if (len == 0) {
  110. len = 1;
  111. }
  112. while (len--) {
  113. crc ^= *ptr;
  114. for (i = 0; i<8; i++)
  115. {
  116. if (crc & 1) {
  117. crc >>= 1;
  118. crc ^= wcs_polynom;
  119. }
  120. else {
  121. crc >>= 1;
  122. }
  123. }
  124. ptr++;
  125. }
  126. return(crc);
  127. }
  128. static __inline wcs_frame_tail_t *wcs_get_tail(void *buf, int sz)
  129. {
  130. uint8_t *pbuf = buf;
  131. return (wcs_frame_tail_t *)&pbuf[sz - sizeof(wcs_frame_tail_t)];
  132. }
  133. static __inline uint8_t *wcs_get_body(void *buf, int sz)
  134. {
  135. uint8_t *pbuf = buf;
  136. return &pbuf[sizeof(wcs_frame_head_t)];
  137. }
  138. static void wcs_ack_status(wcs_ack_t *pack)
  139. {
  140. ll_get_point((wcs_point_t *)&pack->location);
  141. pack->seg_no = ll_get_seg();
  142. pack->seg_target = htons(ll_get_target());
  143. pack->car_status = ll_get_car_status();
  144. pack->warning = ll_get_dtc();
  145. pack->pallet_status = ll_get_pallet();
  146. pack->reserve_status = ll_get_reserve();
  147. pack->dir = ll_get_dir();
  148. pack->vol = ll_get_battery();
  149. // LOG_D("ack");
  150. }
  151. static void wcs_ack_clear(void)
  152. {
  153. wcs_clear_ack = 1;
  154. }
  155. static void wcs_ack(uint8_t result, wcs_frame_head_t *head, wcs_cmd_req_t *cmd)
  156. {
  157. static uint8_t buf[sizeof(wcs_ack_t) + sizeof(wcs_frame_head_t) + sizeof(wcs_frame_tail_t)] = {0};
  158. wcs_frame_tail_t *ptail = wcs_get_tail(buf, sizeof(buf));
  159. wcs_ack_t *pack = (wcs_ack_t *)wcs_get_body(buf, sizeof(buf));
  160. wcs_frame_head_t *phead = (wcs_frame_head_t *)buf;
  161. if(wcs_clear_ack)
  162. {
  163. wcs_clear_ack = 0;
  164. memset(buf, 0, sizeof(buf));
  165. }
  166. /* 填充发送信息 */
  167. phead->tag = htons(0x02fd);
  168. phead->msg_len = htons(sizeof(buf));
  169. phead->map_ver = 0;
  170. if((cmd && cmd->cmd_no) || head->task_no)
  171. {
  172. memcpy(&phead->dev_type, &head->dev_type, sizeof(wcs_frame_head_t) - 4);
  173. }
  174. if(head->task_no)
  175. {
  176. phead->task_type = head->task_type;
  177. pack->task_result = result;
  178. pack->cmd_no = 0;
  179. pack->cmd_exe_result = 0;
  180. pack->cmd_exe_param = 0;
  181. }
  182. else if(cmd)
  183. {
  184. pack->task_result = 0;
  185. pack->cmd_no = cmd->cmd_no;
  186. pack->cmd_exe_result = result;
  187. pack->cmd_exe_param = cmd->cmd_param; /* 延时指令不会返回参数 */
  188. }
  189. /* 任务执行完毕 */
  190. else if(phead->task_no && phead->task_type == 2)
  191. {
  192. if(ll_get_car_status() == 3)
  193. {
  194. pack->task_result = 0;
  195. }
  196. }
  197. else
  198. {
  199. int rc;
  200. uint8_t cmd_exe_no = 0;
  201. rc = cmd_work_result(&cmd_exe_no);
  202. if(rc >= 0)
  203. {
  204. pack->cmd_no = cmd_exe_no;
  205. pack->cmd_exe_result = rc;
  206. }
  207. }
  208. wcs_ack_status(pack);
  209. ptail->tag = htons(0x03fc);
  210. ptail->msg_len = htons(sizeof(buf));
  211. ptail->crc = wcs_crc16(buf, sizeof(buf) -4);
  212. be_send(buf, sizeof(buf));
  213. if((cmd && cmd->cmd_no) || head->task_no)
  214. LOG_HEX(DBG_TAG, 16, buf, sizeof(buf));
  215. }
  216. /****************************************
  217. * wcs帧解析
  218. *函数功能 :
  219. *参数描述 : 无
  220. *返回值 : 无
  221. ****************************************/
  222. static int wcs_frame_parser(void *buf, int sz)
  223. {
  224. wcs_frame_head_t *phead = (wcs_frame_head_t *)buf;
  225. wcs_frame_tail_t *ptail = wcs_get_tail(buf, sz);
  226. int rc = 0;
  227. if(phead->msg_len == ptail->msg_len && ntohs(phead->msg_len) == sz) /* 长度一致 */
  228. {
  229. // LOG_D("recv frame");
  230. uint16_t cal_crc = wcs_crc16(buf, sz -4);
  231. if(ptail->crc == cal_crc) /* 校验通过 */
  232. {
  233. // LOG_D("check ok");
  234. if(phead->dev_type == DEV_TYPE_SHUTTLE) /* 对象四向车 */
  235. {
  236. if(phead->task_no) /* 任务编号 */
  237. {
  238. LOG_I("task id[%u]", phead->task_no);
  239. LOG_HEX(DBG_TAG, 16, buf, sz);
  240. if(phead->task_type == 1) /* 任务类型 */
  241. {
  242. if(ll_get_car_status() != 3)
  243. {
  244. rc = 0;
  245. }
  246. else //就绪,就获取身体信息
  247. {
  248. uint8_t seg_cnt;
  249. wcs_seg_t *ptask = (wcs_seg_t *)wcs_get_body(buf, sz);
  250. //LOG_I("add trajectory");
  251. seg_cnt = (sz - sizeof(wcs_frame_head_t) - sizeof(wcs_cmd_req_t) - sizeof(wcs_frame_tail_t)) / sizeof(wcs_point_t);
  252. rc = sch_trajectory(phead->task_no, seg_cnt, ptask->point);
  253. }
  254. wcs_ack(rc? rc: 1, phead, NULL); /* 回应信息 */
  255. }
  256. else if(phead->task_type == 2) //任务类型:1:路径中各段节点; 2:RES能行驶的分段动作序号
  257. {
  258. if(ll_get_car_status() != 11) //11:节点待命
  259. {
  260. rc = 0;
  261. }
  262. else
  263. {
  264. wcs_seg_t *ptask = (wcs_seg_t *)wcs_get_body(buf, sz);
  265. LOG_I("schedule task");
  266. if(cmd_work_result(NULL) < 0)
  267. {
  268. rc = sch_target(phead->task_no, ptask->seg_no);
  269. }
  270. else
  271. {
  272. rc = ERR_C_RES_TASK_DOING;
  273. }
  274. }
  275. wcs_ack(rc? rc: 1, phead, NULL);
  276. }
  277. }
  278. else
  279. {
  280. wcs_cmd_req_t *pcmd = (wcs_cmd_req_t *)wcs_get_body(buf, sz);
  281. if(pcmd->cmd_no || pcmd->cmd)
  282. {
  283. LOG_I("commands[%#x]", pcmd->cmd);
  284. LOG_HEX(DBG_TAG, 16, buf, sz);
  285. rc = cmd_parser(pcmd->cmd_no, pcmd->cmd, (uint32_t *)&pcmd->cmd_param);
  286. wcs_ack(rc, phead, pcmd);
  287. }
  288. else
  289. wcs_ack(rc, phead, NULL);
  290. }
  291. }
  292. }
  293. }
  294. return 0;
  295. }
  296. static int wcs_init(void)
  297. {
  298. extern void be_set_parser(int (*parser_fun)(void *, int));
  299. be_set_parser(wcs_frame_parser);
  300. cmd_set_clear_indication(wcs_ack_clear);
  301. return 0;
  302. }
  303. INIT_APP_EXPORT(wcs_init);