发布信息
- mqtt客户端连接到服务端后即可发布信息,每条信息必须包含一个主题
- 服务端根据主题决定将信息转发给哪些客户端
发布信息时,会向服务端发送一个PUBLISH报文:
topicName:主题名
qos:服务质量等级,分0、1、2共三个等级
packetId:报文标识符,用于区别不同报文
【注意】:报文标识符的内容与QoS级别有密不可分的关系。只有QoS级别大于0时,报文标识符才是非零数值。如果QoS等于0,报文标识符为0。
retainFlag:保留标志。
一般情况,客户端订阅某个主题的信息后,服务器不会立刻返回该主题的信息,要等服务器收到新信息时才会返回;
特殊情况,我们要求客户端订阅一个主题后,服务器就要立刻返回新信息
payLoad:有效载荷,可以使用mqtt协议发送文本、图片等内容,这些内容是通过payLoad来发送的
dupFlag:重发标志。当接收方没有及时确认收到报文时,发送方会重复发送MQTT报文。在重复发送MQTT报文时,发送方会将此“重发标志”设置为true。
【注意】重发标志只在QoS级别大于0时使用。
订阅主题
当客户端连接到服务端后,除了可以发布消息,也可以接收消息,而客户端要想接收消息,首先要订阅该消息的主题。
客户端是通过向服务端发送SUBSCRIBE报文来实现订阅主题
【注意】一个SUBSCRIBE报文可以包含有单个或者多个订阅主题名。
qos:客户端在订阅主题时也可以明确QoS。服务端会根据SUBSCRIBE中的QoS来提供相应的服务保证。
MQTT设备可以通过**“报文标识符”**对MQTT报文进行甄别和管理。
订阅确认:
服务端接收到客户端的订阅报文后,会向客户端发送SUBACK报文确认订阅。
该报文包含**”订阅返回码“和”报文标识符“**两个信息
返回码 |
Return Code Response |
0 |
订阅成功 – QoS 0 |
1 |
订阅成功- QoS 1 |
2 |
订阅成功- QoS 2 |
128 |
订阅失败 |
【注意】针对不同的主题订阅QoS,服务端的返回码会有所不同。
报文标识符:MQTT设备可以通过该标识符对报文进行管理。
取消订阅
客户端要取消订阅某主题时,可通过向服务端发送UNSUBSCRIBE 报文来实现。
UNSUBSCRIBE报文包含两个重要信息:
- packetId:“报文标识符”
- topic1、topic2、…… :取消订阅的主题的名称
当服务端接收到UNSUBSCRIBE报文后,会向客户端发送取消订阅确认报文 – UNSUBACK报文。该报文含有客户端所发送的“取消订阅报文标识符”。
客户端接收到UNSUBACK报文后就可以确认取消主题订阅
ESP8266发布MQTT消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <Ticker.h>
const char* ssid = "RBook"; const char* password = "1719171945678"; const char* mqttServer = "test.ranye-iot.net";
Ticker ticker; WiFiClient wifiClient; PubSubClient mqttClient(wifiClient);
int count;
void setup() { Serial.begin(9600);
WiFi.mode(WIFI_STA);
connectWifi();
mqttClient.setServer(mqttServer, 1883);
connectMQTTServer();
ticker.attach(1, tickerCount); }
void loop() { if (mqttClient.connected()) { if (count >= 3){ pubMQTTmsg(); count = 0; } mqttClient.loop(); } else { connectMQTTServer(); } }
void tickerCount(){ count++; }
void connectMQTTServer(){ String clientId = "esp8266-" + WiFi.macAddress();
if (mqttClient.connect(clientId.c_str())) { Serial.println("MQTT Server Connected."); Serial.println("Server Address: "); Serial.println(mqttServer); Serial.println("ClientId:"); Serial.println(clientId); } else { Serial.print("MQTT Server Connect Failed. Client State:"); Serial.println(mqttClient.state()); delay(3000); } }
void pubMQTTmsg(){ static int value;
String topicString = "Taichi-Maker-Pub-" + WiFi.macAddress(); char publishTopic[topicString.length() + 1]; strcpy(publishTopic, topicString.c_str());
String messageString = "Hello World " + String(value++); char publishMsg[messageString.length() + 1]; strcpy(publishMsg, messageString.c_str());
if(mqttClient.publish(publishTopic, publishMsg)){ Serial.println("Publish Topic:");Serial.println(publishTopic); Serial.println("Publish message:");Serial.println(publishMsg); } else { Serial.println("Message Publish Failed."); } }
void connectWifi(){
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("WiFi Connected!"); Serial.println(""); }
|