/** ****************************************************************************** * @file AIR.c * @author 度云未来 DOIOT * @brief EC20模块AT指令简易串口驱动 ****************************************************************************** * @attention *

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

* 注意:本程序针对cubemx 生成的hal库快速开发 * 环境:keil5.0 * 描述: * 文件版本:1.3 更新时间2020/10/15 已支持TCP,LWM2M的连接 ********************************************************************************/ /*必备依赖*/ #include "includes.h" #include "trace.h" #include "me3616.h" /*文件的头文件*/ #include "at_module.h" /*AT指令相关的头文件*/ #include "string_fuc.h" #include "bsp.h" #include #include #include #include /********************************************************************************/ /* 测试了strstr和kmp的性能,最终用strstr。 */ /* AIR类的句柄,该句柄会默认调用 */ ME3616 air; /** * @brief AIR硬件开机 * @param flug = 1,阻塞开机,会直到开机成功,且读取完全部开机信息后才会退出 * @param flug = 0,操作完硬件开机后立即返回 * @param [Antiphase_flug]额外参数 : 以宏形式的标志,1为反相,0为不反相 * 【是否反相根据硬件电路决定,如果mcu拉低,模组也被拉低,则不需要反相,否则给反相位置1即可】 * 如果在计时器启动前调用了,建议选择直接返回[针对RTOS] */ uint8_t AIR_Power_On(uint8_t flug) { OS_ERR err; char buff[200]={0}; OSTimeDlyHMSM(0, 0, 0, 500, OS_OPT_TIME_DLY, &err); GPIO_SetBits(GPIOC, GPIO_Pin_3); GPIO_ResetBits(GPIOD, GPIO_Pin_14); OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_DLY, &err); GPIO_SetBits(GPIOD, GPIO_Pin_14); OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_DLY, &err); if(flug) { /*这里是为了吃掉三条开机信息,如果直接开始往下运行,开就信息可能会干扰*/ memset(buff,0,200); if(Module_Blocking_Read(buff,10000)) { printf("Power on info : %s\r\n", buff); air.State.pwr=1; if(strstr(buff,"*CGEV:")) { /*完整开机需要的时常很长*/ AT_CMD_Polling("AT\r\n","OK",200,15000); AT_CMD_Polling("AT\r\n","OK",200,15000); AT_CMD_Polling("AT\r\n","OK",200,15000); ME3616_INFO("AIR Hardware Power On OK!"); module_printf("AT+CREG=1\r\n"); if(Module_Read_A_CRC("OK\r\n", 300)){ printf("\r\n set AT+CREG = OK \r\n"); } module_printf("AT+CREG=?\r\n"); // 查询网络注册状态 return 1; } } } return 0; } /** * @brief AIR硬件复位 * @param flug:复位标志,1,阻塞复位,会直到开机成功才退出,开机时间较长,2,立即返回*/ uint8_t AIR_HARD_Rest(uint8_t flug) { return 0; } /** * @brief AIR软件复位 * @param flug:复位标志,1,阻塞复位,会直到开机成功才退出,软复位很快,2,立即返回*/ uint8_t AIR_SOFT_Rest(uint8_t flug) { return 0; } /** * @brief AIR读取网络状态并打印数据 **/ uint8_t AIR_READ_EPS() { char buff[MODULE_RDA_MAXlen]={0}; char get_buff[100]; int log; ME3616_INFO("Start to query network registration status"); module_printf("AT+CEREG?\r\n"); if(Module_Blocking_Read(buff,1000)) { if(strstr(buff,"+CEREG:")) { AT_GET_Data_2Param(buff,(uint8_t*)get_buff,",","OK"); log=atoi(get_buff); air.State.eps=log; /*装载标数据*/ air.flug.eps=1; /*装载成功标志*/ switch(log) { case 0: ME3616_INFO("You are not logged on to the network. You are not searching the network at present"); break; case 1: ME3616_INFO("Local network already logged in"); break; case 2: ME3616_INFO("\r\nYou are not logged on to the network. You are currently searching the network\r\n"); break; case 3: ME3616_INFO("\r\nRegistration denied\r\n"); break; case 4: ME3616_INFO("\r\nUnknown state\r\n"); break; case 5: ME3616_INFO("\r\nYou have logged in to the network and are roaming\r\n"); break; default: { ME3616_ERROR("Response ME3616_ERROR:%s",buff); return 33;//设定的错误码 } } return log+1; }else { ME3616_ERROR("%s",buff); return 0; } } ME3616_INFO("Response timeout"); return 0; } /** * @brief AIR读取网络信号强度 * @param rssi:用来装载的参数,会装载信号强度原文[弃用] * @param ber:用来装载的参数, 会装载错码率原文[弃用] * */ uint8_t AIR_READ_CSQ() { char buff[MODULE_RDA_MAXlen]={0}; char get_buff[100]={0}; int log; #if(config_CHINESE_LOG) ME3616_INFO("开始查询网络信号强度"); #else ME3616_INFO("Start querying network signal strength"); #endif module_printf("AT+CSQ\r\n"); if(Module_Blocking_Read(buff,1000)) { if(strstr(buff,"+CSQ:")) { AT_GET_Data_2Param(buff,(uint8_t*)get_buff,"+CSQ:",","); log=atoi(get_buff); air.State.rssi=log; air.flug.rssi=1; /*装载成功标志*/ if(log==99) {air.State.dBm = 0; ME3616_INFO("signal intensity:there is no signal");} else if(log>=31&&log<=99) {air.State.dBm = log*2-113; ME3616_INFO("signal intensity:-51dBm or higher");} else if(log>=2&&log<31) {air.State.dBm = log*2-113; ME3616_INFO("signal intensity:-109dBm ~ -53dBm");} else if(log==1) {air.State.dBm = -111; ME3616_INFO("signal intensity:-111dBm");} else {air.State.dBm = log*2-113; ME3616_INFO("signal intensity:-111dBm or less");} AT_GET_Data_2Param(buff,(uint8_t*)get_buff,",","OK"); log=atoi(get_buff); air.State.ber=log; air.flug.ber=1; /*装载成功标志*/ //*ber=log; switch(log) { case 0: ME3616_INFO("Bit error rate:<0.01%"); break; case 1: ME3616_INFO("Bit error rate:0.01% --- 0.1%"); break; case 2: ME3616_INFO("Bit error rate:0.1% --- 0.5%"); break; case 3: ME3616_INFO("Bit error rate:0.5% --- 1.0%"); break; case 4: ME3616_INFO("Bit error rate:1.0% --- 2.0%"); break; case 5: ME3616_INFO("Bit error rate:2.0% --- 4.0%"); break; case 6: ME3616_INFO("Bit error rate:4.0% --- 8.0%"); break; case 7: ME3616_INFO("Bit error rate:> 8.0%"); break; case 8: ME3616_INFO("Bit error rate:So far or not measurable");break; default: { ME3616_ERROR("So far or not measurable"); return 33;//设定的错误码 } } return log+1; } { ME3616_ERROR("%s",buff); return 0; } } ME3616_INFO("Response timeout"); return 0; } /** * @brief AIR读取精确的网络信号强度 * */ int AIR_READ_CESQ() { char buff[MODULE_RDA_MAXlen]={0}; char get_buff[100]={0}; int log; ME3616_INFO("Start querying network signal strength"); module_printf("AT+CESQ\r\n"); if(Module_Blocking_Read(buff,1000)) { if(strstr(buff,"+CESQ:")) { AT_GET_Data_2Param(buff,(uint8_t*)get_buff,"+CESQ: ",","); log=atoi(get_buff); //me3616.State.rssi=log; air.flug.dBm=1; /*装载成功标志*/ log=atoi(get_buff); log+=-110;/*转化成dBm*/ air.State.dBm=log; ME3616_INFO("signal intensity:%ddBm"); return log+1; } { ME3616_ERROR("%s",buff); return 0; } } ME3616_INFO("Response timeout"); return 0; } /** * @brief AIR读取SIM卡的CCID * @param rssi:用来装载的参数,会装载信号强度原文 * @param ber:用来装载的参数, 会装载错码率原文 * */ uint8_t AIR_READ_CCID() { char buff[MODULE_RDA_MAXlen]={0}; char get_buff[32]={'\0'}; ME3616_INFO("Start to query SIM card iccid"); module_printf("AT+ICCID\r\n"); if(Module_Blocking_Read(buff,3000)) { if(strstr(buff,"+ICCID:")) { if(AT_GET_Data_2Param(buff,(uint8_t*)get_buff, "+ICCID: ", "\r\n"))//0d0a { strcpy(air.State.iccid,get_buff); air.flug.iccid=1; /*装载成功标志*/ debug_printf("\r\nICCID:%s\r\n", get_buff); } else { ME3616_ERROR("%s",buff); return 0; } return 1; } else { if(strstr(buff,"SIM not inserted")) { ME3616_ERROR("SIM card not inserted,Please check the SIM card"); return 0; } else { ME3616_ERROR("%s",buff); return 0; } } } ME3616_ERROR("Response timeout"); return 0; } /** * @brief AIR查询pin状态 * @param return 1 为ready,0 其他 * */ uint8_t AIR_READ_PIN() { char buff[256]={0}; #if(config_CHINESE_LOG) ME3616_INFO("开始查询PIN状态"); #else ME3616_INFO("Start to query pin status"); #endif module_printf("AT+CPIN?\r\n"); if(Module_Blocking_Read(buff,1000)) { if(strstr(buff,"+CPIN:")) { air.State.pin=1; air.flug.pin=1; /*装载成功标志*/ #if(config_CHINESE_LOG) if(strstr(buff,"READY")) {ME3616_INFO("PIN状态: READY,已准备好");return 1;} else if(strstr(buff,"SIM PIN")) {ME3616_INFO("PIN状态: 需要pin码");return 1;} else if(strstr(buff,"SIM PUK")) {ME3616_INFO("PIN状态: PIN 码解锁密码");return 1;} else if(strstr(buff,"PH-SIM PIN")) {ME3616_INFO("PIN状态: SIM 卡绑定密码");return 1;} else if(strstr(buff,"SIM PIN2")) {ME3616_INFO("PIN状态: PIN2 码密码");return 1;} else if(strstr(buff,"SIM PUK2")) {ME3616_INFO("PIN状态: PIN2 码解锁密码");return 1;} else if(strstr(buff,"PH-NET PIN")) {ME3616_INFO("PIN状态: 网络密码");return 1;} #else if(strstr(buff,"READY")) {ME3616_INFO("Pin status: READY");return 1;} else if(strstr(buff,"SIM PIN")) {ME3616_INFO("Pin status: need pin");return 1;} else if(strstr(buff,"SIM PUK")) {ME3616_INFO("Pin status: Pin code unlock password");return 1;} else if(strstr(buff,"PH-SIM PIN")) {ME3616_INFO("Pin status: SIM card binding password");return 1;} else if(strstr(buff,"SIM PIN2")) {ME3616_INFO("Pin status: Pin2 code");return 1;} else if(strstr(buff,"SIM PUK2")) {ME3616_INFO("Pin status: Pin2 code unlock password");return 1;} else if(strstr(buff,"PH-NET PIN")) {ME3616_INFO("Pin status: Network password");return 1;} #endif } else{ ME3616_ERROR("%s",buff); return 0; } } ME3616_INFO("Response timeout"); return 0; } /** * @brief AIR查询CIMI状态 * */ uint8_t AIR_READ_CIMI() { char buff[MODULE_RDA_MAXlen]={0}; #if(config_CHINESE_LOG) ME3616_INFO("开始查询PIN状态"); #else ME3616_INFO("Start to query pin status"); #endif module_printf("AT+CIMI\r\n"); if(Module_Blocking_Read(buff,1000)) { if(strstr(buff,"OK")) { AT_Extract_numbers(buff); /*提纯数字*/ strcat(air.State.imsi,buff); air.flug.imsi=1; ME3616_INFO("CIMI:%s",buff); return 1; } else{ ME3616_ERROR("%s",buff); return 0; } } ME3616_INFO("Response timeout"); return 0; } /** * @brief AIR查询IMEI并装载至寄存器 * @param * */ uint8_t AIR_READ_IMEI() { char buff[MODULE_RDA_MAXlen]={0}; ME3616_INFO("Start query IMEI"); module_printf("AT+CGSN\r\n"); if(Module_Blocking_Read(buff,3000)) { if(strstr(buff,"OK")) { char temp[32]={0}; AT_GET_Data_2Param(buff,(uint8_t*)temp, "", "OK"); /*头尾提取方法*/ AT_Extract_numbers(temp); /*提纯数字*/ strcpy(air.State.imei,temp); air.flug.imei=1; debug_printf("\r\nIMEI:%s\r\n", temp); return 1; } else { ME3616_ERROR("%s",buff); return 0; } } ME3616_ERROR("Response timeout"); return 0; } /** * @brief AIR查询IMEI并装载至寄存器 * @param * */ uint8_t AIR_READ_Revision() { return 0; } int AIR_HTTP_GET(const char *url, uint32_t len, uint32_t *pLen) { int ret = 0; char buff[MODULE_RDA_MAXlen]={0}; //关闭UDP或TCP module_printf("AT+CIPCLOSE\r\n"); Module_Read_A_CRC("CLOSE OK", 200); //设置HTTP功能的承载类型 module_printf("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n"); Module_Read_A_CRC("OK", 200); //设置pdp承载参数之APN module_printf("AT+SAPBR=3,1,\"APN\",\"\"\r\n"); Module_Read_A_CRC("OK", 200); //激活该承载的GPRS PDP上下文 module_printf("AT+SAPBR=1,1\r\n"); Module_Read_A_CRC("OK", 200); //查询下承载的状态 module_printf("AT+SAPBR=2,1\r\n"); Module_Read_A_CRC("OK", 200); //HTTP协议栈初始化 module_printf("AT+HTTPINIT\r\n"); Module_Read_A_CRC("OK", 200); //建立http链接 module_printf("AT+HTTPPARA=\"URL\",\"%s\"\r\n", url); Module_Read_A_CRC("OK", 300); //设置HTTP会话参数:CID //module_printf("AT+HTTPPARA=\"CID\",1", url); //Module_Read_A_CRC("OK", 300); //发送的命令, 提取数据 AT+HTTPACTION= module_printf("AT+HTTPACTION=0\r\n"); /* OK +HTTPACTION: ,, +HTTPACTION: ,, +HTTPACTION: ,, */ Module_Read_A_CRC("OK", 300); //TODO 提取数据长度 if(Module_Blocking_Read(buff,6000)) { char *strx; printf("%s\r\n", buff); //+HTTPACTION: 0,200,55420 strx = strstr(buff, "," ); if(strx) { printf("%s\r\n", strx); strx += 1; strx = strstr(strx, "," ); if(strx) { printf("%s\r\n", strx); strx += 1; *pLen = atoi(strx);//获取接收长度 } } //sscanf(buff, "+HTTPACTION: %d,%d,%d", &method, &status_code, pLen); //printf("%d, %d, %d\r\n", method, status_code, *pLen); ret = 1; } return ret; } char http_buffer[1024]; uint8_t * AIR_HTTP_READ(uint32_t start_addr, uint32_t data_len) { uint8_t *p_buf = NULL; uint32_t read_len; //AT+HTTPREAD=, module_printf("AT+HTTPREAD=%d,%d\r\n", start_addr, data_len); /* +HTTPREAD: OK */ memset(http_buffer, 0, sizeof(http_buffer)); if(Module_Blocking_Read(http_buffer, 300)) { char temp[32]={0}; if(AT_GET_Data_2Param(http_buffer,(uint8_t*)temp, "+HTTPREAD: ", "\r\n")) { /*头尾提取方法*/ read_len = atoi(temp); if(data_len == read_len) { //printf("%s", http_buffer); p_buf = (uint8_t *)strstr(http_buffer, "+HTTPREAD: "); p_buf = (uint8_t *)strstr((char *)p_buf, "\r\n"); p_buf += 2;/* data position. */ } } } return p_buf; } /*--------------------------------MQTT------------------------------------------------------*/ uint8_t AIR_MQTT_Set_Net(char *ip,char *port) { if(strcpy(air.State.mqtt_ip,ip)) { if(strcpy(air.State.mqtt_port,port)) { air.flug.mqtt_ip=1; air.flug.mqtt_port=1; ME3616_INFO("Net Set OK!"); return 1; } } return 0; } uint8_t AIR_MQTT_Connet(char *_productID,char *_deviceID,char *_secret) { int mqttid; if(!(air.flug.mqtt_ip&&air.flug.mqtt_port)) { ME3616_INFO("The network port has not been configured"); return 0; } //AT+MCONFIG=, XXXX, $$$$ module_printf("AT+MCONFIG=%s,%s,%s\r\n",_deviceID,_productID,_secret); //printf("AT+MCONFIG=%s,%s,%s\r\n",_deviceID,_productID,_secret); if(Module_Read_A_CRC("OK", 300)) { //AT+MIPSTART=”ip或域名”,”port” module_printf("AT+MIPSTART=\"%s\",\"%s\"\r\n",air.State.mqtt_ip,air.State.mqtt_port); // module_printf("AT+MIPSTART=\"%s\",\"%s\"\r\n","mqtt.cpyypt.cn","9000"); if(Module_Read_A_CRC("CONNECT OK", 1000)) { module_printf("AT+MCONNECT=1,60\r\n"); if(Module_Read_A_CRC("CONNACK OK", 300)) { air.State.mqtt_id=mqttid; air.State.MQTT_State=1; ME3616_INFO("Connect MQTT Successful,MQTT id"); /***********************************/ module_printf("AT+MQTTMODE=1\r\n"); if(Module_Read_A_CRC("OK", 300)) { ME3616_INFO("MQTTMODE Successful,MQTT MODE 1"); } else { ME3616_ERROR("AT+MQTTMODE error"); } /***********************************/ module_printf("ATE0\r\n"); if(Module_Read_A_CRC("OK", 300)){ ME3616_ERROR("ATE success\r\n"); } else { ME3616_ERROR("ATE error\r\n"); } return 1; } else { ME3616_ERROR("AT+MCONNECT error"); } } else { ME3616_ERROR("AT+MCONFIG error"); } } else { ME3616_INFO("Response timeout"); } return 0; } uint8_t AIR_MQTT_SUB(char * topic) { if(!air.State.MQTT_State) { ME3616_INFO("Cannot Connect MQTT_02"); return 0; } //AT+MSUB=, module_printf("AT+MSUB=\"%s\", 0\r\n", topic); if(Module_Read_A_CRC("SUBACK", 300)) { //ME3616_INFO("Sub \"%s\" Successful", topic); ME3616_INFO("Sub topic Successful"); return 1; } else { ME3616_INFO("Sub ERROR"); return 0; } } /*----------------------------------------------------------------- * 返回值 : 0:没有连接上 * 1: 连接上mqtt * ---------------------------------------------------------------*/ uint8_t AIR_MQTT_PUB(char * topic, char *data, uint32_t len) { if(!air.State.MQTT_State) { ME3616_INFO("Cannot Connect MQTT_03"); return 0; } #if ( 1 ) // printf("test %s\n",data); //AT+MPUB=,,, module_printf("AT+MPUB=\"%s\",0,0,\"%s\"\r\n",topic,data); if(Module_Read_A_CRC("OK", 300)) { //ME3616_INFO("Pub Successful \r\n[%s]<-[%s]",topic,data); return 1; } else { ME3616_INFO("Pub ERROR"); return 0; } #else module_printf("AT+MPUBEX=\"%s\",2,0,%d\r\n",topic,len); if(Module_Read_A_CRC(">", 300)) { //ME3616_INFO("return >\r\n"); //module_printf(data); uart_msg_send(UART3_ID,data,len); //data_dump("net sendx", (uint8_t *)data, len); if(Module_Read_A_CRC_DA("OK","FEFE",len, 300)){ // ME3616_INFO("return success\r\n"); return 1; } else { ME3616_INFO("return failed\r\n"); return 0; } } else { ME3616_INFO("Pub ERROR"); return 0; } #endif } void AIR_IMEI_ICCID_INFO_GET(char *imei, char *iccid) { memcpy(imei, air.State.imei, strlen(air.State.imei)); memcpy(iccid, air.State.iccid, strlen(air.State.iccid)); } /*发送的指令组,需要校验的响应组,校验组数量,校验等级,重发次数,跳转位置,超时时间*/ /** * @brief AIR句柄的构造函数 * @param 该函数会对本文件核心全局句柄进行函数构造 */ ME3616 * AIR_Init(void) { ME3616 * me=&air; memset(me, 0, sizeof(ME3616)); #if(config_MQTT_Enable) me->MQTT.SetNet=AIR_MQTT_Set_Net; me->MQTT.Connect=AIR_MQTT_Connet; me->MQTT.Sub=AIR_MQTT_SUB; me->MQTT.Pub=AIR_MQTT_PUB; #endif me->imei_iccid_get = AIR_IMEI_ICCID_INFO_GET; me->PowerOn=AIR_Power_On; #if(Hvertion_data) me->HardRest=AIR_HARD_Rest; #endif #if(SoftRest_fun) me->SoftRest=AIR_SOFT_Rest; #endif #if(GetEPS_fun) me->GetEPS=AIR_READ_EPS; #endif #if(GetCSQ_fun) me->GetCSQ=AIR_READ_CSQ; #endif me->GetCESQ=AIR_READ_CESQ; #if(GetCCID_fun) me->GetCCID=AIR_READ_CCID; #endif me->GetPIN=AIR_READ_PIN; me->GetIMEI=AIR_READ_IMEI; #if(Svertion_data) me->Version=AIR_READ_Revision; #endif #if 0 me->flug.iccid=0; memset(me->State.iccid,0,50); me->flug.imei=0; memset(me->State.imei,0,50); me->flug.imsi=0; memset(me->State.imsi,0,50); #if(Hvertion_data) me->flug.Hvertion=0; memset(me->State.Hvertion,0,50); #endif #if(Svertion_data) me->flug.Svertion=0; memset(me->State.Svertion,0,50); #endif me->flug.pwr=0; me->flug.rssi=0; me->flug.ber=0; me->flug.eps=0; me->flug.pin=0; me->flug.rest=0; #endif return me; } void AIR_CLOSE_TCP(void) { module_printf("AT+MDISCONNECT\r\n"); // 先关闭mqtt连接 if(Module_Read_A_CRC("OK", 300)){ printf("mqtt connect close"); } module_printf("AT+MDISCONNECT\r\n"); // 再关闭TCP连接 if(Module_Read_A_CRC("OK", 300)){ printf("tcp connect close"); } // maqtt_check_connect_status(1); } int maqtt_check_connect_status(uint8_t type) { char buff[64]={0}; // char get_buff[32]={'\0'}; switch(type){ case 0x01: // 查询MQTT连接状态 module_printf("AT+MQTTSTATU\r\n"); if(Module_Read_A_CRC("OK", 300)){ printf("mqtt connect ok"); } if(Module_Blocking_Read(buff,5000)) { if(strstr(buff,"+MQTTSTATU:")) { printf("mqtt status : %s\r\n",buff); } else { printf("\r\n mqtt opt \r\n"); } } else { printf("\r\n mqtt connect failed \r\n"); } break; } return 0; }