物联网--MQTT协议(九)讲:构建PUBLISH报文

MQTT协议系列文章:

[物联网–MQTT协议(一):MQTT协议简介

物联网–MQTT协议(二):MQTT协议组成介绍

物联网–MQTT协议(三):MQTT协议服务等级介绍

物联网–MQTT协议(四):构建CONNECT报文

物联网–MQTT协议(五):构建CONNACK、DISCONNECT报文

物联网–MQTT协议(六):构建PINGREQ、PINGRESP报文

物联网–MQTT协议(七):构建SUBSCRIBE、SUBACK报文

物联网–MQTT协议(八):构建UNSUBSCRIBE、UNSUBACK报文

由于前面的文章没同步在博客上,感兴趣的可以移步到微信公众号:南风过境蜻蜓飞 查看

MQTT协议共14个报文,前面给大家讲解了怎么构建 CONNECT、CONNACK、DISCONNECT、PINGREQ、PINGRESP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK 报文,今天继续给大家讲解构建 PUBLISH(发布消息)报文

一、准备工作

1.阿里云创建设备

已在阿里云上创建了一个设备,设备三元组为:

  {
    
    
     "ProductKey": "a1GOQO9ZBek",
     "DeviceName": "191106",
     "DeviceSecret": "wWo0xItypjQzrJQFlLpiITBjOGJhSLWE"
  }

2.网络调试助手的使用

MQTT协议的所有报文均是16进制表示,故需要进制转换,进制转换工具可以直接使用网络调试助手,即可转换为16进制,并得到转换数据的大小,操作如下:


  • 输入需要转换的数据时,结束的地方不能多有空格,否则转换过后的数据也会包含空格,导致出错

  • 发送完成一次数据之后记得复位计数(右下角),且把按十六进制发送的√取消掉再进行下一次数据转换,否则会数据累加,导致出错

3.阿里云产品添加功能定义

登录阿里云物联网平台,找到本项目创建的产品,进入产品详情界面

根据自己需求添加产品功能(此处若我们选择上传当前的室内人数,可自己定义)

完成之后确认,点击发布上线,即可在页面上看到我们刚添加的产品功能

4.获取设备的发布主题

登录阿里云物联网平台,找到本项目创建的产品,进入产品详情界面

将 /sys/a1GOQO9ZBek/${deviceName}/thing/event/property/post 中的 ${deviceName} 修改为我们本次项目创建的设备,即得到设备的发布主题:/sys/a1GOQO9ZBek/191106/thing/event/property/post

二、PUBLISH(发布消息)报文

PUBLISH(发布消息)报文就是指从客户端向服务端或者服务端向客户端传输一个应用消息,PUBLISH 报文由固定报头、可变报头、有限负载组成。本节将在已连接上阿里云的基础上通过PUBLISH发送数据到阿里云。

1.固定报头

MQTT协议的 PUBLISH 报文的固定报头数据如下:

MQTT协议规定,对于 QoS0 的消息, DUP 标志必须设置为 0,此处我们发送的数据为 QoS 0的服务器消息,故QoS及DUP均为0,设置RETAIN(保留标志位)为0,服务端不存储这个消息也不移除或替换任何现存的保留消息,剩余长度的值暂定为:XX

MQTT协议的 PUBLISH 报文固定报头为:30 XX

2.可变报头

MQTT协议的 PUBLISH 报文的可变报头按顺序包含主题名和报文标识符

MQTT协议手册给的一个案例(示例中的主题名为 “a/b”, 长度等于 3, 报文标识符为 “10”):

主题名(Topic Name) 用于识别有效载荷数据应该被发布到哪一个信息通道,即云端的设备发布主题,根据

而对于报文标识符,MQTT协议规定,只有当 QoS 等级是 1 或 2 时,报文标识符(Packet Identifier) 字段才能出现在 PUBLISH 报文中,故我们的可变报头中只包含主题名

设备的发布主题为:/sys/a1GOQO9ZBek/191106/thing/event/property/post,转换为16进制为:2F 73 79 73
2F 61 31 47 4F 51 4F 39 5A 42 65 6B 2F 31 39 31 31 30 36 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74,长度为49个字节,将49转换为16进制为31

得到MQTT协议的 PUBLISH 报文可变报头为:00 31 2F 73 79 73 2F 61 31 47 4F 51 4F 39 5A 42 65 6B 2F 31 39 31 31 30 36 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74

3.解析云端下发数据

MQTT协议的 PUBLISH 报文的有效载荷包含将被发布的应用消息,数据的内容和格式是应用特定的。由于我们不知道阿里云发送数据的具体格式,故我们可以通过参考阿里云下发的数据格式,从而得到发送数据到阿里云的有效载荷格式

使用网络调试助手,在通过CONNECT报文连接上阿里云之后,用SUBSCRIBE报文订阅服务器的主题topic,就能收到从服务器下发的数据

  • CONNECT报文连接上阿里云
  • SUBSCRIBE报文订阅服务器主题
  • 阿里云下发数据

从网络调试助手看到,接收到的服务器下发的数据为:30 90 01 00 32 2F 73 79 73 2F 61 31 47 4F 51 4F 39 5A 42 65 6B 2F 31 39 31 31 30 36 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 38 35 31 35 37 36 38 37 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 6E 75 6D 22 3A 36 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D

  • 根据MQTT协议,对这一长串的16进制数进行解析,计算得到长度为147,除去固定报头之后长度大于127,根据MQTT协议的 剩余长度字段大小的表示方法,知道大于长度127的字段用两个字节表示

  • 故该数据的固定报头为:30 90 01

  • 00 32 为可变报头的长度,32转换为10进制为50,说明可变报头有50个字节,从00 32开始,取50个字节数据,得到该数据可变报头:2F 73 79 73 2F 61 31 47 4F 51 4F 39 5A 42 65 6B 2F 31 39 31 31 30 36 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 7B 22 6D 65 74,通过网络调试助手转换为字符:/sys/a1GOQO9ZBek/191106/thing/service/property/set,即是使用SUBSCRIBE报文订阅的主题

  • 除去固定报头,可变报头,剩下部分即为有效载荷:7B 22 6D 65 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 38 35 31 35 37 36 38 37 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 6E 75 6D 22 3A 36 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D,通过网络调试助手转换为字符格式:{“mehod”:“thing.service.property.set”,“id”:“85157687”,“params”:{“num”:6},“version”:“1.0.0”},该字符串即为发送数据到阿里云的有效载荷格式,我们只需要将{“num”:6}里面的标识符和值更换为我们所需要传输的数据

3.有效负载

MQTT协议的 PUBLISH 报文的有效载荷包含将被发布的应用消息,根据上文,有效载荷的格式为:{“mehod”:“thing.service.property.set”,“id”:“85157687”,“params”:{“num”:6},“version”:“1.0.0”}

假设我们需要传输的数据标识符为num,值为99,则有效载荷为:{“mehod”:“thing.service.property.set”,“id”:“85157687”,“params”:{“num”:99},“version”:“1.0.0”}

将有效载荷转换为16进制,即可得到MQTT协议的 PUBLISH 报文的有效载荷:7B 22 6D 65 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 38 35 31 35 37 36 38 37 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 6E 75 6D 22 3A 39 39 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D

4.计算剩余长度

根据上文,得到构造的PUBLISH 报文:30 XX 00 31 2F 73 79 73 2F 61 31 47 4F 51 4F 39 5A 42 65 6B 2F 31 39 31 31 30 36 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 7B 22 6D 65 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 38 35 31 35 37 36 38 37 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 6E 75 6D 22 3A 39 39 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D (XX表示剩余长度)

计算XX后面数据的字节大小,共占143个字节,大于128个字节,根据MQTT协议的 剩余长度字段大小的表示方法,应该用两个字节表示剩余长度字段大小,143减128为15,将15转换为16进制为0F(0000 1111),根据协议规定的剩余长度字段大小表示法,剩余长度的大小为8F 01(1000 1111 0000 0001)

故完整的PUBLISH 报文为:30 8F 01 00 31 2F 73 79 73 2F 61 31 47 4F 51 4F 39 5A 42 65 6B 2F 31 39 31 31 30 36 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 7B 22 6D 65 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 38 35 31 35 37 36 38 37 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 6E 75 6D 22 3A 39 39 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D

四、测试报文

网络调试助手中发送 物联网–MQTT协议(四):构建CONNECT报文构建 中构建好的CONECT报文,可以看到返回:20 02 00 00,说明CONNECT连接被服务端接受,连接上云端设备,再发送构建好的PUBLISH报文,若TCP Client没有断开连接,则证明构建的报文没有错误

在阿里云物联网平台设备详情界面能看到网络调试助手发送的数据

笔者知识有限,如果发现本文有错误的地方欢迎批评、指正,若本文对您有所帮助,转发、分享也是笔者坚持的动力

猜你喜欢

转载自blog.csdn.net/qq_42965739/article/details/107701923
今日推荐