什么是MQTT
MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。
优点:
轻巧、开放、简单、规范,易于实现。
这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。
基本原理
在MQTT协议通讯中,有两个最为重要的角色。它们分别是服务端和客户端。
服务端:
是消息传输的枢纽
客户端:
客户端有多个,它们之间不能直接相互通信,中间使用服务端来处理消息分配。
客户端要获取某个主题信息,要向服务端进行主题 “订阅”,订阅后可以向服务端发送与主题相关的信息,其他客户端再从服务端获取信息。
客户端连接服务端
分2个步骤
- 客户端向服务端发送请求数据包“CONNECT”(也叫报文),其中包含了连接请求的信息
- 服务端收到请求后,发送数据包“CONNACK”进行确认
CONNECT报文
这是该报文的信息:
clientID
clientId是MQTT客户端的唯一标识,MQTT服务端以此来识别客户端
cleanSession – 清除会话
表示如果客户端未能正确接收到数据时,服务端是否要对数据进行保存;
取值true表示保存,false表示不保存
注意:如果数据很重要,客户端没有正确接收到会造成严重后果,建议取值true,让服务端先把会话保留,待客户端能正常接收再发送。
反之如果数据不会重要,可以取值为false
keepAlive —— 间隔时间
用于服务端每隔多久就了解一下客户端是否与其保持连接的情况
CONNACK – 确认连接请求
sessionPresent
CONNACK报文的sessionPresent与CONNECT报文的cleanSession相互配合。
cleanSession=true时,sessionPresent应该配置为false,即不需要保存信息;反之sessionPresent应该配置为true,即需要保存会话信息。
总之,sessionPresent作用是客户端发送连接请求时,服务端告知客户端有没有保存报文信息。这个被服务端保存的报文信息是来自于上一次客户端连接时,服务端曾经发送此报文给客户端,但是发送后没有收到客户端接收确认。
returnCode —— 返回码
当服务端收到了客户端的连接请求后,会向客户端发送returnCode(返回码),用以说明连接情况
返回码 | 返回码描述 |
---|---|
0 | 成功连接 |
1 | 连接被服务端拒绝,原因是不支持客户端的MQTT协议版本 |
2 | 连接被服务端拒绝,原因是不支持客户端标识符的编码。 可能造成此原因的是客户端标识符编码是UTF-8,但是服务端不允许使用此编码。 |
3 | 连接被服务端拒绝,原因是服务端不可用。 即,网络连接已经建立,但MQTT服务不可用。 |
4 | 连接被服务端拒绝,原因是用户名或密码无效。 |
5 | 连接被服务端拒绝,原因是客户端未被授权连接到此服务端。 |
ESP8266连接MQTT服务端
http://test.ranye-iot.net 是国内一个MQTT服务器平台地址,TCP端口为1883
接下来使用PubSubClient
库(去GitHub下载zip包后通过ArduinoIDE添加即可)来实现MQTT物联网应用。
-
配置WiFi
-
创建mqtt客户端对象(间接创建)
1
2WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient); -
配置客户端要连接哪个服务端(绑定服务端)
1
2
3String mqttServer = "test.ranye-iot.net";
const int port = 1883;
mqttClient.setServer(mqttServer, port); //连接服务端 -
连接服务端
1
2
3
4//用设备的mac地址来生成唯一标识该设备的clientID
String clientID = "esp8266-" + WiFi.macAddress();
mqttClient.connect(clientId.c_str()) //连接成功返回true -
连接成功后保持 “心跳”,否则…(可以尝试继续连接)
1
2
3
4
5
6
7void loop() {
if (mqttClient.connected()) { // 如果开发板成功连接服务器
mqttClient.loop(); // 保持客户端心跳
} else { // 如果开发板未能成功连接服务器
connectMQTTServer(); // 则尝试连接服务器
}
}
完整code:
1 |
|