模組註冊碼
移動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;
}