[文章]Niobe开发板MQTT联网演示

阅读量0
0
0
本案例程序将演示怎么在拓维Niobe WiFi IoT Core开发板上编写一个连接MQTT服务器的业务程序,实现开发板联网上报数据到服务器。
简述MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
MQTT协议中的方法MQTT协议中定义了一些方法(也被称为动作),来于表示对确定资源所进行操作。这个资源可以代表预先存在的数据或动态生成数据,这取决于服务器的实现。通常来说,资源指服务器上的文件或输出。主要方法有:
  • Connect。等待与服务器建立连接。
  • Disconnect。等待MQTT客户端完成所做的工作,并与服务器断开TCP/IP会话。
  • Subscribe。等待完成订阅。
  • UnSubscribe。等待服务器取消客户端的一个或多个topics订阅。
  • Publish。MQTT客户端发送消息请求,发送完成后返回。

特点
  • 开放消息协议,简单易实现
  • 发布订阅模式,一对多消息发布
  • 基于TCP/IP网络连接,提供有序,无损,双向连接。
  • 1字节固定报头,2字节心跳报文,最小化传输开销和协议交换,有效减少网络流量。
  • 消息QoS支持,可靠传输保证
    • “最多一次”,尽操作环境所能提供的最大努力分发消息。消息可能会丢失。例如,这个等级可用于环境传感器数据,单次的数据丢失没关系,因为不久之后会再次发送。
    • “至少一次”,保证消息可以到达,但是可能会重复。
    • “仅一次”,保证消息只到达一次。例如,这个等级可用在一个计费系统中,这里如果消息重复或丢失会导致不正确的收费。
  • 异常连接断开发生时,能通知到相关各方。
MQTT结构体详解
  1. typedef struct
  2. {
  3.         /** The eyecatcher for this structure.  must be MQTC. */
  4.         char struct_id[4];
  5.         /** The version number of this structure.  Must be 0 */
  6.         int struct_version;
  7.         /** Version of MQTT to be used.  3 = 3.1 4 = 3.1.1
  8.           */
  9.         unsigned char MQTTVersion;
  10.         MQTTString clientID;
  11.         unsigned short keepAliveInterval;
  12.         unsigned char cleansession;
  13.         unsigned char willFlag;
  14.         MQTTPacket_willOptions will;
  15.         MQTTString username;
  16.         MQTTString password;
  17. } MQTTPacket_connectData;
复制代码
主要代码分析
  1. static void MQTTDemoTask(void)
  2. {
  3.     // 连接WIFI
  4.     WifiConnect(SELECT_WIFI_SSID, SELECT_WIFI_PASSWORD);
  5.     printf("Starting ...n");
  6.     int rc, count = 0;
  7.     MQTTClient client;

  8.     // 初始化网络参数
  9.     NetworkInit(&network);
  10.     printf("NetworkConnect  ...n");
  11. begin:
  12.     // 连接服务器网络
  13.     NetworkConnect(&network, "123.60.8.120", 1883);
  14.     printf("MQTTClientInit  ...n");
  15.     // 初始化客户端
  16.     MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

  17.     // 连接参数
  18.     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
  19.     // 客户ID,唯一
  20.     data.clientID.cstring= "Talkweb";   
  21.     // 不使用临终遗言
  22.     data.willFlag = 0;
  23.     // MQTT版本号
  24.     data.MQTTVersion = 3;
  25.     // 保存存活时间
  26.     data.keepAliveInterval = 0;
  27.     // 重新连接后是否清除以前的信息 0表示不清除,1表示重连清除
  28.     data.cleansession = 1;
  29.     // 服务器用户名
  30.     data.username.cstring = "Talkweb";
  31.     // 服务器用户密码
  32.     data.password.cstring = "Talkweb1996";

  33.     printf("MQTTConnect  ...n");
  34.     // 登录服务器
  35.     rc = MQTTConnect(&client, &data);
  36.     // 失败处理
  37.     if (rc != 0) {
  38.         printf("MQTTConnect: %dn", rc);
  39.         NetworkDisconnect(&network);
  40.         MQTTDisconnect(&client);
  41.         osDelay(200);
  42.         goto begin;
  43.     }

  44.     printf("MQTTSubscribe  ...n");
  45.     // 订阅主题,并绑定回调函数处理接收到的消息
  46.     rc = MQTTSubscribe(&client, "pubtopic", 2, MessageArrived);
  47.     // 订阅失败处理
  48.     if (rc != 0) {
  49.         printf("MQTTSubscribe: %dn", rc);
  50.         osDelay(200);
  51.         goto begin;
  52.     }
  53.     while (count++) {
  54.         MQTTMessage message;
  55.         // 发布的内容
  56.         char payload[] = {"{"name": "Talkweb","url": "https://www.talkweb.com.cn/"}"};
  57.         // 仅一次
  58.         message.qos = 2;
  59.         message.retained = 0;
  60.         message.payload = payload;
  61.         message.payloadlen = strlen(payload);
  62.         // 发布
  63.         if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0) {
  64.             printf("Return code from MQTT publish is %dn", rc);
  65.             NetworkDisconnect(&network);
  66.             MQTTDisconnect(&client);
  67.             goto begin;
  68.         }
  69.         osDelay(100);
  70.     }
  71.    
  72. }
复制代码
编译
修改对接热点的账号密码修改mqtt_main.h第32行和33行的WiFi热点SSID和密码,改成自己环境中的WiFi热点。
  1. // 默认WiFi名和密码
  2. #define SELECT_WIFI_SSID "111"
  3. #define SELECT_WIFI_PASSWORD "0987654321"
复制代码



修改 BUILD.gn 文件修改 applications/app/BUILD.gn 路径中的 BUILD.gn 文件,指定 network_mqttclient_example 参与编译。
  1. # "TW208_Module_ds1307:module_ds1307_example",
  2. # "TW209_Module_gps:module_gps_example",
  3. # "TW301_Network_wifista:network_wifista_example",
  4. # "TW302_Network_wifiap:network_wifiap_example",
  5. "TW303_Network_mqttclient:network_mqttclient_example",
  6. # "TW304_Network_httpclient:network_httpclient_example",
  7. # "TW305_Network_ntpclient:network_ntpclient_example",
复制代码
运行结果
  1. Starting ...
  2. NetworkConnect  ...
  3. MQTTClientInit  ...
  4. MQTTConnect  ...
  5. MQTTSubscribe  ...
  6. wait for suback
  7. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
  8. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
  9. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
  10. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
  11. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
  12. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
  13. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
  14. Message arrived on topic pubtopic: {"code":-20,"desc":"appId cannot be empty"}
复制代码
自己搭建MQTT服务器,用于测试。测试步骤如下:1、下载apache-apollo-1.7.1搭建本地mqtt服务器,用于接入测试。工具使用参考:https://blog.csdn.net/yanyf2016/article/details/108057173。 2、获取本地IP地址,并把本地IP地址和端口61613替换案例中的地址。替换MQTTDemoTask函数中的NetworkConnect(&network, "123.60.8.120", 1883); 3、对应修改服务器用户名和密码,替换为apollo的默认用户名和密码:admin,password。 4、为了方便测试,可以把本地电脑,开发板连接同一个网络。 5、正常显示如下:
  1. NetworkConnect  ...                                                                                         
  2. MQTTClientInit  ...                                                                                       
  3. MQTTConnect  ...                                                                                             
  4. MQTTSubscribe  ...                                                                                          
  5. wait for suback                                                                                         
  6. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
  7. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
  8. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
  9. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
  10. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
  11. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
  12. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}                 
  13. Message arrived on topic pubtopic: {"name": "Talkweb","url": "https://www.talkweb.com.cn/"}
复制代码






回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友