at_module.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /********************************************************************************
  2. * @file AT_Module.c
  3. * @author 度云未来 DOIOT
  4. * @brief 针对公司模块AT指令的处理库
  5. ******************************************************************************
  6. * @attention
  7. * <h2><center>&copy; Copyright (c) 2019 成都度云未来
  8. * All rights reserved.</center></h2>
  9. * 注意:本程序针对cubemx 生成的hal库程序快速开发
  10. * 环境:keil5.0
  11. * STM32Cube FW_F1 V1.8.0
  12. * 文件版本:1.3 更新时间2020/10/15 降低了文件之间的耦合度
  13. ********************************************************************************/
  14. #include "includes.h"
  15. #include "trace.h"
  16. #include "at_module.h"
  17. #include "stdarg.h"
  18. #include "string.h"
  19. #include "stdio.h"
  20. #include "stdlib.h"
  21. #include "../net_proc.h"
  22. uint8_t AT_CMD_SEND(AT_CMD task);
  23. extern int uart_blocking_read(char *buffer, u8 uartid, u32 timeout);
  24. char at_rxbuff[1024];
  25. extern system_network_t sys_net;
  26. int Module_Blocking_Read(char *buffer, u32 timeout)
  27. {
  28. int ret = 0;
  29. // char *str1;
  30. // char *msg = NULL;
  31. // int len = 0;
  32. ret = uart_blocking_read(buffer, UART_ME3616, timeout);
  33. // if(strstr(buffer,"+MSUB:")){
  34. // str1 = strstr(buffer,"byte");
  35. // if(str1){
  36. // len = atoi(str1-3);
  37. // memset(sys_net.str, 0, sizeof(sys_net.str));
  38. // msg = (char *)net_queue_mem_calloc_must();
  39. // if(msg) {
  40. // memcpy(msg, str1+5, len);
  41. // // data_dump("NET RECB", (char*)msg, len);
  42. // net_queue_insert((char *)msg, len); //将数据放到消息队列中
  43. // }
  44. // else
  45. // {
  46. // net_queue_mem_free(msg);
  47. // }
  48. // }
  49. // }
  50. return ret;
  51. }
  52. uint8_t AT_TASK_START(AT_CMD task[],uint8_t Size)
  53. {
  54. uint32_t i;
  55. for(i=0;i<Size;i++)
  56. {
  57. AT_INFO("Start Task %d",i+1);
  58. if(AT_CMD_SEND(task[i]))
  59. {
  60. /*校验成功,开始延时*/
  61. HAL_Delay(task[i].delay_time);
  62. }
  63. else
  64. {
  65. /*校验失败,开始处理*/
  66. if(task[i].REF_Count!=0)
  67. {
  68. task[i].REF_Count--;
  69. i--;/*下一次迭代会回到这个地方*/
  70. AT_INFO("开始重发");
  71. }
  72. else/*没有重发次数或者次数已尽*/
  73. {
  74. /*装载跳跃位置*/
  75. if(task[i].jump!=0)
  76. {
  77. i=task[i].jump-2;
  78. AT_INFO("开始跳转");
  79. }
  80. }
  81. }
  82. }
  83. return 1;
  84. }
  85. uint8_t AT_CMD_SEND(AT_CMD task)
  86. {
  87. uint8_t i=0;
  88. rxbuff(buff);
  89. /*先执行前调函数*/
  90. if(task.BeforeCpltCallback!=NULL)
  91. {
  92. task.BeforeCpltCallback();
  93. }
  94. module_printf("%s", task.SEND_CMD);
  95. AT_INFO("SEND:%s",task.SEND_CMD);
  96. for(i=0;i<task.crc_size;i++)
  97. {
  98. Module_Blocking_Read(buff,task.timeout);
  99. AT_INFO("ASK:%s",buff);
  100. if(strstr(buff,task.ASK[i]))
  101. {
  102. }else
  103. {
  104. AT_ERROR("%s",buff);
  105. /*校验失败,执行失败回掉*/
  106. if(task.ErrorCpltCallback!=NULL)
  107. {
  108. task.ErrorCpltCallback(buff);
  109. }
  110. return 0;
  111. }
  112. }
  113. /*校验成功,执行完成回调函数*/
  114. if(task.AfterCpltCallback!=NULL)
  115. {
  116. task.AfterCpltCallback(buff);
  117. }
  118. return 1;
  119. }
  120. /**
  121. * @param sned_cmd : 发送的指令
  122. * @param cmd_arry : 要校验的响应数组
  123. * @param ack_str: 响应的校验的字串
  124. * @param overtime : 校验的数量【如果响应组是3,校验是2,则会读取三次,但只校验到第2组】
  125. */
  126. uint8_t Module_SEND_CRC(char* send_cmd,char *ack_str,uint32_t overtime)
  127. {
  128. //char rxbuf[cmd_length];
  129. module_printf("%s", send_cmd);
  130. if(Module_Read_A_CRC(ack_str,overtime)) return 1;//校验成功;
  131. else return 0;/*阻塞的读取一次响应,超时返回失败*/
  132. }
  133. /**
  134. * @param sned_cmd : 发送的指令
  135. * @param cmd_arry : 要校验的响应数组
  136. * @param arry_size: 响应的校验组数量
  137. * @param crc_size : 校验的数量【如果响应组是3,校验是2,则会读取三次,但只校验到第2组】
  138. */
  139. uint8_t Module_SEND_A_CRC(char* send_cmd,char cmd_arry[][cmd_length],uint8_t arry_size,uint8_t crc_size)
  140. {
  141. char rxbuf[cmd_length];
  142. uint8_t i;
  143. module_printf("%s", send_cmd);
  144. for(i=0;i<arry_size;i++) /*读取完指定次数*/
  145. {
  146. if(Module_Blocking_Read(rxbuf,1000)); /*阻塞的读取一次响应,超时返回失败*/
  147. else return 0;
  148. if(i<crc_size) /*校验指定的次数*/
  149. {
  150. if(strstr(rxbuf,cmd_arry[i]))
  151. {
  152. }else goto cmd_fail;
  153. }
  154. }
  155. return 1;//校验成功
  156. cmd_fail:
  157. {
  158. /*自写错误处理*/
  159. }
  160. return 0;
  161. }
  162. /**
  163. * @param 阻塞读取一次数据并校验
  164. * @param cmd_arry : 要校验的响应数组
  165. * @param overtime : 超时时间
  166. */
  167. uint8_t Module_Read_A_CRC(char cmd_arry[],uint32_t overtime)
  168. {
  169. //rxbuff(at_rxbuff);
  170. memset(at_rxbuff, 0, sizeof(at_rxbuff));
  171. if(Module_Blocking_Read(at_rxbuff,overtime)) /*阻塞的读取一次响应,超时返回失败*/
  172. {
  173. // printf("%s\r\n", at_rxbuff);
  174. if(strstr(at_rxbuff,cmd_arry))
  175. return 1;
  176. else
  177. {
  178. return 0;
  179. }
  180. }
  181. else return 0;
  182. }
  183. uint8_t Module_Read_A_CRC_DA(char cmd_arry[],char head_arry[], uint32_t len, uint32_t overtime)
  184. {
  185. //rxbuff(at_rxbuff);
  186. memset(at_rxbuff, 0, sizeof(at_rxbuff));
  187. if(Module_Blocking_Read(at_rxbuff,overtime)) /*阻塞的读取一次响应,超时返回失败*/
  188. {
  189. // if(strstr(at_rxbuff,head_arry)){
  190. // if(strstr(at_rxbuff+len,cmd_arry)) return 1;
  191. // else return 0;
  192. // }
  193. // else {
  194. if(strstr(at_rxbuff+len,cmd_arry))
  195. return 1;
  196. else
  197. {
  198. return 0;
  199. }
  200. // }
  201. }
  202. else return 0;
  203. }
  204. /**@brief AT_CMD_Polling:按指定的指令轮询直到响应对应的ACK才返回
  205. * @param send_cmd : 需要轮询的指令
  206. * @param Polling_fre : 轮询间隔
  207. * @param overtime : 超时时间
  208. */
  209. uint8_t AT_CMD_Polling(char *send_cmd,char*ack,uint32_t Polling_delay,uint32_t overtime)
  210. {
  211. uint32_t time_count=0;
  212. while(1)
  213. {
  214. if(time_count%Polling_delay==0)
  215. {
  216. module_printf("%s", send_cmd);
  217. if(Module_Read_A_CRC(ack,100)) return 1;
  218. }
  219. time_count++;
  220. HAL_Delay(1);
  221. if(time_count>overtime) return 0;
  222. }
  223. }
  224. /**@brief AT_GET_data:提取字符串中第Number_of_groups组被特定字符包裹的信息,标志必须是成对闭合的
  225. * @param buff : 待提取的字符串,可以是数组或静态字符串
  226. * @param get_data : 提取后装载的数组,必须是数组,不能是静态字符串因为需要写
  227. * @param sign : 包裹符号,是一个字符
  228. * @param Number_of_groups : 提取的是第几组
  229. * 例:字符串 "AT+MIPOPEN=1,"TCP","122.114.122.174",41838,100,0,1,2,11002"
  230. * 参数Number_of_groups=2提取第二组,装载结果get_data: 122.114.122.174
  231. */
  232. uint8_t AT_GET_Data(char * buff,uint8_t get_data[],char*sign,uint8_t Number_of_groups)
  233. {
  234. uint16_t i=0,count=0;
  235. while(buff[i]!='\0') /*获取分隔符整数*/
  236. {
  237. if(buff[i]==sign[0]) count++;
  238. i++;
  239. }
  240. if(count%2==0&&count>=Number_of_groups*2) /*偶数分隔符数才继续进行*/
  241. {
  242. char chBuffer[512] ; /*按需调整*/
  243. char *pchDilem =sign; /*分隔符*/
  244. char *pchStrTmpIn = NULL; /*剩下的缓存*/
  245. char *pchTmp = NULL; /*提取出的字符*/
  246. i=0;
  247. strcpy(chBuffer,buff);
  248. pchTmp = chBuffer;
  249. while(NULL != ( pchTmp = strtok_r( pchTmp, pchDilem, &pchStrTmpIn) ))
  250. {
  251. // uart1_printf("\n pchTmp[%s] \n",pchTmp);
  252. i++;
  253. if(i==Number_of_groups*2) strcpy((char*)get_data,pchTmp);
  254. pchTmp = NULL;
  255. }
  256. return 1;
  257. }
  258. else return 0; /*非偶数分隔符直接结束*/
  259. }
  260. /**@brief AT_GET_Data_2Param :提取被头尾字符串包裹的字串
  261. * @param buff : 待提取的字符串,可以是数组或静态字符串
  262. * @param get_data : 提取后装载的数组,必须是数组,不能是静态字符串因为需要写
  263. * @param head : 头字符串【任意长度符串】
  264. * @param tail : 尾字符串【任意长度字符串】
  265. * 例:字符串 "+QGPSGNMEA: $GPRMC,021229.00,A,3041.560083,N,10405.832869,E,0.0,247.3,040920,1.9,W,A*28"
  266. * 参数head ",A",tail ",N",装载结果get_data: "3041.560083"
  267. */
  268. uint8_t AT_GET_Data_2Param(char * buff,uint8_t get_data[],char*head,char*tail)
  269. {
  270. if(strstr(buff,head)&&strstr(buff,tail))
  271. {
  272. uint16_t i;
  273. uint16_t len1,len2;
  274. char *t = NULL;
  275. char *h=strstr(buff,head);
  276. len1=strlen(h); /*剩余长度*/
  277. len2=strlen(head); /*头子串长度*/
  278. t=strstr(h+len2,tail);
  279. if(len1>len2)
  280. {
  281. for(i=0;h+i+len2!=t;i++)
  282. {
  283. get_data[i]=h[i+len2];
  284. }
  285. get_data[i]='\0';//加上结束符
  286. }else
  287. {
  288. debug_printf("\r\n字串长度错误\r\n");
  289. return 0;
  290. }
  291. }else
  292. {
  293. if(!strstr(buff,head))debug_printf("\r\n未能检索到头字串\r\n");
  294. if(!strstr(buff,tail))debug_printf("\r\n未能检索到尾字串\r\n");
  295. debug_printf("\r\n请检查你的数据原文:\r\n");
  296. debug_printf("%s", buff);
  297. return 0;
  298. }
  299. return 1;
  300. }
  301. /**@brief AT_Data_Replace :提取被头尾字符包裹的字串
  302. * @param buff : 待提取的字符串,必须是实体数组,需要写入
  303. * @param str1 : 被替换的子串,可以是数组和静态字符串
  304. * @param str2 : 替换成的子串,可以是数组和静态字符串
  305. * 例:字符串 AT+QMTCFG="aliauth",0,"a1XVq3z4DsR"
  306. * 参数str1 "aliauth",str2 "recv/mode",替换结果buff: AT+QMTCFG="recv/mode",0,"a1XVq3z4DsR"
  307. */
  308. uint8_t AT_Data_Replace(char buff[],char *str1, char *str2) {
  309. int i,flag = 0;
  310. char *p,*q,*ts;
  311. for(i = 0; buff[i]; ++i)
  312. {
  313. if(buff[i] == str1[0])
  314. {
  315. p = buff + i;
  316. q = str1;
  317. while(*q && (*p++ == *q++));
  318. if(*q == '\0')
  319. {
  320. ts = (char *)malloc(strlen(buff) + 1);
  321. strcpy(ts,p);
  322. buff[i] = '\0';
  323. strcat(buff,str2);
  324. strcat(buff,ts);
  325. free(ts);
  326. flag = 1;
  327. }
  328. }
  329. }
  330. return flag;
  331. }
  332. /**@brief AT_GET_Data_Param_number :指定的标志位开始,提取后面的数据,直到遇到\r,\n,
  333. * @param buff : 待提取的字符串,可以是数组或静态字符串
  334. * @param get_data : 提取后装载的数组,必须是数组,不能是静态字符串因为需要写
  335. * @param head : 头字符串【任意长度符串】
  336. * 例:字符串 " +ESOERR=1,4 "
  337. * 参数head ",",装载结果get_data: "4"
  338. */
  339. uint8_t AT_GET_Data_Param(char * buff,uint8_t get_data[],char*head)
  340. {
  341. char *h=strstr(buff,head);
  342. if(h!=NULL)
  343. {
  344. uint16_t i;
  345. int len=strlen(head);
  346. for(i=0;h[i+len]!='\r'&&h[i+len]!='\n'&&h[i+len]!=' ';i++)
  347. {
  348. get_data[i]=h[i+len];
  349. }
  350. get_data[i]='\0';//加上结束符
  351. }else
  352. {
  353. if(!strstr(buff,head))debug_printf("\r\n未能检索到标志位\r\n");
  354. debug_printf("\r\n请检查你的数据原文:\r\n");
  355. debug_printf("%s", buff);
  356. return 0;
  357. }
  358. return 1;
  359. }
  360. /**@brief AT_Extract_numbers :导入的数组进行提纯,去掉非数字的部分
  361. * @param buff : 待提纯的字符串,必须是实体数组,需要写入
  362. */
  363. uint8_t AT_Extract_numbers(char buff[]) {
  364. uint16_t i=0,n=0;
  365. int len=strlen(buff);
  366. char fifo[32];/*浪费空间,但是效率更高*/
  367. memset(fifo,0, sizeof(fifo));
  368. for(;buff[i]!='\0';)
  369. {
  370. if(buff[i]>='0'&&buff[i]<='9')
  371. {
  372. fifo[n]=buff[i];
  373. n++;
  374. i++;
  375. }
  376. else
  377. {
  378. i++;
  379. }
  380. }
  381. strcpy(buff,fifo);
  382. return 1;
  383. }
  384. /**@brief AT_Extract_numbers :导入的数组进行提纯,去掉非数字和非字母的部分
  385. * @param buff : 待提纯的字符串,必须是实体数组,需要写入
  386. */
  387. uint8_t AT_Extract_numbers_letters(char buff[]) {
  388. uint16_t i=0,n=0;
  389. int len=strlen(buff);
  390. char fifo[256];/*浪费空间,但是效率更高*/
  391. memset(fifo,0,len+1);
  392. for(;buff[i]!='\0';)
  393. {
  394. if((buff[i]>='0'&&buff[i]<='9')||(buff[i]>='A'&&buff[i]<='Z')||(buff[i]>='a'&&buff[i]<='z'))
  395. {
  396. fifo[n]=buff[i];
  397. n++;
  398. i++;
  399. }
  400. else
  401. {
  402. i++;
  403. }
  404. }
  405. //debug_printf("\r\n");
  406. //debug_printf(fifo);
  407. strcpy(buff,fifo);
  408. return 1;
  409. }
  410. /**@brief AT_Remove_spaces :去掉空字符,\r,\n,space
  411. * @param buff : 待提纯的字符串,必须是实体数组,需要写入
  412. */
  413. uint8_t AT_Remove_spaces(char buff[]) {
  414. uint16_t i=0,n=0;
  415. int len=strlen(buff);
  416. char fifo[256];/*浪费空间,但是效率更高*/
  417. memset(fifo,0,len+1);
  418. for(;buff[i]!='\0';)
  419. {
  420. if((buff[i]!='\r')&&(buff[i]!='\n')&&(buff[i]!=' '))
  421. {
  422. fifo[n]=buff[i];
  423. n++;
  424. i++;
  425. }
  426. else
  427. {
  428. i++;
  429. }
  430. }
  431. //debug_printf("\r\n");
  432. //debug_printf(fifo);
  433. strcpy(buff,fifo);
  434. return 1;
  435. }