IoT:MQTT+Mosquitto
MQTT(Message Queuing Telemetry Transport)协议是重要的物联网传输协议
MQTT 作为物联网协议具有很多的优势:
- 异步消息协议
- 面向长连接
- 双向数据传输
- 协议轻量级
- 被动数据获取
MQTT 核心
Broker (MQTT 服务器)
Broker 是 MQTT 传递信息的枢纽,发布者会将信息发布到这里,而订阅者会从这里监听需要的信息。发布者和订阅者之间没有任何联系,都是通过 Broker 这个代理人来进行信息的互动。
Topic (主题)
主题是信息类型的标记,一般情况下主题是类似于文件系统的目录结构 assistant/light/bedroom
, 你可以把 Broker 想象成一个存放信息的大仓库,而这个主题下的信息,就是存放在 assistant
区,light
货架上的 bedroom
层。不过 MQTT 服务器并没有规定 topic 的规则,只要发布者和订阅者协商一致,任何字符串都可以当做主题。
Publish (发布)、Subscribe (订阅)
发布者将要发布的信息传送给MQTT服务器的某个主题下,订阅者可以监听对应的主题并读取信息
MQTT 信息
传输质量
MQTT中定义了三种传输质量(发布者和订阅者在与服务器通讯的过程中可以指定对应的质量)。
- 0:信息仅被传输一次,对于信息是否被收到不做任何确认。
- 1:信息可能被传输若干次,只有当信息收取者确认收到后才停止传输。
- 2:通过额外的4次握手过程,保证信息仅被传输一次,并且接收者收到了信息。
信息保留
每条发布的消息可以设置成保留(Retained)——意味着MQTT服务器在将这条信息发送给对应主题的当前订阅者之后,还会保留这条信息,这样当新的订阅者连接服务器时,会收到这条消息。
信息保留机制,对于那些非频繁更新的信息比较有用,这样新的订阅者就能收到当前的状态——比如一个温度传感器,每小时发送当前温度给MQTT服务器;另一个想要获知温度的程序连接MQTT服务器时,可能需要等一个小时才能得到当前温度;当温度传感器发送的消息代有信息保留(Retain)属性时,就不会发生这种情况了。
Will消息
客户端连接 MQTT 服务器时,可以告知服务器它有一个 Will 消息(遗嘱)—— Will 消息将在这个客户端非正常断开时被发布。
比如,一个 MQTT 的灯,可以通过Will消息告知控制端,自己已经断开连接了(OffLine)。
保持连接
MQTT 采用 TCP 协议作为通讯基础,TCP很容易在一方突然断电时形成另一方以为连接还有效的状态。同时,因为MQTT传输内容的性质,很可能长时间没有客户端与服务器端的实际内容通讯——简单来说,就是系统无法分辨连接已经断了还是真实没有通讯。
因此,在MQTT中有类似 ping 的机制,客户端发送 ping,服务器端进行回应。同时,在客户端与服务器端建立连接时,可以设置保持连接(KeepAlive)——约定在多少秒之内,若客户端没有任何消息(包括 ping)发送给服务器端,服务器端就认为这个连接已经断了。
主题通配符
在订阅消息时,订阅者订阅的主题名称可以使用通配符。MQTT协议的通配符有两个,+
和 #
。
+
代表主题名称中的一级;#
代表主题名称中若干级。
例如:
a/b/+/d:可以收到主题“a/b/c/d”或者“a/b/x/d”上的消息,但不能收到“a/b/x/y/d”上的消息。
a/b/#/d:可以收到主题“a/b/c/d”、“a/b/x/d”、“a/b/x/y/d”上的消息
客户端认证
- MQTT服务器可以设置为允许匿名登录——这时,所有客户端不需要认证即可登录服务器。
- MQTT服务器可以设置成需要用户名密码——这时,提供正确用户名和密码的客户端可以登录服务器。
- MQTT服务器可以设置成加密通讯,并且需要客户端证书——这时,提供能通过验证的证书文件的客户端可以登录服务器(用户名为证书信息中的CN,Common Name)
MQTT 服务
Mosquitto
Eclipse Mosquitto 是实现 MQTT 协议版本5.0、3.1.1 和 3.1 的开源消息代理(经EPL / EDL许可)。 Mosquitto 非常的轻巧,在从低功耗单板计算机到完整服务器的所有设备上都可以使用。Mosquitto 项目还提供了一个 C 库, 用于实现 MQTT 客户端。你可以方便的使用命令行 mosquitto_pub 和 mosquitto_sub 来发布、订阅主题。
下载安装
配置
Mosquitto 服务的配置文件为 /etc/mosquitto/mosquitto.conf,但一般情况下,我们不会去修改这个文件,而是将需要配置的内容新建文件保存在 /etc/mosquitto/conf.d/ 目录下。
在缺省情况下,Mosquitto 服务是允许匿名用户发布和订阅信息的,我们需要将其改成用户通过用户名和密码,以保证安全。
创建文件 /etc/mosquitto/passwd,并增加用户 ssbun,设置密码
1 | sudo mosquitto_passwd -c /etc/mosquitto/passwd ssbun |
如果没有
-c
参数,代表不新建文件,而是在原文件中增加新的用户,或修改原来用户的密码。
新建文件 /etc/mosquitto/conf.d/allow.conf,内容为:
allow_anonymous false
password_file /etc/mosquitto/passwd
更多的配置,可以参考官方文档
调试使用
mosquitto_sub
- 监听指定主题下的消息
常用参数 | 作用 |
---|---|
-h | 连接的服务器 |
-p | 连接的端口号(缺省为1883) |
-u | 用户名 |
-P | 密码(注意P为大写) |
-V | 协议版本号(注意V为大写) |
-t | 主题名称,可以使用通配符#和+ |
-v | 输出主题+监听到的消息(否则仅输出监听到的消息) |
例如,以下命令使用用户 pi
、密码 123
,连接到 10.0.1.105
的 1883
端口,监听所有的主题,打印出对应的内容:
1 | mosquitto_sub -t "#" -v -u pi -P 123 -h 10.0.1.105 |
mosquitto_pub
- 向指定的主题发送消息
常用参数 | 作用 |
---|---|
-h | 连接的服务器 |
-p | 连接的端口号(缺省为1883) |
-u | 用户名 |
-P | 密码(注意P为大写) |
-V | 协议版本号(注意V为大写) |
-t | 主题名称 |
-m | 消息体 |
例如,以下命令在 hello/world
主题位置发布消息 Hello, World
1 | mosquitto_pub -t hello/world -m "Hello, World" -h 10.0.1.105 -u pi -P 123 |