文章目錄標題
ESP8266和帶有MQTT的Node-RED(Publish and Subscribe)
在這篇文章中,我們將向您展示如何控制ESP8266的輸出以及如何在Node-RED上顯示ESP8266的感測器數據。Node-RED軟件在Raspberry Pi上的Home Assistant運行,ESP8266和Node-RED軟件之間的通信通過MQTT通信協議實現。
下圖概述了本課程將要執行的操作。
Node-RED和Node-RED儀表板
MQTT協議
MQTT代表 MQ Telemetry Transport,這是一個很棒的輕量級的發布和訂閱系統,您可以發布和接收消息的客戶端。它是一種簡單的消息傳遞協議,設計用於受限設備且具有低帶寬。因此,它是物聯網應用程序的完美解決方案。
安裝Mosquitto Broker
有幾個經紀人您可以使用。而在本教程中,我們將使用 Home Assistant上的 Mosquitto Broker 來安裝。
安裝完成後,可以看到Configuration中,可輸入 login 的帳號密碼。這個帳號密碼是 ESP8266 連線到 MQTT broker 的帳號密碼,如果不輸入的話,也可以使用使用者帳號密碼。
再往下一點可以看到 MQTT 會使用到的 port,這裡我們維持預設值。
測試中
要查看是否已成功安裝Mosquitto代理,我們可以先確認在Home Assistant中的Mosquitto broker已經啟動,接著透過MQTTlens來測試是否已經安裝完成。下圖是確認Mosquitto broker已經啟動。
接著在Chrome中安裝MQTTlens,先透過Chrome開啟MQTTlens下載網址,點選右側的Add to Chrome進行安裝。
點選新增應用程式
開啟MQTTlens,點選MQTTlens的圖示來開啟APP
接著進行Mosquitto串接測試。
點選【Connections】旁的【+】
接著填寫相關資訊;於Connection name欄位,請填寫一個可識別的名稱,於Hostname欄位填寫Mosquitto所在的IP,若需帳戶及密碼認證,也請填入帳戶及密碼。當以上資訊填寫完成後點選CREATE CONNECTION按鍵。
當連接Mosquitto MQTT Broker成功會顯示緑色燈號,這時我們輸入一個範例來測試Sensor/Temperature/Room1
先在訂閱(SUBSCRIBE)的欄位地方輸入該topic並訂閱它。接著在發佈的欄位也輸入該topic,並在message中輸入hello,並發佈它,則可以得到我們訂閱的topic收到hello的訊息。這樣代表MQTT已經成功安裝,並完成測試。
與Node-RED建立MQTT通信
儀表板佈局
第一步是創建儀表板佈局。在這個示例中,我們將有一個按鈕來控制ESP8266輸出;圖表和儀表顯示DHT11傳感器的溫度和濕度讀數。
在“ Node-RED”窗口的右上角,選擇“dashboard” 選項卡下的“ Layout”選項卡。建立一個名為 Room的選項卡,並在Room選項卡的內部,建立兩個組:Lamp和 Sensor,如下圖所示。
建立流程
將以下節點拖到流中–參見下圖:
- switch開關–這將控制ESP8266輸出
- mqtt輸出節點–這將根據開關狀態將消息發佈到ESP8266
- 2個 mqtt輸入節點–該節點將訂閱溫度和濕度主題,並從ESP接收感測器數據
- chart圖表–將顯示溫度感測器讀取的數據
- Gauge儀表–將顯示濕度感測器讀取的數據
需要連接Node-RED和MQTT代理。要將MQTT代理連接到Node-REd,請雙擊MQTT輸出節點。彈出一個新窗口–如下圖所示。
服務端的IP,請輸入自己設定的IP。
若Mosquitto Broker有設定帳戶及密碼認證,則在安全的選項中,也請一併輸入認證的帳戶及密碼,若無設定帳密就無需理會本設定步驟。
以上均輸入相關欄位後,再按下新增,MQTT輸出節點將自動連接到您的代理。
編輯所有其他節點屬性,如下圖所示:
- switch切換-當switch的狀態是on時,會發送一個 on字符串消息; 並在off時發送 off 字符串消息。該節點將在room/lamp topic上發布 。然後,您的ESP如有訂閱該主題,則會接收到此消息。
- mqtt輸出節點。此節點連接到mosquitto broker,它將在room/lamp topic中發布。
- mqtt輸入節點。該節點已訂閱room/temperature topic,以從ESP8266接收溫度感測器數據。ESP8266將發布有關該主題的溫度讀數。
- chart圖表。 該圖表將顯示在room/temperature topic上收到的讀數。
- mqtt輸入節點。 該節點已訂閱room/humidity topic,以從ESP8266接收濕度感測器數據。ESP8266將在同一主題上發布濕度讀數。
- Gauge測量。儀表將顯示有關room/humidity topic的讀數。
如下圖所示連接節點。
您的Node-RED應用程序已準備就緒。單擊右上角的 部署按鈕。
Node-RED應用程序已準備就緒。要查看儀表板的外觀,請訪問 http:// your-pi-ip-address / ui。可以在Node-RED部署下方小圖示按下也可以直接開啟新視窗訪問。
現在,請按照以下部分準備您的ESP8266。
準備您的Arduino IDE
安裝PubSubClient庫
該PubSubClient庫提供了客戶端做簡單的發布/訂閱訊息與Server之間端,它支援MQTT架構(基本上可以讓你的ESP8266與Node-RED溝通)。
1) 點擊此處下載PubSubClient庫。您的下載文件夾中應該有一個.zip文件夾
2)解壓縮.zip文件夾,您應該獲得pubsubclient-master文件夾
3)重命名您的文件夾 pubsubclient-master到pubsubclient
4)將pubsubclient文件夾移至Arduino IDE安裝庫文件夾
5)然後,重新打開您的Arduino IDE
該庫附帶了許多示例草圖。請參閱Arduino IDE軟件中的檔案>範例> PubSubClient。
安裝DHT感測器庫
DHT感測器庫 提供了使用任何DHT感測器讀取溫度和濕度與ESP8266或Arduino板間的一個簡單的方法。
1) 點擊此處下載DHT感測器庫。您 的下載中應該有一個 .zip文件夾
2) 解壓縮 .zip 文件夾,您應該獲得 DHT-sensor-library-master 文件夾
3) 重命名您的文件夾 DHT感測器庫主 到 DHT
4) 將 DHT 文件夾移至Arduino IDE安裝 庫 文件夾
5) 然後重新打開您的Arduino IDE
有關DHT11感測器和ESP8266的更多信息,請閱讀 ESP8266 DHT11 / DHT22帶Arduino IDE的溫度和濕度Web服務器。
在Arduino IDE上選擇合適的板
您還需要在Arduino IDE上選擇合適的板:
1)轉到工具,然後選擇“ NodeMCU 1.0(ESP-12E模塊)”。
2)在工具>端口> COM6下選擇您的ESP端口號(在我的情況下)
上傳程式碼
ESP訂閱了room/lamp topic,以接收Node-RED應用程序在該主題上發布的消息,來開啟或關閉燈泡。
該程式碼順便也註釋了您需要進行更改的位置。您需要使用自己的SSID,密碼和Home Assistant IP地址編輯程式碼。
該程式碼還與其他DHT感測器兼容-您只需要取消註釋並註釋正確的程式碼行即可選擇您的感測器。
/***** Terry Lee 完整的程式碼及專案說明請參閱: *****/ #include <ESP8266WiFi.h> #include <PubSubClient.h> #include "DHT.h" // 無論您使用的DHT感測器類型是哪一個,請將您使用的那個型號解開 #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 // 更改下面的憑據,您的ESP8266才可以連接到您的路由器 const char* ssid = "YourSSID"; const char* password = "SSID Password"; // 將變數值更改為HomeAssistant IP地址,以便連接到MQTT Broker const char* mqtt_server = "mqtt server ip"; // 若MQTT Broker有設定認證請輸入自己設定的帳密 const char* mqtt_user = "MQTT User"; const char* mqtt_password = "MQTT Password"; // 初始化espClient。如果您在家庭自動化系統中運行多個ESP,則應更改每個espClient變數名稱 WiFiClient espClient; PubSubClient client(espClient); // DHT Sensor - GPIO 5 = D1 on ESP-12E NodeMCU board const int DHTPin = D1; // Lamp - LED - GPIO 4 = D2 on ESP-12E NodeMCU board const int lamp = D2; // 初始化 DHT sensor. DHT dht(DHTPin, DHTTYPE); // 輔助計時器變數 long now = millis(); long lastMeasure = 0; // 不要更改下面的功能。此功能將ESP8266連接到路由器 void setup_wifi() { delay(10); // 我們首先連接到WiFi網絡 Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("WiFi connected - ESP IP address: "); Serial.println(WiFi.localIP()); } // 當某些設備向esp8266訂閱的主題發布消息時,會執行此功能 // 更改下面的函數以將邏輯增加到程序,因此當設備將消息發佈到主題時您的ESP8266實際上可以配合執行相關作業 void callback(String topic, byte* message, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print(". Message: "); String messageTemp; for (int i = 0; i < length; i++) { Serial.print((char)message[i]); messageTemp += (char)message[i]; } Serial.println(); // 隨意添加更多IF語句以控制更多GPIO與MQTT // 當主題room/lamp上收到了一條消息,請檢查消息是on或off。根據消息啟閉燈泡GPIO if(topic=="room/lamp"){ Serial.print("Changing Room lamp to "); if(messageTemp == "true"){ digitalWrite(lamp, HIGH); Serial.print("On"); } else if(messageTemp == "false"){ digitalWrite(lamp, LOW); Serial.print("Off"); } } Serial.println(); } // 此功能將您的ESP8266重新連接到MQTT broker // 如果要與ESP8266訂閱更多主題,請更改下面的功能 void reconnect() { // 循環直到我們重新聯繫 while (!client.connected()) { Serial.print("Attempting MQTT connection..."); String clientId = "ESP8266Client-"; clientId += String(random(0xffff), HEX); if (client.connect(clientId.c_str(),mqtt_user,mqtt_password)) { Serial.println("connected"); // 訂閱或重新訂閱主題 // 您可以訂閱更多主題 (可以控制更多燈泡等等) client.subscribe("room/lamp"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // 重試前等待5秒鐘 delay(5000); } } } // 設置功能將ESP GPIOS設置為輸出,以115200的鮑率啟動序列通信 // 設置MQTT代理並設置callback函數 // 回饋函數是收到消息的原因,實際控制LED void setup() { pinMode(lamp, OUTPUT); dht.begin(); Serial.begin(9600); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } // 對於此案,您無需在循環函數中更改任何內容。基本上它確保您的ESP已連接到您的broker void loop() { if (!client.connected()) { reconnect(); } now = millis(); // 每30秒發佈的新型溫度和濕度 if (now - lastMeasure > 3000) { lastMeasure = now; // 感測器的數據可能要每2秒鐘才更新 float h = dht.readHumidity(); // 讀取攝氏溫度(預設) float t = dht.readTemperature(); // 讀取華氏溫度 (isFahrenheit = true) float f = dht.readTemperature(true); // 檢查是否有任何讀取失敗並提早退出(重試) if (isnan(h) || isnan(t) || isnan(f)) { Serial.println("Failed to read from DHT sensor!"); return; } // 計算攝氏度的溫度值 float hic = dht.computeHeatIndex(t, h, false); static char temperatureTemp[7]; dtostrf(t, 6, 2, temperatureTemp); // 取消對華氏溫度取值的關注 // float hif = dht.computeHeatIndex(f, h); // static char temperatureTemp[7]; // dtostrf(hif, 6, 2, temperatureTemp); static char humidityTemp[7]; dtostrf(h, 6, 2, humidityTemp); // 發布溫度和濕度值 client.publish("room/temperature", temperatureTemp); client.publish("room/humidity", humidityTemp); Serial.print("Humidity: "); Serial.print(h); Serial.print(" %\t Temperature: "); Serial.print(t); Serial.print(" *C "); Serial.print(f); Serial.print(" *F\t Heat index: "); Serial.print(hic); Serial.println(" *C "); // Serial.print(hif); // Serial.println(" *F"); } client.loop(); }
上載程式碼後,在HomeAssistant運行您的Node-RED應用程序和Mosquitto Broker的情況下,您可以以115200的鮑率打開Arduino IDE序列監視器,並即時查看發生了什麼。
這有助於檢查ESP是否已成功建立與路由器和Mosquitto Broker的連接。您還可以查看ESP正在接收和發布的消息。
建立電路
所需零件
這些是構建電路所需的零件
- Raspberry Pi
- ESP8266(ESP-12E nodemcu)
- DHT11溫濕度感測器
- 麵包板
- 330電阻
- LED
- 4700Ω電阻
原理圖
範例
總結
我們希望您對本教程有所幫助。
您好
感謝大大的教學,學習到很多,但是還是有一些疑問
請問使用mosquitto當broker是要把讓電腦一直開啟才能保持功能嗎?
如果不是連同一個網路(比如說人在外面,用手機網路)是不是就不能控制NodeMCU(Station模式)了?
如果把node-red的terminal關掉是不是做好的功能也沒有了?
謝謝
mosquitto(也就是MQTT)要一直開啟才可以持續傳送broker
nodered也是要持續開啟,MQTT的功能才生效
你提到的「連同一個網路」問題,這裡需要設定DNS,只要把你的Node-Red及Mosquitto都設定DNS,這樣無論人在那邊,只要可以連上網就可以執行任何MQTT的任務了