/******************************************************************************** * @file AT_Module.c * @author 度云未来 DOIOT * @brief 针对公司模块AT指令的处理库 ****************************************************************************** * @attention *

© Copyright (c) 2019 成都度云未来 * All rights reserved.

* 注意:本程序针对cubemx 生成的hal库程序快速开发 * 环境:keil5.0 * STM32Cube FW_F1 V1.8.0 * 文件版本:1.3 更新时间2020/10/15 降低了文件之间的耦合度 ********************************************************************************/ #include "includes.h" #include "trace.h" #include "at_module.h" #include "stdarg.h" #include "string.h" #include "stdio.h" #include "stdlib.h" #include "../net_proc.h" uint8_t AT_CMD_SEND(AT_CMD task); extern int uart_blocking_read(char *buffer, u8 uartid, u32 timeout); char at_rxbuff[1024]; extern system_network_t sys_net; int Module_Blocking_Read(char *buffer, u32 timeout) { int ret = 0; // char *str1; // char *msg = NULL; // int len = 0; ret = uart_blocking_read(buffer, UART_ME3616, timeout); // if(strstr(buffer,"+MSUB:")){ // str1 = strstr(buffer,"byte"); // if(str1){ // len = atoi(str1-3); // memset(sys_net.str, 0, sizeof(sys_net.str)); // msg = (char *)net_queue_mem_calloc_must(); // if(msg) { // memcpy(msg, str1+5, len); // // data_dump("NET RECB", (char*)msg, len); // net_queue_insert((char *)msg, len); //将数据放到消息队列中 // } // else // { // net_queue_mem_free(msg); // } // } // } return ret; } uint8_t AT_TASK_START(AT_CMD task[],uint8_t Size) { uint32_t i; for(i=0;iovertime) return 0; } } /**@brief AT_GET_data:提取字符串中第Number_of_groups组被特定字符包裹的信息,标志必须是成对闭合的 * @param buff : 待提取的字符串,可以是数组或静态字符串 * @param get_data : 提取后装载的数组,必须是数组,不能是静态字符串因为需要写 * @param sign : 包裹符号,是一个字符 * @param Number_of_groups : 提取的是第几组 * 例:字符串 "AT+MIPOPEN=1,"TCP","122.114.122.174",41838,100,0,1,2,11002" * 参数Number_of_groups=2提取第二组,装载结果get_data: 122.114.122.174 */ uint8_t AT_GET_Data(char * buff,uint8_t get_data[],char*sign,uint8_t Number_of_groups) { uint16_t i=0,count=0; while(buff[i]!='\0') /*获取分隔符整数*/ { if(buff[i]==sign[0]) count++; i++; } if(count%2==0&&count>=Number_of_groups*2) /*偶数分隔符数才继续进行*/ { char chBuffer[512] ; /*按需调整*/ char *pchDilem =sign; /*分隔符*/ char *pchStrTmpIn = NULL; /*剩下的缓存*/ char *pchTmp = NULL; /*提取出的字符*/ i=0; strcpy(chBuffer,buff); pchTmp = chBuffer; while(NULL != ( pchTmp = strtok_r( pchTmp, pchDilem, &pchStrTmpIn) )) { // uart1_printf("\n pchTmp[%s] \n",pchTmp); i++; if(i==Number_of_groups*2) strcpy((char*)get_data,pchTmp); pchTmp = NULL; } return 1; } else return 0; /*非偶数分隔符直接结束*/ } /**@brief AT_GET_Data_2Param :提取被头尾字符串包裹的字串 * @param buff : 待提取的字符串,可以是数组或静态字符串 * @param get_data : 提取后装载的数组,必须是数组,不能是静态字符串因为需要写 * @param head : 头字符串【任意长度符串】 * @param tail : 尾字符串【任意长度字符串】 * 例:字符串 "+QGPSGNMEA: $GPRMC,021229.00,A,3041.560083,N,10405.832869,E,0.0,247.3,040920,1.9,W,A*28" * 参数head ",A",tail ",N",装载结果get_data: "3041.560083" */ uint8_t AT_GET_Data_2Param(char * buff,uint8_t get_data[],char*head,char*tail) { if(strstr(buff,head)&&strstr(buff,tail)) { uint16_t i; uint16_t len1,len2; char *t = NULL; char *h=strstr(buff,head); len1=strlen(h); /*剩余长度*/ len2=strlen(head); /*头子串长度*/ t=strstr(h+len2,tail); if(len1>len2) { for(i=0;h+i+len2!=t;i++) { get_data[i]=h[i+len2]; } get_data[i]='\0';//加上结束符 }else { debug_printf("\r\n字串长度错误\r\n"); return 0; } }else { if(!strstr(buff,head))debug_printf("\r\n未能检索到头字串\r\n"); if(!strstr(buff,tail))debug_printf("\r\n未能检索到尾字串\r\n"); debug_printf("\r\n请检查你的数据原文:\r\n"); debug_printf("%s", buff); return 0; } return 1; } /**@brief AT_Data_Replace :提取被头尾字符包裹的字串 * @param buff : 待提取的字符串,必须是实体数组,需要写入 * @param str1 : 被替换的子串,可以是数组和静态字符串 * @param str2 : 替换成的子串,可以是数组和静态字符串 * 例:字符串 AT+QMTCFG="aliauth",0,"a1XVq3z4DsR" * 参数str1 "aliauth",str2 "recv/mode",替换结果buff: AT+QMTCFG="recv/mode",0,"a1XVq3z4DsR" */ uint8_t AT_Data_Replace(char buff[],char *str1, char *str2) { int i,flag = 0; char *p,*q,*ts; for(i = 0; buff[i]; ++i) { if(buff[i] == str1[0]) { p = buff + i; q = str1; while(*q && (*p++ == *q++)); if(*q == '\0') { ts = (char *)malloc(strlen(buff) + 1); strcpy(ts,p); buff[i] = '\0'; strcat(buff,str2); strcat(buff,ts); free(ts); flag = 1; } } } return flag; } /**@brief AT_GET_Data_Param_number :指定的标志位开始,提取后面的数据,直到遇到\r,\n, * @param buff : 待提取的字符串,可以是数组或静态字符串 * @param get_data : 提取后装载的数组,必须是数组,不能是静态字符串因为需要写 * @param head : 头字符串【任意长度符串】 * 例:字符串 " +ESOERR=1,4 " * 参数head ",",装载结果get_data: "4" */ uint8_t AT_GET_Data_Param(char * buff,uint8_t get_data[],char*head) { char *h=strstr(buff,head); if(h!=NULL) { uint16_t i; int len=strlen(head); for(i=0;h[i+len]!='\r'&&h[i+len]!='\n'&&h[i+len]!=' ';i++) { get_data[i]=h[i+len]; } get_data[i]='\0';//加上结束符 }else { if(!strstr(buff,head))debug_printf("\r\n未能检索到标志位\r\n"); debug_printf("\r\n请检查你的数据原文:\r\n"); debug_printf("%s", buff); return 0; } return 1; } /**@brief AT_Extract_numbers :导入的数组进行提纯,去掉非数字的部分 * @param buff : 待提纯的字符串,必须是实体数组,需要写入 */ uint8_t AT_Extract_numbers(char buff[]) { uint16_t i=0,n=0; int len=strlen(buff); char fifo[32];/*浪费空间,但是效率更高*/ memset(fifo,0, sizeof(fifo)); for(;buff[i]!='\0';) { if(buff[i]>='0'&&buff[i]<='9') { fifo[n]=buff[i]; n++; i++; } else { i++; } } strcpy(buff,fifo); return 1; } /**@brief AT_Extract_numbers :导入的数组进行提纯,去掉非数字和非字母的部分 * @param buff : 待提纯的字符串,必须是实体数组,需要写入 */ uint8_t AT_Extract_numbers_letters(char buff[]) { uint16_t i=0,n=0; int len=strlen(buff); char fifo[256];/*浪费空间,但是效率更高*/ memset(fifo,0,len+1); for(;buff[i]!='\0';) { if((buff[i]>='0'&&buff[i]<='9')||(buff[i]>='A'&&buff[i]<='Z')||(buff[i]>='a'&&buff[i]<='z')) { fifo[n]=buff[i]; n++; i++; } else { i++; } } //debug_printf("\r\n"); //debug_printf(fifo); strcpy(buff,fifo); return 1; } /**@brief AT_Remove_spaces :去掉空字符,\r,\n,space * @param buff : 待提纯的字符串,必须是实体数组,需要写入 */ uint8_t AT_Remove_spaces(char buff[]) { uint16_t i=0,n=0; int len=strlen(buff); char fifo[256];/*浪费空间,但是效率更高*/ memset(fifo,0,len+1); for(;buff[i]!='\0';) { if((buff[i]!='\r')&&(buff[i]!='\n')&&(buff[i]!=' ')) { fifo[n]=buff[i]; n++; i++; } else { i++; } } //debug_printf("\r\n"); //debug_printf(fifo); strcpy(buff,fifo); return 1; }