移动M5310A模块固件中封装的SDK会自动获取模组当前的IMEI和IMSI用于ONENET平台登录,在ONENET平台需要使用当前设备的 IMEI 和 IMSI 进行设备注册。模组设备实体创建需要的配置数据,称为设备注册码。虽然有专门的软件生成注册码,但是不同平台接入或者接入方式有更改时,则需要重新生产注册码并更新程序,本文将生成注册码移植到程序中,只提供相应的接口修改。
注意:本流程使用的模组版本为CMVER:2.1.1.1809071028.
原始配置信息在config.xml文件中:
-
1.0 //配置文件版本号
3 //配置个数
-
1024 //最大传输单元大小
1 //连接类型。默认配置为1
1 //网络类型,默认应设置为 1
//缺省,保持默认为空
//APN 用户名,保持默认为空
//APN 密码,保持认为空
1 //接入方式,对接重庆平台默认应配置为 1,其他平台配置为 0
nbiotbt.heclouds.com:5683 //平台地址
AuthCode:12458789; /*其他配置信息,以“key:value;”的组合形式构成,
如支持认证的 OneNET 接入方式配置为 AuthCode,value 为具体的 AuthCode 根据需求自行填写。如未设置
AuthCode 无需填写*/
-
0 //调试开关,0 表示关闭调试模式,1 表示打开调试模式
0 //扩展信息开关,默认应设置为 1
0 //日志输出模式,默认应设置为 3
0 //日志输出调试级别,默认应设置为 1
0 //日志缓存长度,无效值
//如无需 OneNET 设备认证,该选项应缺省为空,否则应配置 AuthCode
模组侧设备创建使用 AT+MIPLCREATE 指令,其指令格式为:
AT+MIPLCREATE=,,,,
//totalsize : 指示部分总数据长度,按照 ASCII 计数
//config : 具体的设备配置数据,满足配置结构体规范
//index : 配置数据分片参数
//currentsize : 当前指令所包含的配置文件长度
//flag : 配置数据流结束符
/**@brief 配置ID**/
typedef enum enum_cfgid {
cis_cfgid_init = 0x01,
cis_cfgid_net = 0x02,
cis_cfgid_sys = 0x03
}cfgid_t;
/**@brief 头信息结构体**/
typedef struct {
uint8_t head; // version << 4 | cfgcnt
uint16_t config_len;
}head_node_t;
/**@brief 初始信息结构体**/
typedef struct {
uint8_t cfgid;
uint16_t node_len;
}init_node_t;
/**@brief 网络信息结构体**/
typedef struct {
uint8_t cfgid;
uint16_t node_len;
uint16_t mtu_len;
uint8_t link_band; // ((linktype << 4) & 0xF0 | bandtype & 0x0F)
uint16_t apn_len;
uint8_t* apn;
uint16_t uname_len;
uint8_t* uname;
uint16_t pwd_len;
uint8_t* pwd;
uint16_t hostlen_bootstrap; //(dataHost.length)|(bootstrap<<12)
char* host_data;
uint16_t user_data_len;
uint8_t* user_data;
}net_node_t;
/**@brief 系统调试信息结构体**/
typedef struct {
uint8_t cfgid;
uint16_t node_len;
uint8_t log_cfg; //LogEnabled << 7 | LogExtOutput << 6 | LogOutputType << 4 | LogOutputLevel
uint16_t log_buf_size;
uint16_t user_data_len;
uint8_t* user_data;
}sys_node_t;
/**@brief MIPL配置结构体**/
typedef struct {
head_node_t head_node; /* 头信息 */
init_node_t init_node; /* 初始信息 */
net_node_t net_node; /* 入网信息 */
sys_node_t sys_node; /* 系统调试信息 */
}mipl_config_t;
/*******************************************************************************
* 函数名称:config_put_u16
* 功能描述:16位数据转为字符串格式
* 输入参数:p - 字符串指针
* val - 传入需要转换的数值
* 返 回 值 : none.
******************************************************************************/
static void config_put_u16(uint8_t* p, uint16_t val)
{
uint8_t data[2] = { 0 };
data[0] = (val >> 8) & 0xff;
data[1] = (val) & 0xff;
memcpy(p, data, 2);
}
/*******************************************************************************
* 函数名称:m5310a_HexToAsc
* 功能描述:将一个字节数据转换为16进制字符串
* 输入参数:uc - 待转换数据
* val - 转换后的字符串
* 返 回 值 : none.
******************************************************************************/
static void m5310a_HexToAsc(uint8_t uc, unsigned char* str)
{
*str++ = g_strlib_digits[(uc >> 4) & 0x0f];
*str++ = g_strlib_digits[uc & 0x0f];
*str = 0;
}
/*******************************************************************************
* 函数名称:mipconfig_legal
* 功能描述:MIPL配置参数检验合格性
* 输入参数:config - 传入配置信息数据指针
* 返 回 值 : 0:成功,-1:失败.
******************************************************************************/
static int mipconfig_legal(mipl_config_t* config)
{
if (config->net_node.mtu_len <= 256) {
config->net_node.mtu_len = 256;
M5310A_dbg( "WARNING:not found mtu.use default %d\n", config->net_node.mtu_len);
}
else if (config->net_node.mtu_len > 1280) {
config->net_node.mtu_len = 1280;
M5310A_dbg("WARNING:invalid mtu.use default %d\n", config->net_node.mtu_len);
}
if (0 == (config->net_node.hostlen_bootstrap & 0x0fff) || NULL == config->net_node.host_data) {
M5310A_dbg("ERROR:invalid or not found host info.\n");
return - 1;
}
if (config->net_node.apn_len > 0) {
if (config->net_node.apn == NULL) {
M5310A_dbg("ERROR:invalid or not found APN info.\n");
return -1;
}
}
if (config->net_node.uname_len > 0) {
if (config->net_node.uname == NULL) {
M5310A_dbg("ERROR:invalid or not found Username info.\n");
return -1;
}
}
if (config->net_node.pwd_len > 0) {
if (config->net_node.pwd == NULL) {
M5310A_dbg("ERROR:invalid or not found Password info.\n");
return -1;
}
}
if (config->net_node.user_data_len > 0) {
if (config->net_node.user_data == NULL) {
M5310A_dbg("ERROR:invalid or not found Userdata info.\n");
return -1;
}
}
if (config->sys_node.user_data_len > 0) {
if (config->sys_node.user_data == NULL) {
M5310A_dbg("ERROR:invalid or not found Log_Userdata info.\n");
return -1;
}
}
return 0;
}
/*******************************************************************************
* 函数名称:head_node_parse
* 功能描述:头信息解析
* 输入参数:head_node - 传入头信息数据指针
* buffer - 解析处理后存储缓冲区指针
* 返 回 值 : 返回数据长度.
******************************************************************************/
static int head_node_parse(head_node_t * head_node, uint8_t * buffer)
{
uint8_t* buf = buffer;
uint8_t* start = buf;
*buf++ = head_node->head;
buf += sizeof(uint16_t);
return buf - start;
}
/*******************************************************************************
* 函数名称:init_node_parse
* 功能描述:初始信息解析
* 输入参数:init_node - 传入初始信息数据指针
* buffer - 解析处理后存储缓冲区指针
* 返 回 值 : 返回数据长度.
******************************************************************************/
static int init_node_parse(init_node_t * init_node, uint8_t * buffer)
{
uint8_t* buf = buffer;
uint8_t* start = buf;
uint16_t offset = 0;
*buf++ = init_node->cfgid;
buf += sizeof(uint16_t);
offset = buf - start;
config_put_u16(start + 1, offset);
return offset;
}
/*******************************************************************************
* 函数名称:net_node_parse
* 功能描述:网络信息解析
* 输入参数:net_node - 传入网络信息数据指针
* buffer - 解析处理后存储缓冲区指针
* 返 回 值 : 返回数据长度.
******************************************************************************/
static int net_node_parse(net_node_t * net_node, uint8_t * buffer)
{
uint8_t* buf = (uint8_t *)buffer;
uint8_t* start = (uint8_t *)buf;
uint16_t offset = 0;
*buf++ = net_node->cfgid;
buf += sizeof(uint16_t);
config_put_u16(buf, net_node->mtu_len);
buf += sizeof(uint16_t);
*buf++ = net_node->link_band;
config_put_u16(buf, net_node->apn_len);
buf += sizeof(uint16_t);
if (net_node->apn_len > 0) {
memcpy(buf, net_node->apn, net_node->apn_len);
buf += net_node->apn_len;
}
config_put_u16(buf, net_node->user_data_len);
buf += sizeof(uint16_t);
if (net_node->user_data_len > 0) {
memcpy(buf, net_node->user_data, net_node->user_data_len);
buf += net_node->user_data_len;
}
config_put_u16(buf, net_node->pwd_len);
buf += sizeof(uint16_t);
if (net_node->pwd_len > 0) {
memcpy(buf, net_node->pwd, net_node->pwd_len);
buf += net_node->pwd_len;
}
config_put_u16(buf, net_node->hostlen_bootstrap);
buf += sizeof(uint16_t);
if ((net_node->hostlen_bootstrap & 0x0fff) > 0) {
memcpy(buf, (uint8_t *)net_node->host_data, net_node->hostlen_bootstrap & 0x0fff);
buf += (net_node->hostlen_bootstrap & 0x0fff);
}
config_put_u16(buf, net_node->user_data_len);
buf += sizeof(uint16_t);
if (net_node->user_data_len > 0) {
memcpy(buf, net_node->user_data, net_node->user_data_len);
buf += net_node->user_data_len;
}
offset = buf - start;
config_put_u16(start + 1, offset);
return offset;
}
/*******************************************************************************
* 函数名称:sys_node_parse
* 功能描述:系统调试信息解析
* 输入参数:sys_node - 传入系统调试信息数据指针
* buffer - 解析处理后存储缓冲区指针
* 返 回 值 : 返回数据长度.
******************************************************************************/
static int sys_node_parse(sys_node_t * sys_node, uint8_t * buffer)
{
uint8_t* buf = (uint8_t*)buffer;
uint8_t* start = (uint8_t*)buf;
uint16_t offset = 0;
*buf++ = (sys_node->cfgid & 0xff);
buf += sizeof(uint16_t);
*buf++ = sys_node->log_cfg;
config_put_u16(buf, sys_node->log_buf_size);
buf += sizeof(uint16_t);
config_put_u16(buf, sys_node->user_data_len);
buf += sizeof(uint16_t);
if (sys_node->user_data_len > 0) {
memcpy(buf, sys_node->user_data, sys_node->user_data_len);
buf += sys_node->user_data_len;
}
offset = buf - start;
config_put_u16(start + 1, offset);
return offset;
}
char cmd_buf[256];
short Nb_IPAddr[4]; //添加平台地址
short Nb_Port; //端口号
short NB_BootStarp; //接入方式
/*******************************************************************************
* 函数名称:miplconfig_generate
* 功能描述:入网MIPL信息配置发送,应用层只改bootstarp 以及 host ,
* 其他为默认,如有其他需要可自行修改
* 输入参数:None.
* 返 回 值 : SUCCESS : 成功,ERROR : 失败.
******************************************************************************/
BOOL miplconfig_generate(void)
{
int init_len = 0;
int net_len = 0;
int sys_len = 0;
int config_len = 0;
int head_len = 0;
int i = 0, count = 0;
uint8_t* pConfig = (uint8_t*)cmd_buf + 50; // 预留50字节
uint8_t* pbuf = (uint8_t*)cmd_buf + 50;
uint8_t *pSend = (uint8_t *)cmd_buf;
char host_addr[30] = {0};
int host_len = 0;
mipl_config_t mipl_config;
if (pbuf == NULL) return ERROR;
sprintf(host_addr, "%d.%d.%d.%d:%d", Nb_IPAddr[0], Nb_IPAddr[1],
Nb_IPAddr[2], Nb_IPAddr[3], Nb_Port);
host_len = strlen(host_addr);
mipl_config.head_node.head = (1 << 4) | 3;
mipl_config.init_node.cfgid = 0xf0 | cis_cfgid_init; /* 配置ID */
mipl_config.net_node.cfgid = 0xf0 | cis_cfgid_net; /* 配置ID */
mipl_config.net_node.mtu_len = 1024;
mipl_config.net_node.link_band = ((1 << 4) & 0xF0) | (1 & 0x0F);
mipl_config.net_node.apn_len = 0;
mipl_config.net_node.apn = NULL;
mipl_config.net_node.uname_len = 0;
mipl_config.net_node.uname = NULL;
mipl_config.net_node.pwd_len = 0;
mipl_config.net_node.pwd = NULL;
mipl_config.net_node.hostlen_bootstrap = ((NB_BootStarp << 12) | host_len);
mipl_config.net_node.host_data = host_addr;
mipl_config.net_node.user_data_len = 1;
mipl_config.net_node.user_data = "1";
mipl_config.sys_node.cfgid = 0xf0 | cis_cfgid_sys; /* 配置ID */
mipl_config.sys_node.log_cfg = 0;
mipl_config.sys_node.log_buf_size = 0;
mipl_config.sys_node.user_data_len = 0;
mipl_config.sys_node.user_data = NULL;
if (0 != mipconfig_legal(&mipl_config)) return ERROR;
memset(cmd_buf, 0, sizeof(cmd_buf));
head_len = head_node_parse(&mipl_config.head_node, pbuf);
pbuf += head_len;
init_len = init_node_parse(&mipl_config.init_node, pbuf);
pbuf += init_len;
net_len = net_node_parse(&mipl_config.net_node, pbuf);
pbuf += net_len;
sys_len = sys_node_parse(&mipl_config.sys_node, pbuf);
pbuf += sys_len;
config_len = head_len + init_len + net_len + sys_len;
config_put_u16(pConfig + 1, config_len);
sprintf((char *)pSend, "AT+MIPLCREATE=%d,", config_len);
count = strlen((char *)pSend);
for (i = 0; i < config_len; i++) {
m5310a_HexToAsc(pConfig[i], &pSend[i * 2+count]);
}
sprintf((char *)&pSend[i*2 + count], ",0,%d,0", config_len);
printf("pSend:%s\r\n", pSend);
return SUCCESS;
}