1.MQTT基本概念
MQTT 协议入门:基础知识和快速教程-阿里云开发者社区 (aliyun.com)
1.1MQTT定义
MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受欢迎,能够实现传感器、执行器和其它设备之间的高效通信。
1.2MQTT原理
MQTT 客户端、MQTT Broker、发布-订阅模式、主题、QoS
-
MQTT 客户端:任何运行 MQTT 客户端库的应用或设备都是 MQTT 客户端。例如,使用 MQTT 的即时通讯应用是客户端,使用 MQTT 上报数据的各种传感器是客户端,各种 MQTT 测试工具也是客户端。
-
MQTT Broker:MQTT Broker 是负责处理客户端请求的关键组件,包括建立连接、断开连接、订阅和取消订阅等操作,同时还负责消息的转发。
-
发布-订阅模式:发布-订阅模式与客户端-服务器模式的不同之处在于,它将发送消息的客户端(发布者)和接收消息的客户端(订阅者)进行了关联。发布者和订阅者之间无需建立直接连接,而是通过 MQTT Broker 来负责消息的路由和分发。
-
下图展示了 MQTT 发布/订阅过程。温度传感器作为客户端连接到 MQTT Broker,并通过发布操作将温度数据发布到一个特定主题(例如
Temperature
)。MQTT Broker 接收到该消息后会负责将其转发给订阅了相应主题(Temperature
)的订阅者客户端。
-
-
主题:MQTT 协议根据主题来转发消息。主题通过
/
来区分层级,类似于 URL 路径,例如:chat/room/1 sensor/10/temperature sensor/+/temperature
MQTT 主题支持以下两种通配符:
+
和#
。+
:表示单层通配符,例如a/+
匹配a/x
或a/y
。#
:表示多层通配符,例如a/#
匹配a/x
、a/b/c/d
。
注意:通配符主题只能用于订阅,不能用于发布。
-
QoS:MQTT 提供了三种服务质量(QoS),在不同网络环境下保证消息的可靠性。
- QoS 0:消息最多传送一次。如果当前客户端不可用,它将丢失这条消息。
- QoS 1:消息至少传送一次。
- QoS 2:消息只传送一次。
1.3MQTT工作流程
- 客户端使用 TCP/IP 协议与 Broker 建立连接,可以选择使用 TLS/SSL 加密来实现安全通信。客户端提供认证信息,并指定会话类型(Clean Session 或 Persistent Session)。
- Clean Session:MQTT 客户端通常只能在在线状态下接收其它客户端发布的消息。如果客户端离线后重新上线,它将无法收到离线期间的消息。但是,如果客户端连接时设置 Clean Session 为 false,并且使用相同的客户端 ID 再次上线,那么消息服务器将为客户端缓存一定数量的离线消息,并在它重新上线时发送给它。
- 客户端既可以向特定主题发布消息,也可以订阅主题以接收消息。当客户端发布消息时,它会将消息发送给 MQTT Broker;而当客户端订阅消息时,它会接收与订阅主题相关的消息。
- MQTT Broker 接收发布的消息,并将这些消息转发给订阅了对应主题的客户端。它根据 QoS 等级确保消息可靠传递,并根据会话类型为断开连接的客户端存储消息。
2.使用MQTTX在阿里云上模拟两个设备的通信
2.1前言
为了更好的进行过程的描述,我通过实例来进行演示,同时也会涉及一些原理的讲解。
为什么要用MQTTX模拟两个物理设备通信?该blog是我在学习嵌入式设备联网的过程中写下的,使用嵌入式模块上传和接收数据之前得熟悉阿里云以及MQTT协议的使用。
2.2过程
2.2.1阿里云产品和设备创建
首先我在阿里云上创建了产品Camera
(创建过程就不详细说明了)
在产品Camera
下,创建两个设备dht11
和receiver1
(看名字可以知道,设备dht11
用于采集温湿度,receiver1
用于接收数据),这里的设备并不是物理上的设备,可以理解成物理设备与阿里云服务器的一个接口,物理设备A(如嵌入式设备),经过dht11
接口接入云服务器,然后将实际采集到的数据上传至服务器端,物理设备B接入receiver1
接口接收数据,这样就实现了数据的通信。
注:没有物理设备接入时,“设备状态”这一栏显示的是“离线”。
到此阿里云平台就设置完成了。
2.2.2MQTTX模拟物理设备连接阿里云
2.2.1中,已经完成了服务器接口的创建,现在就可以连接服务器了。
打开MQTTX(下载地址:MQTTX:全功能 MQTT 客户端工具)
新建连接,看到如下要填的几项:
然后到阿里云“设备”这一项去找,首先连接dht11接口,查看“MQTT连接参数”:
按照如下对应关系去填MQTTX里的内容:
MQTTX | 阿里云MQTT连接参数 |
---|---|
名称 (随便填,和连接服务器无关) | / |
Client ID | clientId |
服务器地址 mqtt:// | mqttHostUrl |
端口 | port |
用户名 | username |
密码 | passwd |
注意:密码是会根据时间戳改变的,所以如果不是第一次连接,密码和clientId要变一起变(要么都不变),其他参数可以不变,否则连接失败
填完之后点“连接”即可。
然后再建一个连接,和上述步骤一样把接口receiver1
也连上,此时通信的状态如下:
此时,两个设备都和服务器连接上了,就可以开始通信了。
2.2.3MQTT的发布/订阅机制
由于本人也是小白,接触MQTT没多少时间,这部分仅根据我的理解进行阐述,如果有细节表述不合理的地方还请各位指出。
MQTT的发送和订阅机制类似于“邮递员—邮箱—收信人”。topic就是双方通信的“邮箱”,“邮递员”就是数据发送方,“收信人”是数据接收方,指定一个topic后,发送方往该topic发送数据,发送方发完,触发接收方接收数据。
2.2.4阿里云的topic
物理设备A接入dht11
为数据发送方,物理设备B接入receiver1
为数据接收方,数据流转的过程如下图:
可以看出,数据从物理设备A到物理设备B不是一次性直接从A到B的,而是A—topic1—Server、Server—topic2—B的方式。
现在,可以看一下Topic在阿里云里是怎么建立的,依次点击"产品—查看—Topic类列表":
可以看到“自定义Topic”下,已经自动有了三个Topic,即三个“邮箱”,但这个“邮箱”和现实里的邮箱不太一样,可以看到后面“操作权限”这一栏,规定了这个“邮箱”是指定发/收消息,也就是说这个邮箱有一定权限,如果往收邮箱里发布数据就不行,在“监控运维—日志服务”里可以看到权限冲突的信息。
这三个邮箱中,主要用连两个进行数据的收发(当然也可以自定义其他的Topic,但为了操作的规范和方便我就直接使用定义好的了)
/k0t6huhHB99/${deviceName}/user/get
:k0t6huhHB99
是ProductKey,${deviceName}
是使用时的设备名称( 在该例中就是dht11
和receiver1
),该Topic只能用于订阅,即接收消息,一旦有数据发送到该Topic时,对应的设备就会接收。/k0t6huhHB99/${deviceName}/user/update
:该Topic只能用于数据的发送,即要发送数据时,只能发到该topic里。
注:阿里云规定,每个设备的收/发数据时,topic格式都是定好的,例如:对于dht11
,如果要发数据,数据只能送到/${ProductKey}/dht11/user/update
,如果要接收订阅的数据,只能从/${ProductKey}/dht11/user/get
里收。如果发数据时往/${ProductKey}/receiver1/user/update
里发会返回错误信息。(这个地方本人也弄了好久才弄清)
2.2.5发送数据到阿里云
2.2.4中,知道了每个设备的收/发数据的topic,就可以开始发送数据了。
现在,用物理设备A给阿里云服务器发送数据。
2.2.2中,我们用MQTTX连上了dht11
接口:
在上图位置里填写Topic,即/k0t6huhHB99/${deviceName}/user/update
(设备dht11的发送topic),填写要发送的数据:222,点击发送:
看到已经发送完成,然后进阿里云控制台点击”监控运维—日志服务“,看到服务器确实接收到了数据:
2.2.6从阿里云接收数据
物理设备B从接口receiver1
接收数据,接收数据的Topic为:/k0t6huhHB99/${deviceName}/user/get
,接收数据时,必须添加订阅,即订阅topic,/k0t6huhHB99/${deviceName}/user/get
,意为当有数据指名道姓是给该topic时,就接收数据,如果不添加订阅,时无法接收消息的。
打开MQTTX,在名称为receiver1
的连接里,添加订阅,填入Topic,点击确认:
出现如下状态时,说明添加成功:
然后进阿里云控制台,在设备的Topic列表里,已经出现了一条订阅信息:
点击”发布消息“,即服务器给订阅该topic的设备发送数据:
MQTTX里出现了接收到的信息:
2.2.7设备之间的数据传递
2.2.5和2.2.6已经完成了”设备到服务器“,”服务器到设备“的数据交互,现在用设备dht11
向receiver1
发送和接收数据。
有了2.2.5和2.2.6,dht11
向topic1发数据,receiver1
从topic2收数据,现在就差一步:topic1数据转发到topic2。
打开阿里云控制台,菜单栏点击”消息转发—云产品流转“,整个流转示意图如下:
建立数据源(名称随便填),建立完成后,点进去添加Topic:
这一步就是一旦检测到这个topic发送了数据,就开始数据流转。
然后创建数据目的(名称随便填):
这一步就是指定源数据流转到哪里,选择”发布到另一个Topic“。
创建完成后,创建解析器,并点击”查看—解析器脚本“,来设置数据源数据、目的topic,最后点击发布:
// 草稿页为空时,进入草稿页会生成默认脚本
// 如果默认脚本自动保存过,继续绑定数据目的,默认脚本不会自动更新
// 此时清空脚本并保存之后,重新进入草稿页即可重新生成包含最新数据目的的默认脚本
// 设备上报数据内容,json格式
var data = payload('json');
var deviceName = "receiver1";
var productKey = "k0t6huhHB99";
// 流转到另一个Topic
writeIotTopic(1000, "/" + productKey + "/" + deviceName + "/user/get", data);
注意:图里截图截错了,writeIotTopic
函数第二个参数里的productKey
把括号去了,是变量不是函数
writeIotTopic(destinationId, topic, payload)
destinationId
:数据目的IDtopic
:需要转发到哪一个topicpayload
:转发的数据
点击”启动“:
启动完成后,打开MQTTX,在发送方dht11
连接中,发送111:
可以看到receiver1
接收到了数据:
到此,成功实现设备间的数据流转。
最后,再查看一下服务器数据的接收情况:
和之前讲的过程一致。