微信小程序使用MQTT远程控制单片机——MQTT控制报文③

DISCONNECT ——断开连接

固定报头

报文则为:E0 00
在这里插入图片描述

可变报头

DISCONNECT报文没有可变报头。

有效载荷

DISCONNECT报文没有有效载荷。

响应

客户端发送DISCONNECT报文之后:

  • 必须关闭网络连接
  • 不能通过那个网络连接再发送任何控制报文

服务端在收到DISCONNECT报文时:

  • 必须丢弃任何与当前连接关联的未发布的遗嘱消息
  • 应该关闭网络连接,如果客户端 还没有这么做。

测试

我们先连接上阿里云,
在这里插入图片描述
在这里插入图片描述
测试成功

PINGREQ——心跳请求

客户端发送PINGREQ报文给服务端的。用于:

在没有任何其它控制报文从客户端发给服务的时,告知服务端客户端还活着。
请求服务端发送 响应确认它还活着。
使用网络以确认网络连接没有断开。
保持连接(Keep Alive)处理中用到这个报文

固定报头

总报文为:C0 00
在这里插入图片描述

可变报头

PINGREQ报文没有可变报头。

有效载荷

PINGREQ报文没有有效载荷。

响应

服务端必须发送 PINGRESP报文响应客户端的PINGREQ报文

测试

在这里插入图片描述

SUBSCRIBE - 订阅主题

客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。每个订阅注册客户端关心的一个或多个主题。为了将应用消息转发给与那些订阅匹配的主题,服务端发送PUBLISH报文给客户端。SUBSCRIBE报文也(为每个订阅)指定了最大的QoS等级,服务端根据这个发送应用消息给客户端。

SUBSCRIBE报文固定报头

固定报文转化为十六进制为:82 xx
在这里插入图片描述

SUBSCRIBE控制报固定报头的第3,2,1,0位是保留位,必须分别设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接 [MQTT-3.8.1-1]。

剩余长度字段
因为剩余长度是可变报头的长度(2字节)加上有效载荷的长度。所以这里的报文还不知道用xx代替

可变报头

报文标识符等于10的可变报头即:00 0A(十六进制)

报文标识符就相当于ID

在这里插入图片描述

有效载荷

SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表,它们表示客户端想要订阅的主题。。服务端应该支持包含通配符的主题过滤器。如果服务端选择不支持包含通配符的主题过滤器,必须拒绝任何包含通配符过滤器的订阅请求 。每一个过滤器后面跟着一个字节,这个字节被叫做 服务质量要求(Requested QoS)。它给出了服务端向客户端发送应用消息所允许的最大QoS等级。

SUBSCRIBE报文的有效载荷必须包含至少一对主题过滤器 和 QoS等级字段组合。没有有效载荷的SUBSCRIBE报文是违反协议的

请求的最大服务质量等级字段编码为一个字节,它后面跟着UTF-8编码的主题名,那些主题过滤器 /和QoS等级组合是连续地打包。

在这里插入图片描述

当前版本的协议没有用到服务质量要求(Requested QoS)字节的高六位。如果有效载荷中的任何位是非零值,或者QoS不等于0,1或2,服务端必须认为SUBSCRIBE报文是不合法的并关闭网络连接。

看不懂就直接看我操作,其实我也看不懂个,我只是看了老师教学视频而已,他也没咋将,就讲操作。

第一,主题过滤器表示的是客户端需要订阅的主题,这里是订阅阿里云里的设备主题。然后转化为十六进制:2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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。我还需要计算这个十六进制的长度这里是48个自己转化为十六进制为 00 30,这个字节长度要放到主题过滤器前面也就是:00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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
注意:里面的deviceName必须要把自己的设备名称带进去,我的是Z001
在这里插入图片描述
在这里插入图片描述

第二,服务质量要求,其实就是选择服务质量等级
在这里插入图片描述
我们一般选择服务等级0,所以为 00,如果等级选择1那就是01
所以整个负载报文为:00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 00

SUBSCRIBE总报文

所以我们这个SUBSCRIBE-订阅主题的报文为:82 xx 00 0A 00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 00,哦对还要计算剩余长度,也就是可变报头跟有效负载的长度为35,所以完整报文为82 35 00 0A 00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 00 这样我们就够建好了SUBSCRIBE的订阅。

上机测试,测试成功
在这里插入图片描述

SUBACK 订阅确定

服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。

SUBACK报文包含一个返回码清单,它们指定了SUBSCRIBE请求的每个订阅被授予的最大QoS等级。

上面,我们订阅了阿里云上的设备主题,回复了几个字节90 03 00 0A 01我们就讲解各为什么意思

固定报头

在这里插入图片描述

可变报头包含等待确认的SUBSCRIBE报文的报文标识符,这里十六进制字节表示为 90,剩余字节数用xx表示

可变报头

可变报头包含等待确认的SUBSCRIBE报文的报文标识符,这里的标识符就是上面SUBSCRIBE里可变报头所说的 00 0A,这个标识符是可变的,只要在SUBSCRIBE设置标识符,这里的SUBACK 就会跟随变化
在这里插入图片描述

有效载荷

有效载荷包含一个返回码清单。每个返回码对应等待确认的SUBSCRIBE报文中的一个主题过滤器。返回码的顺序必须和SUBSCRIBE报文中主题过滤器的顺序相同
在这里插入图片描述
我们设置的等级为0,理应回复00,为什么回复的是01呢?,因为阿里云的话,不管是等于0 还是等于1,回复的都是01

UNSUBSCRIBE –取消订阅

客户端发送UNSUBSCRIBE报文给服务端,用于取消订阅主题。

固定报头

固定报头报文为:A2 xx
在这里插入图片描述
UNSUBSCRIBE报文固定报头的第3,2,1,0位是保留位且必须分别设置为0,0,1,0。服务端必须认为任何其它的值都是不合法的并关闭网络连接
剩余长度字段

等于可变报头的长度加上有效载荷的长度。用xx表示

可变报头

可变报头包含一个报文标识符

在这里插入图片描述
这里的标识符是为SUBSCRIBE里设置的标识符一样的为00 0A

有效载荷

UNSUBSCRIBE报文的有效载荷包含客户端想要取消订阅的主题过滤器列表。UNSUBSCRIBE报文中的主题过滤器必须是连续打包的。

UNSUBSCRIBE报文的有效载荷必须至少包含一个消息过滤器。没有有效载荷的UNSUBSCRIBE报文是违反协议的 。

有效载荷字节格式非规范示例

在这里插入图片描述

有效载荷报文

我们先换算阿里云的订阅主题为十六进制,即00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 ,注意前面两个字节00 30是订阅主题的十六进制长度
在这里插入图片描述

响应

UNSUBSCRIBE报文提供的主题过滤器(无论是否包含通配符)必须与服务端持有的这个客户端的当前主题过滤器集合逐个字符比较。如果有任何过滤器完全匹配,那么它(服务端)自己的订阅将被删除,否则不会有进一步的处理。

如果服务端删除了一个订阅:

  • 它必须停止分发任何新消息给这个客户端
  • 它必须完成分发任何已经开始往客户端发送的QoS 1和QoS 2的消息
  • 它可以继续发送任何现存的准备分发给客户端的缓存消息。

服务端必须发送UNSUBACK报文响应客户端的UNSUBSCRIBE请求。UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符 。即使没有删除任何主题订阅,服务端也必须发送一个UNSUBACK响应

如果服务端收到包含多个主题过滤器的UNSUBSCRIBE报文,它必须如同收到了一系列的多个UNSUBSCRIBE报文一样处理那个报文,除了将它们的响应合并到一个单独的UNSUBACK报文外。

UNSUBSCRIBE 总报文

总报文为:A2 xx 00 0A 00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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。把剩余长度计算出得34 即:A2 34 00 0A 00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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

测试

测试成功
在这里插入图片描述

UNSUBACK – 取消订阅确认

这里回复的几个字节B0 02 00 0A是什么意思呢
在这里插入图片描述

固定报头

换算为十六进制也就是B0
在这里插入图片描述
剩余长度字段,表示可变报头的长度,对UNSUBACK报文这个值等于2

可变报头

可变报头包含等待确认的UNSUBSCRIBE报文的报文标识符。也就是00 0A

有效载荷

UNSUBACK报文没有有效载荷。

PUBLISH – 发布消息

PUBLISH控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。

在这里插入图片描述

固定报头

a. 重发标志DUP

位置:第1个字节,第3位

如果DUP标志被设置为0,表示这是客户端或服务端第一次请求发送这个PUBLISH报文。如果DUP标志被设置为1,表示这可能是一个早前报文请求的重发。

  • 客户端或服务端请求重发一个PUBLISH报文时,必须将DUP标志设置为1,对于QoS 0的消息,DUP标志必须设置为0

  • 服务端发送PUBLISH报文给订阅者时,收到(入站)的PUBLISH报文的DUP标志的值不会被传播。发送(出站)的PUBLISH报文与收到(入站)的PUBLISH报文中的DUP标志是独立设置的,它的值必须单独的根据发送(出站)的PUBLISH报文是否是一个重发来确定

b. 服务质量等级 QoS

第1个字节,第2-1位。

这个字段表示应用消息分发的服务质量等级保证。服务质量等级
在这里插入图片描述
PUBLISH报文不能将QoS所有的位设置为1。如果服务端或客户端收到QoS所有位都为1的PUBLISH报文,它必须关闭网络连接

c. 保留标志 RETAIN

位置:第1个字节,第0位。

  • 如果客户端发给服务端的PUBLISH报文的保留(RETAIN)标志被设置为1,服务端必须存储这个应用消息和它的服务质量等级(QoS),以便它可以被分发给未来的主题名匹配的订阅者 。一个新的订阅建立时,对每个匹配的主题名,如果存在最近保留的消息,它必须被发送给这个订阅者 。如果服务端收到一条保留(RETAIN)标志为1的QoS 0消息,它必须丢弃之前为那个主题保留的任何消息。它应该将这个新的QoS 0消息当作那个主题的新保留消息,但是任何时候都可以选择丢弃它 — 如果这种情况发生了,那个主题将没有保留消息。

  • 服务端发送PUBLISH报文给客户端时,如果消息是作为客户端一个新订阅的结果发送,它必须将报文的保留标志设为1 。当一个PUBLISH报文发送给客户端是因为匹配一个已建立的订阅时,服务端必须将保留标志设为0,不管它收到的这个消息中保留标志的值是多少

  • 保留标志为1且有效载荷为零字节的PUBLISH报文会被服务端当作正常消息处理,它会被发送给订阅主题匹配的客户端。此外,同一个主题下任何现存的保留消息必须被移除,因此这个主题之后的任何订阅者都不会收到一个保留消息 。当作正常 意思是现存的客户端收到的消息中保留标志未被设置。服务端不能存储零字节的保留消息 。

  • 如果客户端发给服务端的PUBLISH报文的保留标志位0,服务端不能存储这个消息也不能移除或替换任何现存的保留消

固定报头的报文

  • 所以这里的报文字节为:30 xx,xx为剩余字节
  • 剩余长度等于可变报头的长度加上有效载荷的长度。
    在这里插入图片描述

可变报头

可变报头按顺序包含主题名和报文标识符。

①主题名 Topic Name

  • 主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。

  • 主题名必须是PUBLISH报文可变报头的第一个字段。

  • PUBLISH报文中的主题名不能包含通配符。

  • 服务端发送给订阅客户端的PUBLISH报文的主题名必须匹配该订阅的主题过滤器

②报文标识符 Packet Identifier

  • 只有当QoS等级是1或2时,报文标识符(Packet Identifier)字段才能出现在PUBLISH报文中
  • 注意,因为之前我们设置是为0,所以此次不设置

③PUBLISH报文可变报头非规范示例

在这里插入图片描述

可变报头总报文

在阿里云的发布主题,也就是这个,转化为十六进制为:2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 ,再加上长度、标识符啥的,则为00 2F 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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
在这里插入图片描述
注意这里的${deviceName}要替换成你的设备

有效载荷

有效载荷包含将被发布的应用消息。数据的内容和格式是应用特定的。有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的PUBLISH报文是合法的。

有效载荷主要的是发送我们数据,但是这个数据是有数据格式的,我们应该案例云的阿里云的数据格式来。

①、首先让阿里云设置一个电源关的指令
在这里插入图片描述

②、然后再串口调试助手获取它的数据
在这里插入图片描述

30 97 01 00 30 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 35 39 35 39 35 37 32 36 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 22 3A 30 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D
第一个字节是固定报头,第二三个字节是剩余长度,第三四个字节是可变包头的主题名的数据长度,我们可以这个长度十进制的48,所以后面的四十八个字节都是主题名,也就是2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 转化为字符串,也就是/sys/a1XshtsktJV/Z001/thing/service/property/set,这个是阿里云下发的topic
后面的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 35 39 35 39 35 37 32 36 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 22 3A 30 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D这个就是阿里云下发的数据{"method":"thing.service.property.set","id":"595957261","params":{"PowerSwitch":0},"version":"1.0.0"}这里的id’是可以更改的。

这些是服务端到发布消息到客户端,那么客户端发布消息到服务端也是一样的数据格式。{"method":"thing.service.property.set","id":"000000111","params":{"PowerSwitch":1},"version":"1.0.0"}。转化为十六进制就是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 30 30 30 30 30 30 31 31 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 22 3A 31 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D

响应

PUBLISH报文的接收者必须按照根据PUBLISH报文中的QoS等级发送响应,见下面表格的描述。
在这里插入图片描述

动作 Actions

  • 客户端使用PUBLISH报文发送应用消息给服务端,目的是分发到其它订阅匹配的客户端。

  • 服务端使用PUBLISH报文发送应用消息给每一个订阅匹配的客户端。

  • 客户端使用带通配符的主题过滤器请求订阅时,客户端的订阅可能会重复,因此发布的消息可能会匹配多个过滤器。对于这种情况,服务端必须将消息分发给所有订阅匹配的QoS等级最高的客户端。服务端之后可以按照订阅的QoS等级,分发消息的副本给每一个匹配的订阅者。

  • 收到一个PUBLISH报文时,接收者的动作取决于4.3节描述的QoS等级。

  • 如果服务端实现不授权某个客户端发布PUBLISH报文,它没有办法通知那个客户端。它必须按照正常的QoS规则发送一个正面的确认,或者关闭网络连接

总报文

所以,现在我们就能写一个完整的发布消息的报文。
总报文 = 固定报头 + 可变报头 + 有效载荷,即30 xx 00 2F 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 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 30 30 30 30 30 30 31 31 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 22 3A 31 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D把剩余长度计算出来,最终得到30 96 01 00 2F 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 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 30 30 30 30 30 30 31 31 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 22 3A 31 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D

验证一下,最终在云端收到我们的数据表明,我们的报文发布成功
在这里插入图片描述

在这里插入图片描述

当然,同时我们可以上传我们温湿度的值

  • 首先我们要找到他的温湿度的标识符
  • 在这里插入图片描述
    然后修改数据格式的值:{"method":"thing.service.property.set","id":"000000111","params":{"CurrentHumidity":34,"CurrentTemperature":28.55},"version":"1.0.0"}。转化为十六进制: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 30 30 30 30 30 30 31 31 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 43 75 72 72 65 6E 74 48 75 6D 69 64 69 74 79 22 3A 33 34 2C 22 43 75 72 72 65 6E 74 54 65 6D 70 65 72 61 74 75 72 65 22 3A 32 38 2E 35 35 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D。所以我们最终发布报文为30 B6 01 00 2F 2F 73 79 73 2F 61 31 58 73 68 74 73 6B 74 4A 56 2F 5A 30 30 31 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 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 30 30 30 30 30 30 31 31 31 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 43 75 72 72 65 6E 74 48 75 6D 69 64 69 74 79 22 3A 33 34 2C 22 43 75 72 72 65 6E 74 54 65 6D 70 65 72 61 74 75 72 65 22 3A 32 38 2E 35 35 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D,注意这里的剩余长度需要修改,因为有效载荷字节长度发生变化。

在这里插入图片描述

持续更新

微信小程序使用MQTT远程控制单片机——阿里云物联网平台①

微信小程序使用MQTT远程控制单片机——MQTT控制报文②

微信小程序使用MQTT远程控制单片机——MQTT控制报文③
学习视频
该博文为个人学习笔记记录,由于知识量储备不够若有错误之处或者补充,请各位大佬批评指正,持续更新中……

  • 13
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值