NBIOT 移动M5310A模块 AT+MIPLCREATE注册码自动生成

模组注册码

移动M5310A模块固件中封装的SDK会自动获取模组当前的IMEI和IMSI用于ONENET平台登录,在ONENET平台需要使用当前设备的 IMEI 和 IMSI 进行设备注册。模组设备实体创建需要的配置数据,称为设备注册码。虽然有专门的软件生成注册码,但是不同平台接入或者接入方式有更改时,则需要重新生产注册码并更新程序,本文将生成注册码移植到程序中,只提供相应的接口修改。
注意:本流程使用的模组版本为CMVER:2.1.1.1809071028.

注册码详细信息

原始配置信息在config.xml文件中:

<?xml version="1.0" encoding="utf-8"?>
<config>
 	<item>
		 <version>1.0</version> //配置文件版本号
		 <cfgcnt>3</cfgcnt> //配置个数
 	</item>
 	<item id="1"></item>
 	<item id="2">
 		<data name="Mtu">1024</data> //最大传输单元大小
 		<data name="Linktype">1</data> //连接类型。默认配置为1
 		<data name="Bandtype">1</data> //网络类型,默认应设置为 1
 		<data name="APN"></data> //缺省,保持默认为空
 		<data name="Username"></data> //APN 用户名,保持默认为空
 		<data name="Password"></data> //APN 密码,保持认为空
 		<data name="Bootstrap">1</data> //接入方式,对接重庆平台默认应配置为 1,其他平台配置为 0
 		<data name="Host">nbiotbt.heclouds.com:5683</data> //平台地址
 		<data name="Userdata">AuthCode:12458789;</data> /*其他配置信息,以“key:value;”的组合形式构成,
 		如支持认证的 OneNET 接入方式配置为 AuthCode,value 为具体的 AuthCode 根据需求自行填写。如未设置
		AuthCode 无需填写*/
 	</item>
 	<item id="3">
 		<data name="LogEnabled">0</data> //调试开关,0 表示关闭调试模式,1 表示打开调试模式
 		<data name="LogExtOutput">0</data> //扩展信息开关,默认应设置为 1
 		<data name="LogOutputType">0</data> //日志输出模式,默认应设置为 3
 		<data name="LogOutputLevel">0</data> //日志输出调试级别,默认应设置为 1
 		<data name="LogBufferSize">0</data> //日志缓存长度,无效值
 		<data name="Userdata"></data> //如无需 OneNET 设备认证,该选项应缺省为空,否则应配置 AuthCode
 	</item>
	</config>

模组侧设备创建使用 AT+MIPLCREATE 指令,其指令格式为:

AT+MIPLCREATE=<totalsize>,<config>,<index>,<currentsize>,<flag>
//totalsize : 	指示<config>部分总数据长度,按照 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章