湖畔科技 发表于 2019-10-14 19:47:34

NB-IoT (BC35、BC26、BC28)模块移远BC35全网通接入OneNET平...

本帖最后由 湖畔科技 于 2019-10-14 19:56 编辑


网上很多NB-IOT模块的资料都是使用LWM2M、COAP协议去连接onenet平台
因为现在很多的NB-IOT模块都支持TCP协议,因此就想使用TCP协议然后转MQTT协议连接onenet平台,经过试验证明是可以的。
首先我们先分析一下如何登陆接入Onenet平台。
先从它数据格式开始分析。首先我们要从后台取出三个信息,我们以这个为例。
鉴权信息:test(具体的看你设置的)设备ID:123456789 产品ID:789123 (具体是什么看你自己的设备)
MQTT接入都是发十六进制的数据。
那么我们发送的时候就是这样子的一串数据<p>0x10 0x24 0x00 0x04 0x4D 0x51 0x54 0x54 0x04 0xC0 0x00 0x78 0x00 0x09 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x00 0x07 0x37 0x38 0x39 0x31 0x32 0x33 0x20 0x00 0x04 0x74 0x65 0x73 0x74
[ 0x10 ]   // MQTT类型=1DupFlag=0 QosLevel=0 Retain=0
[ 0x22 ]   // remainedLength=34以下的数据长度0x00 04......0x74 0x65 0x73 0x74这个之间的长度,您可以数一下看看</p><p>[ 0x00 0x04 ]   // protocolNameLength=4 这是发固定的MQTT这4个字母,长度为4.但是需要两个字节保存长度
[ 0x4D 0x51 0x54 0x54 ]   // protocolName=MQTT
[ 0x04 ]   // protocolLevel=4固定的一种类型
[ 0xC0 ]   // userFlag=1 passwordFlag=1 willFlag=0 willRetainFlag=0 willQosFlag=0 clenSessionFlag=0 clenSessionFlag=0固定的一种类型
[ 0x00 0x78 ]   // keepAlive=120这是保持连接的时间为120S
[ 0x00 0x08]   // clientIdentifierLen=8 这是设备ID的长度 用两个字节记录
[ 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 ]   // clientIdentifier=12345678 设备ID
[ 0x00 0x06 ]   // userNameLen=6 这是产品ID的长度 用两个字节记录
[ 0x37 0x38 0x39 0x31 0x32 0x33]   // userName=789123
[ 0x00 0x04 ]   // userPasswordLen=4 这是鉴权信息的长度 用两个字节记录
[ 0x74 0x65 0x73 0x74 ]   // userPassword=test</p>
这里面有个坑,长度的十六进制是十进制转换为十六进制。而“MQTT” ,test(具体的看你设置的)设备ID:123456789 产品ID:789123 这些信息都是字符串转十六进制
下面我们直接上指令
<p>AT
OK
AT+NRB//重启模块的指令,在单片机里面最好进行重启一下
AT+CMEE=1
OK
AT+CGSN=1
+CGSN:867725030027605
OK
AT+NBAND?
+NBAND:8 //移动的返回+NBAND:8,电信的返回+NBAND:5</p><p>OK
AT+NBAND=8 //设置为移动的,电信的指令为AT+NBAND=5
OK
AT+CIMI //查询卡号
460042437100213
OK
AT+CSQ //查询信号指令,如果返回+CSQ:99,99 说明还没有信号
+CSQ:29,99
OK
AT+NSOCR=STREAM,6,56000,1 //做TCP socket创建准备
AT+NSOCO=1,183.230.40.39,6002//连接服务器。6002为服务器端口号
OK</p>

注意:NB发送数据的时候数据内容需要转换为十六进制。大家可以使用在线转换工具
发送数据的指令为:AT+NSOSD=1,发送内容的长度,内容。//注意长度不可以多或者少
<p>AT+NSOSD=1,36,102200044D51545404C00078000831323334353637380006373839313233000474657374
这个时候已经连接上服务器了,那么现在就发送数据,原始数据如下
{"datastreams":[{"id":"temp","datapoints":[{"value":50}]}]}</p>

但是需要增加一些数据头之类的格式这是转换后的数据
下面我们开始发送数据到服务器AT+NSOSD=1,69,3043000324647001003B7B226461746173747265616D73223A5B7B226964223A2274656D70222C2264617461706F696E7473223A5B7B2276616C7565223A35307D5D7D5D7D
数据头的内容:



3043000324647001003B
数据头的含义
<p>30 // MQTT类型=3DupFlag=0 QosLevel=0 Retain=0
43 //remainedLength=67 即是本位以下的内容数据长度,是十进制的长度装16进制
0003// TopicNameLen=3
246470//TopicName=$dp
01//数据类型:数据类型1:Json数据1;一共有七种
003B//两位数据包长度,即发送内容的长度</p>

完整的步骤
<p>AT
OK
AT+NRB//重启模块的指令,在单片机里面最好进行重启一下
AT+CMEE=1
OK
AT+CGSN=1
+CGSN:867725030027605
OK
AT+NBAND?
+NBAND:8 //移动的返回+NBAND:8,电信的返回+NBAND:5</p><p>OK
AT+NBAND=8 //设置为移动的,电信的指令为AT+NBAND=5
OK
AT+CIMI //查询卡号
460042437100213
OK
AT+CSQ //查询信号指令,如果返回+CSQ:99,99 说明还没有信号
+CSQ:29,99
OK
AT+NSOCR=STREAM,6,56000,1 //做TCP socket创建准备
AT+NSOCO=1,183.230.40.33,6002//连接服务器。6002为服务器端口号
OK
AT+NSOSD=1,36,102200044D51545404C00078000831323334353637380006373839313233000474657374</p><p>OK
+NSONMI:1,4//这是服务器返回来的数据。
AT+NSORF=1,4//查询接收内容的指令203是需要查询的长度。可以多,
1,183.230.40.33,80,203,20200000,0</p><p>OK
AT+NSOSD=1,69,3043000324647001003B7B226461746173747265616D73223A5B7B226964223A2274656D70222C2264617461706F696E7473223A5B7B2276616C7565223A35307D5D7D5D7D</p>


附上C语言转十六进制函数
<p>int Str2Hex(char *str,char *hex)
{
      int high = 0;
      int low = 0;
      int temp = 0;</p><p>      if (NULL==str || NULL==hex){
                //printf("the str or hex is wrong\n");
                return -1;
      }</p><p>      if (0==strlen(str)){
                //printf("the input str is wrong\n");
                return -2;
      }</p><p>      while(*str)
      {
                temp = (int)(*str);
                high = temp>>4;
                low = temp & 15;
                *hex = Value2Hex(high);
                hex++;
                *hex = Value2Hex(low);
                hex++;
                str++;
      }
      *hex = '\0';
      return 0;
}</p>


附上发送MQTT连接服务器的数据及发送数据的格式化函数
<p>void ClearRAM(u8* ram,u32 n)
{
u32 i;
for (i = 0;i < n;i++)
{
    ram = 0x00;
}
}
//构建MQTT连接包
u16 mqtt_connect_message(char *mqtt_message,char *PROID,char *AUTH_INFO,char *DEVID)
{
//      char HTTP_Buf;   //HTTP报文缓存区
      char str;
      char strHEX;
      u16 PROID_length = strlen(PROID);
      u16 DEVID_length = strlen(DEVID);
      u16 AUTH_INFO_length = strlen(AUTH_INFO);
      u16 MQTT_length = strlen("MQTT");
      u16 packetLen;
      u16 i,baseIndex;
      ClearRAM((u8*)str,200);   //清空commandAT数据包缓存,发送命令包含ip端口和长度
      ClearRAM((u8*)strHEX,200); //清空locationHex数据包缓存,转换为hex 需要发送的真实数据
      packetLen = 12;//固定的数据头长度
      if(PROID_length > 0)
                packetLen = packetLen + 2 + PROID_length;
      if(DEVID_length > 0)
                packetLen = packetLen+ 2 + DEVID_length;
                if(AUTH_INFO_length > 0)
                packetLen = packetLen+ 2 + AUTH_INFO_length;
               
                strncpy((char*)(mqtt_message+strlen((char*)mqtt_message)),"10",2);
                sprintf(strHEX,"%02x",(packetLen-2));</p><p>                strcat(mqtt_message,strHEX);
                ClearRAM((u8*)str,200);   //清空commandAT数据包缓存,发送命令包含ip端口和长度
                ClearRAM((u8*)strHEX,200); //清空locationHex数据包缓存,转换为hex 需要发送的真实数据
                strcat(mqtt_message,"00044D51545404C00100");               
    //装载设备ID到数据包               
                sprintf(str, "%02x%02x",((0xff00&(DEVID_length))>>8),(0xff&DEVID_length));
                strcat(mqtt_message,str);
                ClearRAM((u8*)str,200);
                sprintf(str, "%s",DEVID);
                Str2Hex((char*)str,(char*)strHEX);
                strcat(mqtt_message,strHEX);      
                ClearRAM((u8*)str,200);
                ClearRAM((u8*)strHEX,200);
               //装载产品ID到数据包               
                sprintf(str, "%02x%02x",((0xff00&(PROID_length))>>8),(0xff&PROID_length));
                strcat(mqtt_message,str);
                ClearRAM((u8*)str,200);
                sprintf(str, "%s",PROID);
                Str2Hex((char*)str,(char*)strHEX);
                strcat(mqtt_message,strHEX);      
                ClearRAM((u8*)str,200);
                ClearRAM((u8*)strHEX,200);
          //装载产品ID到数据包               
                sprintf(str, "%02x%02x",((0xff00&(AUTH_INFO_length))>>8),(0xff&AUTH_INFO_length));
                strcat(mqtt_message,str);
                ClearRAM((u8*)str,200);
                sprintf(str, "%s",AUTH_INFO);
                Str2Hex((char*)str,(char*)strHEX);
                strcat(mqtt_message,strHEX);      
                ClearRAM((u8*)str,200);
                ClearRAM((u8*)strHEX,200);
                Str2Hex((char*)str,(char*)strHEX);
                strcat(mqtt_message,strHEX);
                strcat(mqtt_message,"\r\n");      
                return packetLen;   
}
//构建MQTT数据包
u16 mqtt_SendData_message(char *mqtt_messageHEX,char *SendData,short length)
{
                char str;
                char strHEX;
                u16 packetLen=length+8;
          u16 SendData_length = strlen(SendData);
          strncpy((char*)(mqtt_messageHEX+strlen((char*)mqtt_messageHEX)),"30",2);
                sprintf(strHEX,"%02x",(packetLen));
                strcat(mqtt_messageHEX,strHEX);
                ClearRAM((u8*)str,200);   //清空commandAT数据包缓存,发送命令包含ip端口和长度
                ClearRAM((u8*)strHEX,200); //清空locationHex数据包缓存,转换为hex 需要发送的真实数据
                strcat(mqtt_messageHEX,"01000324647001");      
            //装载json数据到数据包               
                sprintf(str, "%02x%02x",((0xff00&(SendData_length))>>8),(0xff&SendData_length));
                strcat(mqtt_messageHEX,str);
                ClearRAM((u8*)str,200);
                sprintf(str, "%s",SendData);
                Str2Hex((char*)str,(char*)strHEX);
                strcat(mqtt_messageHEX,strHEX);      
                ClearRAM((u8*)str,200);
                ClearRAM((u8*)strHEX,200);      
          return packetLen;   
}      </p>

MQTT ONEnet测试调试工具:https://www.amobbs.com/thread-5698272-1-1.html
Onenet平台MQTT协议数据包生成器:关注微信公众号“NNHPTCH”,南宁湖畔科技,回复“Onenet平台MQTT协议数据包生成器”

页: [1]
查看完整版本: NB-IoT (BC35、BC26、BC28)模块移远BC35全网通接入OneNET平...