[size=15.3333px] 接上一篇【二姨家买单活动】之一:万物物联之NB模块牛刀小试 继续捣鼓BC26模块。
[size=15.3333px] 为了满足当下IoT应用的多样化需求,市面上开放了包括CoAP、XMPP和DDS在内的多种协议,可供各个应用场景按需选择。MQTT是IBM开发的一个即时通讯协议,基于TCP的,号称是可以支持所有的平台。CoAP是运行于UDP之上的,并且非常的小巧,最小只有4个字节。可以说两者都是营运物联网大趋势和为了适应M2M而生的,相比于其他的通信协议也有较大的优势。其中,消息队列遥测传输(MQTT)及其衍生协议MQTT-SN正广泛应用在日益普遍的低功耗广域(LPWA)网络中。MQTT,目前物联网的最主要的协议,基本所有的云平台都是基于MQTT协议,比如阿里云华为云,中国移动的oneNet、百度的云平台也都支持MQTT的接入
[size=15.3333px] 1、MQTT 协议
[size=15.3333px]作为一种轻量级协议,MQTT拥有简单紧凑的架构和较小的代码占用空间,适用于低成本、低功耗的IoT微控制设备。MQTT可在TCP/IP协议上兼容运行,专攻延迟较高、质量不佳的网络环境。该协议适用于具有以下通信需求的应用:
[size=15.3333px] 使用极小带宽
[size=15.3333px] 无线网络通信
[size=15.3333px] 低功耗
[size=15.3333px] 必要时保证高可靠性
[size=15.3333px] 对处理和内存资源的需求很低
[size=15.3333px] MQTT在IoT多种应用中都备受青睐,如智能表计、资产追踪工具和工业设备的互联传感器。凭借对有限带宽的高效利用,因此MQTT非常适用于网络成本高、功耗大的应用场景,例如远程传感器阵列就需要在现场自主运行数年且期间无需维修。MQTT是多个客户端通过一个中央服务器传递信息的多对多协议,能高效地将信息分发给一个或多个订阅者,加之其代码占用空间小,便使得MQTT成为移动应用通信的理想之选。
[size=15.3333px]
[size=15.3333px]2、MQTT 功能概述
[size=15.3333px] MQTT基于发布和订阅模型,而非“客户端-服务器”模型,它具有两个功能实体——MQTT服务器和MQTT客户端。IoT网络上的任何“事物”,无论是硬件设备还是软件程序,都可以视为MQTT的客户端。所有的客户端并非直接向彼此发布或订阅消息,而是向MQTT服务器所管理的“主题”来发布或订阅消息。“主题”可理解为电子邮件的收件箱;客户端向主题发布消息,订阅该主题的其他客户端都将收到该消息。MQTT服务器负责接收所有已发布的消息,并需要确保将其传输到所有订阅的客户端。消息根据多个商定的QoS级别进行发布。服务器还将对网络上的所有IoT设备进行验证。
[size=15.3333px]
[size=15.3333px]BC26模块:
[size=15.3333px]
[size=15.3333px] BC26 AT阿里云MQTT 核心指令
AT+CGPADDR=1
+CGPADDR: 1,100.91.141.117
OK
AT+QMTCFG="ALIAUTH",0,"a18dtRetCT0","BC26TEST","2oBrMJHjTlHbi8V1uoRGQZcC2SlKBXHE"
OK
AT+QMTOPEN=0,"iot-as-mqtt.cn-shanghai.aliyuncs.com",1883
OK
+QMTOPEN: 0,0
AT+QMTCONN=0,"BC26TEST"
OK
+QMTCONN: 0,0,0
AT+QMTSUB=0,1,"/a18dtRetCT0/BC26TEST/user/get",0
OK
+QMTSUB: 0,1,0,1
AT+QMTPUB=0,1,1,0,"/sys/a18dtRetCT0/BC26TEST/thing/event/property/post","{params:{IndoorTemperature:58.8}}"
OK
+QMTPUB: 0,1,0
一,在阿里云物联网平台新建产品和添加设备
阿里物联网平台连接https://account.aliyun.com/login/login.htm?oauth_callback=https%3A%2F%2Fiot.console.aliyun.com%2Fdevices&lang=zh
在后面接入设备时需要用到三要素:ProductKey,DeviceName,DeviceSecret
ProductKey会在新建产品时生成,DeviceName可以自己定义,应该是只支持英文和数字,DeviceSecret会在添加设备完成后自动生成。
二,设计产品上传数据结构
三 STM32 BC26 MQTT核心代码
#include "bc26.h"
#include "string.h"
#include "usart.h"
#include "wdg.h"
#include "led.h"
char *strx,*extstrx;
extern unsigned char RxBuffer[255],RxCounter;
BC26 BC26_Status;
#define ProductKey "a1dxl58BsE6" //²úÆ·KEY
#define DeviceName "m001" //
#define DeviceSecret "b9c04a0d041aa2eb8f2e5fd437ae7fd5" //
#define PubTopic "/sys/a1dxl58BsE6/m001/thing/event/property/post"//·¢²¼Ö÷Ìâ
#define SubTopic "/sys/a1NXoxeFw4c/mzh002/thing/service/property/set"//¶©ÔÄÖ÷Ìâ
void Clear_Buffer(void)//Çå¿Õ»º´æ
{
u8 i;
Uart1_SendStr((char*)RxBuffer);
for(i=0;i<100;i++)
RxBuffer[i]=0;//»º´æ
RxCounter=0;
IWDG_Feed();//ι¹·
}
void BC26_Init(void)
{
printf("AT\r\n");
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"OK");//·µ»ØOK
Clear_Buffer();
while(strx==NULL)
{
Clear_Buffer();
printf("AT\r\n");
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"OK");//·µ»ØOK
}
printf("AT+CFUN=1\r\n");//»ñÈ¡¿¨ºÅ£¬ÀàËÆÊÇ·ñ´æÔÚ¿¨µÄÒâ˼£¬±È½ÏÖØÒª¡£
delay_ms(300);
printf("AT+CIMI\r\n");//»ñÈ¡¿¨ºÅ£¬ÀàËÆÊÇ·ñ´æÔÚ¿¨µÄÒâ˼£¬±È½ÏÖØÒª¡£
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"460");//·µ460£¬±íÃ÷ʶ±ðµ½¿¨ÁË
Clear_Buffer();
while(strx==NULL)
{
Clear_Buffer();
printf("AT+CIMI\r\n");//»ñÈ¡¿¨ºÅ£¬ÀàËÆÊÇ·ñ´æÔÚ¿¨µÄÒâ˼£¬±È½ÏÖØÒª¡£
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"460");//·µ»ØOK,˵Ã÷¿¨ÊÇ´æÔÚµÄ
}
printf("AT+CGATT=1\r\n");//¼¤»îÍøÂ磬PDP
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"OK");//·µOK
Clear_Buffer();
printf("AT+CGATT?\r\n");//²éѯ¼¤»î״̬
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"+CGATT: 1");//·µ1
Clear_Buffer();
while(strx==NULL)
{
Clear_Buffer();
printf("AT+CGATT?\r\n");//»ñÈ¡¼¤»î״̬
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"+CGATT: 1");//·µ»Ø1,±íÃ÷×¢Íø³É¹¦
}
printf("AT+CESQ\r\n");//²é¿´»ñÈ¡CSQÖµ
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"+CESQ");//·µ»ØCSQ
if(strx)
{
BC26_Status.CSQ=(strx[7]-0x30)*10+(strx[8]-0x30);//»ñÈ¡CSQ
if((BC26_Status.CSQ==99)||((strx[7]-0x30)==0))//˵Ã÷ɨÍøʧ°Ü
{
while(1)
{
BC26_Status.netstatus=0;
Uart1_SendStr("ÐźÅËÑË÷ʧ°Ü£¬Çë²é¿´ÔÒò!\r\n");
delay_ms(300);//ûÓÐÐźž͸´Î»
}
}
else
{
BC26_Status.netstatus=1;
}
}
Clear_Buffer();
}
void BC26_ConTCP(void)
{
printf("AT+QICLOSE=0\r\n");//¹Ø±ÕsocektÁ¬½Ó
delay_ms(300);
Clear_Buffer();
IWDG_Feed();//ι¹·
}
void BC26_CreateTCPSokcet(void)//´´½¨sokcet
{
printf("AT+QIOPEN=1,0,\"TCP\",\"47.99.80.89\",14269,1234,1\r\n");//´´½¨Á¬½ÓTCP,ÊäÈëIPÒÔ¼°·þÎñÆ÷¶Ë¿ÚºÅÂë ,²ÉÓÃÖ±½ÓͳöµÄ·½Ê½
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"+QIOPEN: 0,0");//¼ì²éÊÇ·ñµÇ½³É¹¦
while(strx==NULL)
{
strx=strstr((const char*)RxBuffer,(const char*)"+QIOPEN: 0,0");//¼ì²éÊÇ·ñµÇ½³É¹¦
delay_ms(100);
}
Clear_Buffer();
}
void BC26_Senddata(uint8_t *len,uint8_t *data)//×Ö·û´®ÐÎʽ
{
printf("AT+QSOSEND=0,%s,%s\r\n",len,data);
}
void BC26_Senddatahex(uint8_t *len,uint8_t *data)//·¢ËÍÊ®Áù½øÖÆÊý¾Ý
{
printf("AT+QISENDEX=0,%s,%s\r\n",len,data);
delay_ms(300);
while(strx==NULL)
{
strx=strstr((const char*)RxBuffer,(const char*)"SEND OK");//¼ì²éÊÇ·ñ·¢Ëͳɹ¦
delay_ms(100);
}
Clear_Buffer();
}
void BC26_RECData(void)
{
}
void MQTT_Init(void)
{
printf("AT+QMTCFG=\"aliauth\",0,\"%s\",\"%s\",\"%s\"\r\n",ProductKey,DeviceName,DeviceSecret);
delay_ms(300);
printf("AT+QMTOPEN=0,\"139.196.135.135\",1883\r\n");//ͨ¹ýTCP·½Ê½È¥Á¬½ÓMQTT°¢ÀïÔÆ·þÎñÆ÷
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"+QMTOPEN: 0,0");//¿´Ï·µ»Ø״̬
while(strx==NULL)
{
strx=strstr((const char*)RxBuffer,(const char*)"+QMTOPEN: 0,0");//È·ÈÏ·µ»ØÖµÕýÈ·
}
Clear_Buffer();
printf("AT+QMTCONN=0,\"clientExample_1987\"\r\n");//È¥µÇ¼MQTT·þÎñÆ÷
delay_ms(300);
strx=strstr((const char*)RxBuffer,(const char*)"+QMTCONN: 0,0,0");//¿´Ï·µ»Ø״̬
while(strx==NULL)
{
strx=strstr((const char*)RxBuffer,(const char*)"+QMTCONN: 0,0,0");//¿´Ï·µ»Ø״̬
}
Clear_Buffer();
/*
printf("AT+QMTSUB=0,1,\"mzh_m26\",0\r\n");//¶©ÔĸöÖ÷Ìâ
delay_ms(500);
strx=strstr((const char*)RxBuffer,(const char*)"+QMTSUB: 0,1,0,0");//¶©Ôijɹ¦
while(strx==NULL)
{
strx=strstr((const char*)RxBuffer,(const char*)"+QMTSUB: 0,1,0,0");//¶©Ôijɹ¦
}
Clear_Buffer();
*/
}
void aliyunMQTT_PUBdata(u8 temp,u8 humi)
{
u8 t_payload[200],len;
printf("AT+QMTPUB=0,0,0,0,%s\r\n",PubTopic);//·¢²¼Ö÷Ìâ
delay_ms(300);
len=Mqttaliyun_Savedata(t_payload,temp,humi);
t_payload[len]=0;
printf("%s",t_payload);
while((USART2->SR&0X40)==0){}//Ñ»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï
USART2->DR = (u8) 0x1A;
delay_ms(100);
strx=strstr((const char*)RxBuffer,(const char*)"+QMTPUB: 0,0,0");//¿´Ï·µ»Ø״̬
while(strx==NULL)
{
strx=strstr((const char*)RxBuffer,(const char*)"+QMTPUB: 0,0,0");//¿´Ï·µ»Ø״̬
}
Clear_Buffer();
}
//·ÃÎÊ°¢ÀïÔÆÐèÒªÌá½»JSONÊý¾Ý
u8 Mqttaliyun_Savedata(u8 *t_payload,u8 temp,u8 humi)
{
char json[]="{\"id\":\"26\",\"version\":\"1.0\",\"params\":{\"CurrentTemperature\":{\"value\":%d},\"CurrentHumidity\":{\"value\":%d}},\"method\":\"thing.event.property.post\"}"; // char json[]="{\"datastreams\":[{\"id\":\"location\",\"datapoints\":[{\"value\":{\"lon\":%2.6f,\"lat\":%2.6f}}]}]}";
char t_json[200];
unsigned short json_len;
sprintf(t_json, json, temp, humi);
json_len = strlen(t_json)/sizeof(char);
memcpy(t_payload, t_json, json_len);
return json_len;
}
MQTT把数据传送到阿里云
代码见附件
BC26MQTT阿里云发模拟温湿度代码.rar
(3.99 MB)
MQTT 协议 3.1.1 中文版
MQTT-3.1.1-CN.pdf
(1.33 MB)
[size=15.3333px]
|