学习如何使用电脑客户端和ESP8266客户端来连接MQTT服务端以及订阅主题发送主题操作
MQTT原理與應用
學習如何使用電腦客戶端和ESP8266客戶端來連接MQTT服務端
本文章學習借鑒于太極創客團隊,以表感謝。官網[http://www.taichi-maker.com/]
文章目錄
- MQTT原理與應用
- 一、使用電腦客戶端和ESP8266客戶端來連接MQTT服務端
- 電腦客戶端連接MQTT服務端
- MQTT 客戶端工具 (MQTT X 桌面客戶端)
- MQTT X 下載地址
- MQTTfx 下載地址
- ESP8266連接MQTT服務端
- 示例程序
- 二、 MQTTfx 使用教程
- 公用MQTT服務器列表
- 三、學習客戶端如何實現發布消息、訂閱主題以及取消訂閱主題
- PUBLISH – 發布信息
- SUBSCRIBE – 訂閱主題
- SUBACK – 訂閱確認
- UNSUBSCRIBE – 取消訂閱
- ESP8266發布MQTT消息
- 發布MQTT消息示例
- MQTT 主題介紹
- 主題基本形式
- 主題分級
- 主題通配符
- 主題應用注意事項
- ESP8266訂閱MQTT主題
- 總結
一、使用電腦客戶端和ESP8266客戶端來連接MQTT服務端
電腦客戶端連接MQTT服務端
MQTT 客戶端工具 (MQTT X 桌面客戶端)
MQTT X 是 EMQ 開源的一款跨平臺 MQTT 5.0 客戶端工具,它支持 macOS, Linux, Windows,并且支持 MQTT 消息格式轉換。
MQTT X 的用戶界面借助聊天軟件的形式簡化了頁面的操作邏輯,用戶可以快速創建連接保存并同時建立多個連接客戶端,方便用戶快速測試 MQTT/TCP、MQTT/TLS、MQTT/WebSocket 的 連接/發布/訂閱 功能及其他特性。
MQTT X 致力于打造優雅、易用的全平臺 MQTT 客戶端,并在最近發布了 MQTT X CLI 及 MQTT X Web 兩個版本,目前在 GitHub Star 數已達到 2K,已成為使用場景最完整的 MQTT 測試客戶端。
MQTT X 下載地址
官網下載:https://mqttx.app/zh
GitHub 下載:https://github.com/emqx/MQTTX/releases
MQTTfx 下載地址
百度網盤:https://pan.baidu.com/s/13v0ROf1dOzu2tXqmw3iBMg 提取碼:r9f7
ESP8266連接MQTT服務端
ESP8266的Arduino開發環境里有多個MQTT庫,我們將使用最為流行的PubSubClient庫來作為本教程的主要介紹對象,我們將通過一系列課程教您如何使用ESP8266通過PubSubClient庫來實現MQTT物聯網應用。
ArduinoIDE 安裝庫
ArduinoIDE 導入下載的庫
示例程序
/********************************************************************** 本程序旨在演示如何使用PubSubClient庫使用ESP8266向連接MQTT服務器。 ----------------------------------------------------------------------- 本示例程序為太極創客團隊制作的《零基礎入門學用物聯網》中示例程序。 該教程為對物聯網開發感興趣的朋友所設計和制作。如需了解更多該教程的信息,請參考以下網頁: http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/ ***********************************************************************/ #include <ESP8266WiFi.h> #include <PubSubClient.h>// 設置wifi接入信息(請根據您的WiFi信息進行修改) const char* ssid = "wifi"; const char* password = "12345678"; const char* mqttServer = "test.ranye-iot.net";// 如以上MQTT服務器無法正常連接,請前往以下頁面尋找解決方案 // http://www.taichi-maker.com/public-mqtt-broker/WiFiClient wifiClient; PubSubClient mqttClient(wifiClient);void setup() {Serial.begin(9600);//設置ESP8266工作模式為無線終端模式WiFi.mode(WIFI_STA);// 連接WiFiconnectWifi();// 設置MQTT服務器和端口號mqttClient.setServer(mqttServer, 1883);// 連接MQTT服務器connectMQTTServer(); }void loop() { if (mqttClient.connected()) { // 如果開發板成功連接服務器 mqttClient.loop(); // 保持客戶端心跳} else { // 如果開發板未能成功連接服務器connectMQTTServer(); // 則嘗試連接服務器} }void connectMQTTServer(){// 根據ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 連接MQTT服務器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);} }// ESP8266連接wifi void connectWifi(){WiFi.begin(ssid, password);//等待WiFi連接,成功連接后輸出成功信息while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.print(".");}Serial.println("");Serial.println("WiFi Connected!"); Serial.println(""); }二、 MQTTfx 使用教程
下載完,安裝后,打開軟件 如下圖,第一步驟,點擊設置圖標
創建MQTT服務
connect 開始連接,右側 ,綠色說明連接成功
創建訂閱主題
訂閱主題發布信息
選擇主題,下面輸入發送的內容,點擊publish 發送,
發送記錄查看
同步太極創客教程 連接 https://www.bilibili.com/video/BV1T54y1k7MQ/?spm_id_from=333.999.0.0&vd_source=04d3b5e0230b02edb1f84360e21ab826
公用MQTT服務器列表
然也物聯 (國內)
官網地址:http://www.ranye-iot.net
MQTT服務器地址:test.ranye-iot.net
TCP 端口:1883
TCP/TLS 端口:8883
三、學習客戶端如何實現發布消息、訂閱主題以及取消訂閱主題
PUBLISH – 發布信息
MQTT客戶端一旦連接到服務端,便可以發布消息。 每條發布的MQTT消息必須包含一個主題。MQTT服務器可以通過主題確定將消息轉發給哪些客戶端
以下是PUBLISH報文的詳細信息。
topicName – 主題名
主題名用于識別此信息應發布到哪一個主題。關于MQTT主題的應用,我們在之前的課程中已經做了詳細介紹,在后續課程中我們還會對主題的高級應用進行更加詳細的講解。
QoS – 服務質量等級
QoS(Quality of Service)表示MQTT消息的服務質量等級。QoS有三個級別:0、1和2。QoS決定MQTT通訊有什么樣的服務保證。有關QoS的詳細信息我們會在后續課程中詳細講解。
packetId – 報文標識符
報文標識符可用于對MQTT報文進行標識。不同的MQTT報文所擁有的標識符不同。MQTT設備可以通過該標識符對MQTT報文進行甄別和管理。請注意:報文標識符的內容與QoS級別有密不可分的關系。只有QoS級別大于0時,報文標識符才是非零數值。如果QoS等于0,報文標識符為0。
retainFlag – 保留標志
在默認情況下,當客戶端訂閱了某一主題后,并不會馬上接收到該主題的信息。只有在客戶端訂閱該主題后,服務端接收到該主題的新信息時,服務端才會將最新接收到的該主題信息推送給客戶端。
但是在有些情況下,我們需要客戶端在訂閱了某一主題后馬上接收到一條該主題的信息。這時候就需要用到保留標志這一信息。關于保留標志的具體使用方法,我們將在本教程的后續部分進行詳細講解。
Payload – 有效載荷
有效載荷是我們希望通過MQTT所發送的實際內容。我們可以使用MQTT協議發送文本,圖像等格式的內容。這些內容都是通過有效載荷所發送的。
dupFlag – 重發標志
當MQTT報文的接收方沒有及時確認收到報文時,發送方會重復發送MQTT報文。在重復發送MQTT報文時,發送方會將此“重發標志”設置為true。請注意,重發標志只在QoS級別大于0時使用。有關QoS的詳細信息,我們將會在后續教程中為您做詳細介紹。
SUBSCRIBE – 訂閱主題
當客戶端連接到服務端后,除了可以發布消息,也可以接收消息。我們在之前的課程講過,所有MQTT消息都有主題。客戶端要想接收消息,首先要訂閱該消息的主題。這樣,當有客戶端向該主題發布消息后,訂閱了該主題的客戶端就能接收到消息了。
客戶端要想訂閱主題,首先要向服務端發送主題訂閱請求。客戶端是通過向服務端發送SUBSCRIBE報文來實現這一請求的。該報文包含有一系列“訂閱主題名”。請留意,一個SUBSCRIBE報文可以包含有單個或者多個訂閱主題名。也就是說,一個SUBSCRIBE報文可以用于訂閱一個或者多個主題。
在以上PUBLISH報文講解中,我們曾經提到過QoS(服務質量等級)這一概念。同樣的,客戶端在訂閱主題時也可以明確QoS。服務端會根據SUBSCRIBE中的QoS來提供相應的服務保證。
另外每一個SUBSCRIBE報文還包含有“報文標識符”。報文標識符可用于對MQTT報文進行標識。不同的MQTT報文所擁有的標識符不同。MQTT設備可以通過該標識符對MQTT報文進行甄別和管理。
SUBACK – 訂閱確認
服務端接收到客戶端的訂閱報文后,會向客戶端發送SUBACK報文確認訂閱。
SUBACK報文包含有“訂閱返回碼”和“報文標識符”這兩個信息。
returnCode – 訂閱返回碼
UNSUBSCRIBE – 取消訂閱
顧名思義,當客戶端要取消訂閱某主題時,可通過向服務端發送UNSUBSCRIBE – 取消訂閱報文來實現。
以上示意圖顯示,UNSUBSCRIBE報文包含兩個重要信息,第一個是取消訂閱的主題名稱。同一個UNSUBSCRIBE報文可以同時包含多個取消訂閱的主題名稱。另外,UNSUBSCRIBE報文也包含“報文標識符”,MQTT設備可以通過該標識符對報文進行管理。
當服務端接收到UNSUBSCRIBE報文后,會向客戶端發送取消訂閱確認報文 – UNSUBACK報文。該報文含有客戶端所發送的“取消訂閱報文標識符”。
客戶端接收到UNSUBACK報文后就可以確認取消主題訂閱已經成功完成了。
ESP8266發布MQTT消息
ESP8266的Arduino開發環境里有多個MQTT庫,我們將使用最為流行的PubSubClient庫來作為本教程的主要介紹對象,我們將通過一系列課程教您如何使用ESP8266通過PubSubClient庫來實現MQTT物聯網應用。關于PubSubClient庫,以下是其基本信息:
發布MQTT消息示例
/********************************************************************** 項目名稱/Project : 零基礎入門學用物聯網 程序名稱/Program name : publish_ranye_url 團隊/Team : 太極創客團隊 / Taichi-Maker (www.taichi-maker.com) 作者/Author : CYNO朔 日期/Date(YYYYMMDD) : 20200813 程序目的/Purpose : 本程序旨在演示如何使用PubSubClient庫使用ESP8266向MQTT服務器發布信息。 ----------------------------------------------------------------------- 本示例程序為太極創客團隊制作的《零基礎入門學用物聯網》中示例程序。 該教程為對物聯網開發感興趣的朋友所設計和制作。如需了解更多該教程的信息,請參考以下網頁: http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/ ***********************************************************************/ #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <Ticker.h>// 設置wifi接入信息(請根據您的WiFi信息進行修改) const char* ssid = "taichi-maker"; const char* password = "12345678"; const char* mqttServer = "test.ranye-iot.net";// 如以上MQTT服務器無法正常連接,請前往以下頁面尋找解決方案 // http://www.taichi-maker.com/public-mqtt-broker/Ticker ticker; WiFiClient wifiClient; PubSubClient mqttClient(wifiClient);int count; // Ticker計數用變量void setup() {Serial.begin(9600);//設置ESP8266工作模式為無線終端模式WiFi.mode(WIFI_STA);// 連接WiFiconnectWifi();// 設置MQTT服務器和端口號mqttClient.setServer(mqttServer, 1883);// 連接MQTT服務器connectMQTTServer();// Ticker定時對象ticker.attach(1, tickerCount); }void loop() { if (mqttClient.connected()) { // 如果開發板成功連接服務器// 每隔3秒鐘發布一次信息if (count >= 3){pubMQTTmsg();count = 0;} // 保持心跳mqttClient.loop();} else { // 如果開發板未能成功連接服務器connectMQTTServer(); // 則嘗試連接服務器} }void tickerCount(){count++; }void connectMQTTServer(){// 根據ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 連接MQTT服務器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; // 客戶端發布信息用數字// 建立發布主題。主題名稱以Taichi-Maker-為前綴,后面添加設備的MAC地址。// 這么做是為確保不同用戶進行MQTT信息發布時,ESP8266客戶端名稱各不相同,String topicString = "Taichi-Maker-Pub-" + WiFi.macAddress();char publishTopic[topicString.length() + 1]; strcpy(publishTopic, topicString.c_str());// 建立發布信息。信息內容以Hello World為起始,后面添加發布次數。String messageString = "Hello World " + String(value++); char publishMsg[messageString.length() + 1]; strcpy(publishMsg, messageString.c_str());// 實現ESP8266向主題發布信息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."); } }// ESP8266連接wifi void connectWifi(){WiFi.begin(ssid, password);//等待WiFi連接,成功連接后輸出成功信息while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.print(".");}Serial.println("");Serial.println("WiFi Connected!"); Serial.println(""); }MQTT 主題介紹
主題基本形式
主題是區分大小寫的,不建議使用中文,不建議使用空格
示例
myTopic
motorSpeed
MotorSpeed
current time
主題分級
MQTT主題各個級別之間可以使用”/”來分隔。如下例所示:
home/sensor/kitchen/temperature 四級主題
home/sensor/kitchen 三級主題
主題通配符
單級通配符: +
單級通配符可以代替一個主題級別。 以下為含有單極通配符的主題示例。
同時訂閱多個主題,前后必須一致才可以
home/sensor/+/temperature
- 可以替代中間任何的主題,
home/sensor/kitchen/temperature
home/sensor/bedroom/temperature
多級通配符 # (類似于匹配查詢like home/senso%)
home/sensor/#
home/sensor/kitchen/temperature
home/sensor/bedroom/brightness
home/sensor/data
主題應用注意事項
以$開始的主題是MQTT服務端系統保留的特殊主題,我們不能隨意訂閱或者向其發布信息。
$SYS/broker/clients/connected
$SYS/broker/clients/disconnected
$SYS/broker/clients/total
$SYS/broker/messages/sent
$SYS/broker/uptime
– 不要用 “/” 作為主題開頭
– 主題中不要使用空格
– 保持主題簡潔明了
– 主題中盡量使用ASCII字符
ASCII 碼使用指定的7 位或8 位二進制數組合來表示128 或256 種可能的字符。標準ASCII 碼也叫基礎ASCII碼,使用7 位二進制數(剩下的1位二進制為0)來表示所有的大寫和小寫字母,數字0 到9、標點符號,以及在美式英語中使用的特殊控制字符 [1] 。
了解一下ASCII字符即可
在主題中嵌入客戶端ID
ESP8266訂閱MQTT主題
/********************************************************************** 項目名稱/Project : 零基礎入門學用物聯網 程序名稱/Program name : subscribe_ranye_url 團隊/Team : 太極創客團隊 / Taichi-Maker (www.taichi-maker.com) 作者/Author : CYNO朔 日期/Date(YYYYMMDD) : 20200708 程序目的/Purpose : 本程序旨在演示如何使用PubSubClient庫使用ESP8266向MQTT服務器訂閱信息。 ----------------------------------------------------------------------- 本示例程序為太極創客團隊制作的《零基礎入門學用物聯網》中示例程序。 該教程為對物聯網開發感興趣的朋友所設計和制作。如需了解更多該教程的信息,請參考以下網頁: http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-client/http-request/ ***********************************************************************/ #include <ESP8266WiFi.h> #include <PubSubClient.h>// 設置wifi接入信息(請根據您的WiFi信息進行修改) const char* ssid = "dajiating"; const char* password = "xxxx"; const char* mqttServer = "test.ranye-iot.net"; // 如以上MQTT服務器無法正常連接,請前往以下頁面尋找解決方案 // http://www.taichi-maker.com/public-mqtt-broker/WiFiClient wifiClient; PubSubClient mqttClient(wifiClient);void setup() {pinMode(D4, OUTPUT); // 設置板上LED引腳為輸出模式digitalWrite(D4, HIGH); // 啟動后關閉板上LEDSerial.begin(9600); // 啟動串口通訊//設置ESP8266工作模式為無線終端模式WiFi.mode(WIFI_STA);// 連接WiFiconnectWifi();// 設置MQTT服務器和端口號mqttClient.setServer(mqttServer, 1883);// 設置MQTT訂閱回調函數mqttClient.setCallback(receiveCallback);// 連接MQTT服務器connectMQTTserver(); }void loop() {if (mqttClient.connected()) { // 如果開發板成功連接服務器mqttClient.loop(); // 處理信息以及心跳} else { // 如果開發板未能成功連接服務器connectMQTTserver(); // 則嘗試連接服務器} }// 連接MQTT服務器并訂閱信息 void connectMQTTserver(){// 根據ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)String clientId = "esp8266-" + WiFi.macAddress();// 連接MQTT服務器if (mqttClient.connect(clientId.c_str())) { Serial.println("MQTT Server Connected.");Serial.println("Server Address:");Serial.println(mqttServer);Serial.println("ClientId: ");Serial.println(clientId);// subscribeTopic(); // 訂閱指定主題subscribeTopicList();//} else {Serial.print("MQTT Server Connect Failed. Client State:");Serial.println(mqttClient.state());delay(5000);} }// 收到信息后的回調函數 void receiveCallback(char* topic, byte* payload, unsigned int length) {Serial.print("Message Received [");Serial.print(topic);Serial.print("] ");for (int i = 0; i < length; i++) {Serial.print((char)payload[i]);}Serial.println("");Serial.print("Message Length(Bytes) ");Serial.println(length);if ((char)payload[0] == '1') { // 如果收到的信息以“1”為開始digitalWrite(D4, LOW); // 則點亮LED。Serial.println("LED ON");} else { digitalWrite(D4, HIGH); // 否則熄滅LED。Serial.println("LED OFF");} }// 訂閱指定主題 void subscribeTopic(){// 建立訂閱主題。主題名稱以Taichi-Maker-Sub為前綴,后面添加設備的MAC地址。// 這么做是為確保不同設備使用同一個MQTT服務器測試消息訂閱時,所訂閱的主題名稱不同String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress();char subTopic[topicString.length() + 1]; strcpy(subTopic, topicString.c_str());// 通過串口監視器輸出是否成功訂閱主題以及訂閱的主題名稱if(mqttClient.subscribe(subTopic)){Serial.println("Subscrib Topic:");Serial.println(subTopic);} else {Serial.print("Subscribe Fail...");} }// 訂閱多個指定主題 void subscribeTopicList(){//單級通配符: +//String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress()+"/+/data";//多級通配符 #//String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress()+"/#";// 建立訂閱主題1。主題名稱以Taichi-Maker-Sub為前綴,后面添加設備的MAC地址。// 這么做是為確保不同設備使用同一個MQTT服務器測試消息訂閱時,所訂閱的主題名稱不同String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress();char subTopic[topicString.length() + 1]; strcpy(subTopic, topicString.c_str());// 建立訂閱主題2String topicString2 = "Taichi-Maker-Sub2-" + WiFi.macAddress();char subTopic2[topicString2.length() + 1]; strcpy(subTopic2, topicString2.c_str());// 通過串口監視器輸出是否成功訂閱主題1以及訂閱的主題1名稱if(mqttClient.subscribe(subTopic)){Serial.println("Subscrib Topic:");Serial.println(subTopic);} else {Serial.print("Subscribe Fail...");} // 通過串口監視器輸出是否成功訂閱主題2以及訂閱的主題2名稱if(mqttClient.subscribe(subTopic2)){Serial.println("Subscrib Topic:");Serial.println(subTopic2);} else {Serial.print("Subscribe Fail...");} }// ESP8266連接wifi void connectWifi(){WiFi.begin(ssid, password);//等待WiFi連接,成功連接后輸出成功信息while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.print(".");}Serial.println("");Serial.println("WiFi Connected!"); Serial.println(""); }總結
// 建立發布主題。主題名稱以Taichi-Maker-為前綴,后面添加設備的MAC地址。// 這么做是為確保不同用戶進行MQTT信息發布時,ESP8266客戶端名稱各不相同,String topicString = "Taichi-Maker-Pub-" + WiFi.macAddress();char publishTopic[topicString.length() + 1]; strcpy(publishTopic, topicString.c_str()); //主題必須字符轉化字符數組// 建立發布信息。信息內容以Hello World為起始,后面添加發布次數。String messageString = "Hello World " + String(value++); char publishMsg[messageString.length() + 1]; strcpy(publishMsg, messageString.c_str());// 實現ESP8266向主題發布信息mqttClient.publish(publishTopic, publishMsg) //發布函數// 保持心跳,保持mqtt 正常鏈接。保持在線mqttClient.loop();subscribeTopic(); // 訂閱指定主題 // 收到信息后的回調函數 //char* topic 主題, //byte* payload, 信息內容 //unsigned int length 信息長度 void receiveCallback(char* topic, byte* payload, unsigned int length) //單級通配符: +//String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress()+"/+/data";//多級通配符 #//String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress()+"/#";// 建立訂閱主題1。主題名稱以Taichi-Maker-Sub為前綴,后面添加設備的MAC地址。// 這么做是為確保不同設備使用同一個MQTT服務器測試消息訂閱時,所訂閱的主題名稱不同//訂閱指定主題String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress();char subTopic[topicString.length() + 1]; strcpy(subTopic, topicString.c_str());// 建立訂閱主題2String topicString2 = "Taichi-Maker-Sub2-" + WiFi.macAddress();char subTopic2[topicString2.length() + 1]; strcpy(subTopic2, topicString2.c_str());// 通過串口監視器輸出是否成功訂閱主題1以及訂閱的主題1名稱if(mqttClient.subscribe(subTopic)){Serial.println("Subscrib Topic:");Serial.println(subTopic);} else {Serial.print("Subscribe Fail...");} // 通過串口監視器輸出是否成功訂閱主題2以及訂閱的主題2名稱if(mqttClient.subscribe(subTopic2)){Serial.println("Subscrib Topic:");Serial.println(subTopic2);} else {Serial.print("Subscribe Fail...");}最后 還是感謝太極創客團隊。官網[http://www.taichi-maker.com/]
總結
以上是生活随笔為你收集整理的学习如何使用电脑客户端和ESP8266客户端来连接MQTT服务端以及订阅主题发送主题操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [区块链]DPoS(委托权益证明机制)官
- 下一篇: 虹科教您 | 一分钟了解视距通信,虹科提