OpenCPU网络初始化流程至关重要,是模组正常连接服务器应用的前提。流程包含读取模组IMEI/SN、读取SIM卡IMSI/ICCID和模组PDP激活状态三个环节。本文介绍了ML307A模组OpenCPU模式网络初始化的相关接口、demo代码解析、demo运行示例以及常见问题。
图1 网络初始化流程
一、相关接口
模组的IMEI/SN获取接口可在include\cmiot\cm_sys.h中查看,SIM卡IMSI/ICCID获取接口可以在include\cmiot\cm_sim.h中查看,PDP激活状态查询可以在include\cmiot\cm_modem.h中查看。
1.1 获取模组IMEI
/** * @brief 获取模组IMEI * * @param [out] imei IMEI,长度16字节 * * @return * = 0 - 成功 \n * < 0 - 失败, 返回值为错误码 * * @details More details */int32_t cm_sys_get_imei(char *imei);
模组正常开机成功之后即可调用该接口获取模组IMEI,返回0表示获取成功,小于0表示获取失败;
1.2 获取模组SN
/** * @brief 获取模组SN * * @param [out] sn SN,长度32字节 * * @return * = 0 - 成功 \n * < 0 - 失败, 返回值为错误码 * * @details More details */int32_t cm_sys_get_sn(char *sn);
模组正常开机成功之后即可调用该接口获取模组SN,返回0表示获取成功,小于0表示获取失败;
1.3 获取SIM卡IMSI
/** * @brief 获取设备IMSI * * @param [out] imsi 存储IMSI,长度16字节,申请内存后传入 * @return * = 0 - 成功 \n * < 0 - 失败, 返回值为错误码. * * @details More details * */int32_t cm_sim_get_imsi(char* imsi);
模组正常开机且正常识别到SIM卡之后即可调用该接口获取SIM卡的IMSI,返回0表示获取成功,小于0表示获取失败;
1.4 获取SIM卡ICCID
/* 获取ICCID示例,注意虚拟AT通道传入的指令为"AT*ICCID?\r\n" */void cm_demo_iccid(void)
模组正常开机且正常识别到SIM卡之后即可调用该接口获取SIM卡ICCID,获取ICCID采用虚拟AT指令的方式进行获取,需要注意使用虚拟AT通道之前需要先进行虚拟通道初始化;
1.5 PDP状态查询
int32_t cm_modem_get_pdp_state(uint16_t cid)
模组开机后默认会自动进行第一路PDP激活,该接口调用虚拟AT指令进行激活查询,CID为PDP上下文编号,返回值为虚拟AT指令查询到的PDP状态,返回1表示激活成功,返回0表示激活失败。
二、demo代码解析
在SDK提供的demo中,已经实现模组IMEI/SN和SIM卡的IMSI/ICCID的获取,以及PDP激活状态查询,下面我们详细看一下cm_demo_main.c文件中相关部分的代码。
2.1 获取模组IMEI
#define CM_VER_LEN 65 /*< 存储长度> */char buf[CM_VER_LEN] = {0};/*定义字符串buf并初始化为零 */ int ret;memset(buf, 0, CM_VER_LEN); /*存储的buf清零 */ ret = cm_sys_get_imei(buf); /*调用函数获取IMEI 并存到buf*/ if (ret == 0) { cm_demo_printf("IMEI:%s\n", buf);/*接口函数返回值等于0则获取正常,进行串口打印输出IMEI */ } else { cm_demo_printf("IMEI ERROR\n");/*接口函数返回值不等于0则打印报错 */ }
这里建立一个buf数组,用于存储IMEI字符串,先进行buf清空,然后获取IMEI,最后使用串口打印函数输出;
2.2 获取模组SN
memset(buf, 0, CM_VER_LEN);/*存储的buf清零 */ ret = cm_sys_get_sn(buf); /*调用函数获取模组SN并存到buf*/ if (ret == 0) { cm_demo_printf("SN:%s\n", buf);/*接口函数返回值等于0则获取正常,进行串口打印输出SN */ } else { cm_demo_printf("SN ERROR\n");/*接口函数返回值不等于0则打印报错 */ }
首先进行buf清空,然后获取模组SN,最后使用串口打印函数输出;
2.3 获取SIM卡IMSI
memset(buf, 0, CM_VER_LEN);/*存储的buf清零 */ ret = cm_sim_get_imsi(buf);/*调用函数获取SIM卡IMSI并存到buf*/ if (ret == 0) { cm_demo_printf("IMSI:%s\n", buf);/*接口函数返回值等于0则获取正常,进行串口打印输出IMSI */ } else { cm_demo_printf("IMSI ERROR\n");/*接口函数返回值不等于0则打印报错 */ }
首先进行buf清空,然后获取SIM卡IMSI,最后使用串口打印函数输出;
2.4 获取SIM卡ICCID
/* 获取ICCID示例,注意虚拟AT通道传入的指令为"AT*ICCID?\r\n" */cm_demo_iccid();/* 获取ICCID示例,注意虚拟AT通道传入的指令为"AT*ICCID?\r\n" */void cm_demo_iccid(void){ /* 初始化AT虚拟通道,注册AT虚拟通道消息回调函数*/ if(cm_virt_at_init(iccid_resp_cb)!=0){/* 初始化AT虚拟通道接口返回值不等于0,则串口打印始化AT虚拟通道错误*/ cm_demo_printf("cm_virt_at_init err"); return;}/* 初始化AT虚拟通道接口返回值等于0则发送虚拟AT指令"AT*ICCID?\r\n"*/ if(cm_virt_at_send((uint8_t *)"AT*ICCID?\r\n",strlen("AT*ICCID?\r\n")) < 0){* AT虚拟通道发送数据接口返回值小于0则打印AT虚拟通道发送数据错误*/ cm_demo_printf("cm_virt_at_send err"); return; }osDelay(500);/* AT指令发送完成后进行AT虚拟通道去初始化*/ cm_virt_at_deinit(); }/* AT虚拟通道消息回调函数用于接收AT指令的返回值*/void iccid_resp_cb(void * param){/* 定义at_data字符串用于存储AT指令的返回值*/unsigned char at_data[256]={0};/* 将AT虚拟通道回调函数返回的字符串转换成整型数,不能转换则打印原始数据*/ if(atoi(param) == 0){ /* 通过AT虚拟通道接收数据并存入at_data字符串*/ cm_virt_at_get(at_data,sizeof(at_data));/* 打印AT指令返回值*/ cm_demo_printf("%s\n", at_data); } /* 将AT虚拟通道回调函数返回的字符串转换成整型数*,转换成功则打印ICCID*/else if(atoi(param) == 1){/* 通过AT虚拟通道接收数据并存入at_data字符串*/ cm_virt_at_get(at_data,sizeof(at_data));/* 打印AT指令返回值*/ cm_demo_printf("*ICCID:%s\n", at_data); }}
首先调用函数cm_virt_at_init进行虚拟AT通道初始化,然后发送虚拟AT指令“AT+ICCID?”获取ICCID,通过虚拟AT通道的回调函数iccid_resp_cb打印获取到的ICCID;
2.5查询pdp激活状态
/* 定义PDP查询次数整型变量并初始化为0*/ int pdp_time_out=0; while(1){ /* PDP查询次数大于10次则打印网络超时*/ if(pdp_time_out>10) { cm_demo_printf("network timeout\n"); break; }/* PDP状态查询为1则打印network ready并跳出循环*/ if(cm_modem_get_pdp_state(1) == 1) { cm_demo_printf("network ready\n"); break; }/* 延时1秒PDP查询次数加一*/ osDelay(200); pdp_time_out++; }
以1秒的间隔循环查询PDP激活状态10次,如果次数超过则打印网络超时,如果PDP状态激活成功则打印网络准备好。
三、demo运行示例
上面提到在cm_demo_main.c中,已经实现读取模组IMEI/SN,SIM卡的IMSI/ICCID,以及PDP激活状态查询,下面是cm_demo_main.c运行示例。
[05-04 17:49:19:868]CM OpenCPU Starts //开机成功,opencpu程序开始运行,通过UART0,9600波特率进行打印
[05-04 17:49:19:883]SDK VERSION:ML307A_OpenCPU_Standard_1.3.1.2304071557_release //SDK版本号获取
[05-04 17:49:19:964]fs total:262144,remain:184320 //文件系统信息获取
[05-04 17:49:19:995]heap total:1310716,remain:664352 //系统heap状态获取
[05-04 17:49:20:027]waiting for network... //等待网络激活,超时时间设置为10秒
[05-04 17:49:25:240]network ready //网络初始化成功打印
[05-04 17:49:26:279]Now:2023-5-4:17:49:27,Thursday //获取当前时间
[05-04 17:49:26:311]SN:20209P1001531A000014 //SN号获取
[05-04 17:49:26:343]IMEI:864606060109344 //IMEI获取
[05-04 17:49:26:359]IMSI:460042726515520 //IMSI获取
[05-04 17:49:26:424]*ICCID: "89860407112270005520" //ICCID获取
[05-04 17:49:28:953]
[05-04 17:49:28:953]please input cmds:
四、常见问题
为什么获取不到SIM卡IMSI和ICCID?获取SIM卡IMSI和ICCID需要保证SIM卡电路设计正常,插拔卡方向正确,SIM卡硬件正常才能获取到IMSI和ICCID。
网络超时等待时间是否可以自行配置?可以的,网络超时的时间间隔在不同的网络环境可能存在差异,可自行配置来保证有足够的时间来完成网络激活。
是否所有的AT指令都可以采用虚拟AT指令?虚拟AT不完全支持OneMO AT手册中的指令,仅支持3GPP的AT指令。
激活PDP失败的原因?PDP是在开机读卡之后自动激活的,激活失败需要排查SIM卡是否存在欠费、机卡绑定、未激活问题。