/** ******************************************************************************
* @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, 1, 0, OS_OPT_TIME_DLY, &err);
if(flug)
{
/*这里是为了吃掉三条开机信息,如果直接开始往下运行,开就信息可能会干扰*/
memset(buff,0,200);
if(Module_Blocking_Read(buff,13000))
{
printf("Power on info : %s\r\n", buff);
// printf("\nPower test\r\n");
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");
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;
}
}
uint8_t AIR_MQTT_PUB(char * topic, char *data, uint32_t len)
{
if(!air.State.MQTT_State) {
ME3616_INFO("Cannot Connect MQTT");
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;
}