【eBox生态圈】移植超级火的MQTT物联网协议,进攻物联网

2019-12-11 18:36发布

本帖最后由 shentqlf 于 2015-11-24 01:28 编辑

这个互联网的年代,如果你不支持物联网就不要出来混啦!

科普:

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,将成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。
MQ 遥测传输 (MQTT) 是轻量级基于代理的发布/订阅的消息传输协议,设计思想是开放、简单、轻量、易于实现。这些特点使它适用于受限环境。例如,但不仅限于此:
●网络代价昂贵,带宽低、不可靠。
●在嵌入设备中运行,处理器和内存资源有限。
该协议的特点有:
使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。
●对负载内容屏蔽的消息传输。
●使用 TCP/IP 提供网络连接。
●有三种消息发布服务质量:
    ▲“至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
    ▲“至少一次”,确保消息到达,但消息重复可能会发生。
    ▲“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。
●小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量。
●使用 Last Will和 Testament 特性通知有关各方客户端异常中断的机制。
库文件:Embedded MQTT C/C++ Client Libraries
版本:移植的是目前最新稳定版本3.1.1
下载地址:http://git.eclipse.org/c/paho/or ... mbedded-c.git/refs/
在此网页的左下角有三个下载链接,文件格式不同而已,选择第一个。
移植简介:
初看MQTT库文件觉得不知道从哪里下手。第一步就是选取自己需要的文件,解压后会看到MQTTPacket文件夹,移植到新的平台,这个文件夹就够用了。MQTTClient这个文件夹下面有已经移植好的接口,是在Linux、arduino、mbed平台上运行的。没有支持eBox,说明eBox还不够火,那咱们就自己移植吧。
MQTTPacket文件夹下面有src文件夹。这个就是MQTT的核心代码,不用,也不要做任何修改。Samples文件夹下面的transport.c和.h是MQTT的基本数据传输函数。老外做的就是好,接口文件完全独立于本身的逻辑部分。transport.c这个文件就是移植的最重要部分!要实现基本的四个函数,只填充发送、接收、打开、关闭,不要对函数名称做任何修改,除了这四个函数外,用户也可以添加自己的接口,比如状态判断,需要初始化的东西。

在eBox平台下,我吧transport.c改为.cpp,这要做是为了能让他使用eBox自带的tcp协议,而不必再去基于socket实现传输函数的移植。这一步大大的简化了填充过程。上代码:

  1. #include "tcp.h"

  2. TCPCLIENT mqtt_tcp;
  3. //我自己添加的接口
  4. int transport_init(int local_sock,int local_port)
  5. {
  6.     mqtt_tcp.begin(local_sock,local_port);
  7.     return 0;
  8. }
  9. /*
  10. @return  sended data size for success else 0.
  11. */
  12. int transport_sendPacketBuffer(unsigned char* buf, int buflen)
  13. {
  14.         int rc = 0;
  15.     rc = mqtt_tcp.send(buf,buflen);
  16.         return rc;
  17. }

  18. /*
  19. @return  received data size for success else 0.
  20. [size=4][b]非阻塞式接收[/b],需要在应用层,做好循环控制。我选择这个模式,
  21. 主要是为了,让stm32除了干这个事情外还能兼顾其他的程序,如果使用阻塞式的就会产生长时间等待。[/size]
  22. */
  23. int transport_getdata(unsigned char* buf, int count)
  24. {
  25.         return mqtt_tcp.recv(buf,count);
  26. }
  27. ///*
  28. //@return  received data size for success else 0.
  29. [size=4]//[b]阻塞式接收[/b],用户不需要在应用层做循环控制。缺点就是STM32会一直傻傻的等着。。。[/size]
  30. //*/
  31. //int transport_getdata(unsigned char* buf, int count)
  32. //{
  33. ////×èÈûʽ½ÓÊÕ
  34. //    int rc = 0;
  35. //    uint32_t last_time = millis();
  36. //   
  37. //    while(rc == 0 ){
  38. //        rc = mqtt_tcp.recv(buf,count);       
  39. //        if(millis() - last_time > 1500)
  40. //            return 0;
  41. //        }
  42. //        return rc;
  43. //}

  44. /*
  45. @return  received data size for success else 0.
  46. 这个函数我没有调试,应用程序中使用不到
  47. */
  48. int transport_getdatanb(void *sck, unsigned char* buf, int count)
  49. {
  50.     int rc;
  51.     while(rc == 0)
  52.     {
  53.         rc = mqtt_tcp.recv(buf,count);
  54.     }
  55.         return rc;
  56. }

  57. /**
  58. return >=0 for a socket descriptor, <0 for an error code
  59. @todo Basically moved from the sample without changes, should accomodate same usage for 'sock' for clarity,
  60. removing indirections
  61. @return  1 for success else 0:time out.
  62. */
  63. int transport_open(char* addr, int port)
  64. {   
  65.         return mqtt_tcp.connect((unsigned char *)addr,port);   
  66. }
  67. /*
  68. @return  1 for success else 0:time out.
  69. */

  70. int transport_close(int sock)
  71. {
  72.     mqtt_tcp.stop();
  73.         return 1;
  74. }
  75. //我自己添加的接口
  76. int transport_connnected()
  77. {
  78.     return mqtt_tcp.is_connected();

  79. }
复制代码
写完这几个函数就可以,看官方提供的例程了。例程在samples文件夹下面。pub0sub1.c/qos0sub.c/pub0sub1_nb.c。打开之后,直接懵了。。。。。。。这是什么代码啊。。。


沉下心来,过一遍就能理解个大概了。多过几遍就没问题了。从这几个例程中了解他的一个基本的通信过程。然后把他这些例程,移植到eBox上就行了。这里要注意的是,官方默认为你的接收函数使用阻塞式接收,而我用的是非阻塞的,要再应用层上做点循环,do ...while。先移植publish(发布消息)。调试协议多了,就会明白发送是一个比接收容易一百倍的事情。过了一天,调通了。。。然后移植接收,又是一天。然后就是优化,两天时间。应用层的移植过程中还需要不断的修改底层的函数bug,中间找到了不少网卡和socket的bug。所以花了比较长的时间。涉及的内容太多,就不贴出来了,看附件就行了。
到此基本上实现了mqtt的qos0模式的发布和订阅消息。实现了断线自动重连。我用了两个eBox的板子,一个发布消息,一个订阅消息,运行一个晚上,第二天依然工作。没有断线。
调试工具:http://m2m.demos.ibm.com/mqttclient/#subscribe怎么是个网页呢?鄙人不会各种高大上的软件平台,就找到了网页版的客户端,然后通过他来调试自己发送的数据,接收的数据。还有一个eclipse平台的服务器m2m.eclipse.org,1883端口可以让用户调试。
强势插入两个图片
发布消息,每隔一段时间会给服务器发一个ping_req告诉服务器我还活着。。。
sub.png (4.32 KB, 下载次数: 0) 下载附件 订阅消息 2015-11-24 01:24 上传
移植好的文件,里面有mqtt的src文件和我自己的interface文件夹(包含了transport和应用层api)。用户把此文件夹放到eBox工程目录下的network文件夹下面。然后把代码添加到ebox工程中就可以了。

MQTTPacket.rar (36.82 KB, 下载次数: 142) 2015-11-24 00:40 上传 点击文件名下载附件
两个API使用的例程
eBox_mqtt_example.rar (2.22 KB, 下载次数: 127) 2015-11-24 00:52 上传 点击文件名下载附件
MQTT的全部文件
org.eclipse.paho.mqtt.embedded-c-1.0.0.zip (143.16 KB, 下载次数: 123) 2015-11-24 00:40 上传 点击文件名下载附件
MQTT_3.1.1中文手册
MQTT-3.1.1-CN.pdf (1.33 MB, 下载次数: 647) 2015-11-24 00:40 上传 点击文件名下载附件

这段时间,我并没有闲着,而是努力的完善eBox固件库,由于在此之间更新了网络的一些接口,老的版本固件库不能直接使用(缺少DNS解析),今天太晚了,明天更上来最新的工程文件
http://bbs.elecfans.com/jishu_527922_1_1.html
顺便加一句,在调试的过程中会遇到没有网络的情况,希望各位大神谁有MQTT协议的调试工具,就像串口调试助手那样的。给大家共享出来。
求Android平台工具
求Windows平台工具
当然要已经能直接安装的
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。