ec800m.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #include "ec800m.h"
  2. #include "usart.h"
  3. #include "systick.h"
  4. #include "cJson.h"
  5. #include "string.h"
  6. #include "log.h"
  7. #include "systick.h"
  8. #include "main.h"
  9. void EC800MPwoerOn(void)
  10. {
  11. rcu_periph_clock_enable(RCU_GPIOD);
  12. gpio_init(GPIOD, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
  13. gpio_bit_set(GPIOD,GPIO_PIN_2);
  14. delay_1ms(5000);
  15. gd_pull_EC800M_pwr_up();
  16. gd_pull_EC800M_rst_down();
  17. delay_1ms(50);
  18. gd_pull_EC800M_pwr_down();
  19. delay_1ms(320);
  20. gd_pull_EC800M_rst_up();
  21. delay_1ms(800);
  22. gd_pull_EC800M_pwr_up();
  23. }
  24. void EC800MSendCmd(char *buf, uint16_t len)
  25. {
  26. uint16_t i;
  27. uint16_t data;
  28. for (i = 0; i < len; i++)
  29. {
  30. data = buf[i];
  31. usart_data_transmit(COM_EC800, data);
  32. while (RESET == usart_flag_get(COM_EC800, USART_FLAG_TBE))
  33. ;
  34. }
  35. }
  36. void EC800MWaitReady()
  37. {
  38. WaitResponse(RSP_READY, 0);
  39. }
  40. /*
  41. * 函数名:bool WaitResponse(char *expectStr, int timeout)
  42. * 输入参数:expectStr 需要匹配的关键字 timeout超时时间
  43. * 输出参数:true flase
  44. * 返回值:无
  45. * 函数作用:从UART0_RX_BUF缓冲区中匹配有无对应关键字有关键字则返回true无返回false
  46. */
  47. bool WaitResponse(char *expectStr, int timeout)
  48. {
  49. bool timeoutFlag = false;
  50. if (timeout >= 0)
  51. {
  52. timeoutFlag = true;
  53. }
  54. // gd_485_send((char *)&UART0_RX_BUF, strlen(UART0_RX_BUF)); 不清楚此处调用485意义
  55. while (1)
  56. {
  57. delay_1ms(50);
  58. if (UART0_RX_STAT > 0)
  59. {
  60. UART0_RX_STAT = 0;
  61. char *p = strstr((char *)&UART0_RX_BUF, expectStr);
  62. if (p)
  63. {
  64. Clear_DMA_Buffer();
  65. return true;
  66. }
  67. }
  68. timeout -= 50;
  69. if (timeoutFlag == true && timeout <= 0)
  70. {
  71. Clear_DMA_Buffer();
  72. return false;
  73. }
  74. };
  75. }
  76. /*
  77. * 函数名:void EC800MSetPDP()
  78. * 输入参数:无
  79. * 输出参数:无
  80. * 返回值:无
  81. * 函数作用:设置对应运营商和激活ip
  82. */
  83. void EC800MSetPDP()
  84. {
  85. delay_1ms(200);
  86. EC800MSendCmd(CMD_SET_PDP, strlen(CMD_SET_PDP));
  87. WaitResponse(RSP_OK, 1000);
  88. delay_1ms(200);
  89. EC800MSendCmd(CMD_SET_ACTIVE, strlen(CMD_SET_ACTIVE));
  90. WaitResponse(RSP_OK, 1000);
  91. delay_1ms(200);
  92. }
  93. #define AT_Open "AT+QFOPEN=\"http.txt\",2 \r\n"
  94. #define AT_SEEK "AT+QFSEEK=1,0,0\r\n"
  95. #define AT_128SEEK "AT+QFSEEK=1,128,0\r\n"
  96. #define AT_128Read "AT+QFREAD=1,128\r\n"
  97. #define AT_LIST "AT+QFLST=*\r\n"
  98. #define AT_QFLDS "AT+QFLDS=\"UFS\"\r\n"
  99. //分包宏
  100. /*
  101. * 函数名:bool EC800MGetUrl(char *url)
  102. * 输入参数:url 网址信息
  103. * 输出参数:无
  104. * 返回值:无
  105. * 函数作用:从对应的http获取信息
  106. */
  107. bool EC800MGetUrl(char *url,char *dmaBuffer,uint32_t bufferSize)
  108. {
  109. // Set url
  110. char command[100];
  111. sprintf(command, CMD_SET_URL, strlen(url)); // CMD_SET_URL "%d\r\n"
  112. EC800MSendCmd(command, strlen(command)); // 设置服务器URL 响应若参数格式正确,且不发送 HTTP(S) GET/POST 请求:CONNECT
  113. WaitResponse(RSP_CONNECT, 100);
  114. delay_1ms(200);
  115. EC800MSendCmd(url, strlen(url)); // 输入URL
  116. if (WaitResponse(RSP_OK, 5000) == false)
  117. return false;
  118. // Send get request
  119. delay_1ms(200);
  120. EC800MSendCmd(CMD_GET, strlen(CMD_GET)); // 向服务器发送get请求
  121. if (WaitResponse("QHTTPGET:", 5000) == false)
  122. return false;
  123. // read to UFS
  124. delay_1ms(200);
  125. EC800MSendCmd(CMD_GET_TO_FILE, strlen(CMD_GET_TO_FILE)); //"AT+QHTTPREADFILE=\"UFS:http.txt\",80\r\n"
  126. if (WaitResponse("QHTTPREADFILE:", 5000) == false)
  127. return false;
  128. // get data from UFS
  129. delay_1ms(1000);
  130. dma_config_change(dmaBuffer,bufferSize);
  131. delay_1ms(1000);
  132. EC800MSendCmd(CMD_READ_FILE, strlen(CMD_READ_FILE)); //"AT+QFDWL=http.txt\r\n"
  133. delay_1ms(6000);
  134. return true;
  135. }
  136. /*
  137. * 函数名:void ConnectMQTTSever(uint8_t *host, uint16_t port, uint8_t keepalive, uint8_t *clientid)
  138. * 输入参数:host:mqtt服务器IP port:mqtt端口,keepalive mqtt心跳时间,clientid设备id
  139. * 输出参数:无
  140. * 返回值:无
  141. * 函数作用:与服务器建立连接
  142. */
  143. uint32_t try_connect; //记录尝试与平台建立连接的次数,每次1s当计数到1小时后重启设备
  144. void ConnectMQTTSever(uint8_t *host, uint16_t port, uint8_t keepalive, uint8_t *clientid,uint8_t *mqttUserName,uint8_t *mqttPassword)
  145. {
  146. char cmd[150];
  147. bool success = false;
  148. try_connect=0;
  149. // 主动断开连接
  150. EC800MSendCmd(CMD_MQTT_DISCONNECT, 0);
  151. // 设置mqtt版本
  152. EC800MSendCmd(CMD_MQTT_VERSION, strlen(CMD_MQTT_VERSION));
  153. WaitResponse(RSP_OK, 100);
  154. sprintf(cmd, "AT+QMTCFG=\"qmtping\",0,%d\r\n", keepalive);
  155. EC800MSendCmd(cmd, strlen(cmd));
  156. WaitResponse(RSP_OK, 0);
  157. // EC800MSendCmd(CMD_MQTT_DISCONNECT, 0);
  158. sprintf(cmd, "AT+QMTOPEN=0,\"%s\",%d\r\n", host, port);
  159. do
  160. {
  161. EC800MSendCmd(cmd, strlen(cmd));
  162. success = WaitResponse("QMTOPEN: 0,0", 1000);
  163. delay_1ms(1000);
  164. task_fwdgt_reload();
  165. try_connect++;
  166. if(try_connect==60*60){NVIC_SystemReset();}
  167. } while (!success);
  168. if (success)
  169. {
  170. if(mqttUserName==NULL)
  171. {
  172. sprintf(cmd, "AT+QMTCONN=0,\"%s\",\"%s\",\"%s\"\r\n", clientid, "", ""); // 后两个为username password
  173. }
  174. else
  175. {
  176. sprintf(cmd, "AT+QMTCONN=0,\"%s\",\"%s\",\"%s\"\r\n", clientid, mqttUserName, mqttPassword); // 后两个为username password
  177. }
  178. do
  179. {
  180. EC800MSendCmd(cmd, strlen(cmd));
  181. success = WaitResponse("QMTCONN: 0,0,0", 1000);
  182. delay_1ms(1000);
  183. task_fwdgt_reload();
  184. try_connect++;
  185. if(try_connect==60*60){NVIC_SystemReset();}
  186. } while (!success);
  187. }
  188. }
  189. /*
  190. * 函数名:void MQTTPublish(CONFIG_PARAMS *gateway)
  191. * 输入参数:CONFIG_PARAMS *gateway 网关内存储信息
  192. * 输出参数:无
  193. * 返回值:无
  194. * 函数作用:读出采集到的数据进行上报,若未采集到数据则不进行任何处理 23/4/4添加testId测试丢包情况7/18日重写此方法
  195. */
  196. void MQTTPublish(void)
  197. {
  198. GATEWAY_PARAMS *gateway;
  199. gateway=get_gateway_config_params();
  200. char *payload_out=malloc(25*1024); //要发送的字符串
  201. char mqtt_publish[200]; //发送字符串的指令
  202. sprintf((char *)payload_out,"{\"deviceId\":\"%s\",\"data\":[",gateway->deviceId);//组成json头部
  203. DEVICE_PARAMS *currentDevice=gateway->device_params;
  204. READ_MODBUS_COMMAND *read_modbus_command=NULL;
  205. READ_DLT645_COMMAND *read_dlt645_command=NULL;
  206. switch(currentDevice->protocol)
  207. {
  208. case DLT645_07:
  209. case DLT645_97:
  210. read_dlt645_command=currentDevice->params->node_read_dlt645_command;
  211. break;
  212. case MODBUS:
  213. read_modbus_command=currentDevice->params->node_read_modbus_command;
  214. break;
  215. }
  216. while(1)
  217. {
  218. __START__WHILE:
  219. switch(currentDevice->protocol)
  220. {
  221. case DLT645_07:
  222. case DLT645_97:
  223. if(read_dlt645_command->rxLen!=0)
  224. {
  225. float value;
  226. switch(read_dlt645_command->rxLen)
  227. {
  228. case 4:
  229. memcpy(&value, read_dlt645_command->data, 4);
  230. sprintf(payload_out+strlen(payload_out),"{\"deviceId\":\"%s\",\"%s\": %.2f},",currentDevice->deviceID,read_dlt645_command->keyword,value);
  231. break;
  232. case 5:
  233. sprintf(payload_out+strlen(payload_out),"{\"deviceId\":\"%s\",\"%s\": \"%02X%02X%02X%02X%02X\"},",currentDevice->deviceID,read_dlt645_command->keyword,read_dlt645_command->data[4],
  234. read_dlt645_command->data[3],read_dlt645_command->data[2],read_dlt645_command->data[1],read_dlt645_command->data[0]);
  235. break;
  236. break;
  237. case 9:
  238. memcpy(&value, read_dlt645_command->data, 4);
  239. sprintf(payload_out+strlen(payload_out),"{\"deviceId\":\"%s\",\"%s\":\"%02X%02X%02X%02X%02X%.2f\"},",currentDevice->deviceID,read_dlt645_command->keyword,read_dlt645_command->data[8],
  240. read_dlt645_command->data[7],read_dlt645_command->data[6],read_dlt645_command->data[5],read_dlt645_command->data[4],value);
  241. break;
  242. }
  243. }
  244. break;
  245. case MODBUS:
  246. {
  247. if(read_modbus_command->rxLen!=0)
  248. {
  249. if(read_modbus_command->functionCode==0x03)
  250. {
  251. if(read_modbus_command->decimalPoint!=0)
  252. {
  253. float value;
  254. memcpy(&value, read_modbus_command->value, 4); // 取出相应的值给value
  255. sprintf(payload_out+strlen(payload_out),"{\"deviceId\":\"%s\",\"%s\": %.2f},",currentDevice->deviceID,read_modbus_command->keyword,value);
  256. }
  257. else
  258. {
  259. uint32_t value;
  260. memcpy(&value, read_modbus_command->value, 4);
  261. sprintf(payload_out+strlen(payload_out),"{\"deviceId\":\"%s\",\"%s\": %d},",currentDevice->deviceID,read_modbus_command->keyword,value);
  262. }
  263. }
  264. else if(read_modbus_command->functionCode==0x01)
  265. {
  266. uint8_t value[4];
  267. uint8_t state;
  268. memcpy(&value, read_modbus_command->value, 4);
  269. if (value[2] == 0xFF)
  270. {
  271. state = 1;
  272. }
  273. else
  274. {
  275. state = 0;
  276. }
  277. sprintf(payload_out+strlen(payload_out),"{\"deviceId\":\"%s\",\"%s\": %d},",currentDevice->deviceID,read_modbus_command->keyword,state);
  278. }
  279. }
  280. }
  281. break;
  282. }
  283. switch(currentDevice->protocol)
  284. {
  285. case DLT645_07:
  286. case DLT645_97:
  287. read_dlt645_command=read_dlt645_command->nextParams;
  288. break;
  289. case MODBUS:
  290. read_modbus_command=read_modbus_command->nextParams;
  291. break;
  292. }
  293. if(read_dlt645_command==NULL&&read_modbus_command==NULL)
  294. {
  295. currentDevice=currentDevice->nextDevice;
  296. if(currentDevice==NULL)
  297. {
  298. goto __END__WHILE;
  299. }
  300. else
  301. {
  302. read_dlt645_command=currentDevice->params->node_read_dlt645_command;
  303. read_modbus_command=currentDevice->params->node_read_modbus_command;
  304. }
  305. }
  306. goto __START__WHILE;
  307. }
  308. __END__WHILE:
  309. if(strlen(payload_out)>40)//小于这个值组成的字符串证明没有数据采集到、就不进行发布
  310. {
  311. sprintf(payload_out+strlen(payload_out)-1,"]}\0");
  312. sprintf((char *)mqtt_publish, "AT+QMTPUBEX=0,0,0,0,\"%s\",%d\r\n", gateway->messageTopic, strlen(payload_out));
  313. EC800MSendCmd(mqtt_publish, strlen(mqtt_publish));
  314. WaitResponse("QMTPUBEX", 1000);
  315. delay_1ms(50);
  316. EC800MSendCmd(payload_out, strlen(payload_out));
  317. }
  318. free(payload_out);
  319. payload_out=NULL;
  320. }
  321. /*
  322. * 函数名:void MQTTSubTopic(uint8_t *commandTopic)
  323. * 输入参数:uint8_t *commandTopic 订阅的主题
  324. * 输出参数:无
  325. * 返回值:无
  326. * 函数作用:读出采集到的数据进行上报,若未采集到数据则不进行任何处理
  327. */
  328. void MQTTSubTopic(uint8_t *commandTopic)
  329. {
  330. char AT_SUB[100];
  331. sprintf(AT_SUB, "AT+QMTSUB=0,1,\"%s\",0\r\n", commandTopic);
  332. bool success = false;
  333. uint8_t retry_count = 0;
  334. do
  335. {
  336. EC800MSendCmd(AT_SUB, strlen(AT_SUB));
  337. success = WaitResponse(RSP_OK, 1000);
  338. retry_count++;
  339. } while (!success && retry_count < 3);
  340. }