2026年1月19日 星期一

ESP32(Wokwi) MQTT Basic Example--(1)

 ESP32(Wokwi)  MQTT Basic Example--(1)




MQTT(Message Queuing Telemetry Transport,訊息佇列遙測傳輸)是一種基於 「發佈/訂閱」(Publish/Subscribe) 模式的輕量級通訊協定。

它最初由 IBM 開發,設計目標是為了在低頻寬、不穩定網路環境下的遠端裝置(如感測器)提供可靠的通訊,現在已成為 IoT(物聯網) 領域最主流的標準協定。


1. MQTT 的核心運作機制:發佈與訂閱

在 MQTT 的世界裡,裝置之間並不直接連線,而是透過一個「中間人」稱為 MQTT Broker(代理伺服器)

  • 發佈者 (Publisher):負責發送訊息的裝置(例如你的 ESP32 溫濕度感測器)。它會將訊息發送到一個特定的「主題」(Topic)。

  • 訂閱者 (Subscriber):想要接收訊息的裝置(例如手機 App)。它會告訴 Broker 它對哪些「主題」感興趣。

  • 主題 (Topic):訊息的分類標籤,結構類似資料夾路徑,例如:home/livingroom/temperature

  • 代理伺服器 (Broker):核心轉運站,負責接收所有發佈者的訊息,並根據主題轉發給正確的訂閱者。


2. MQTT 的四大特性

特性說明
輕量省電封包標頭非常小(最小僅 2 bytes),適合電池供電的微控制器(如 ESP32, Arduino)。
雙向通訊裝置可以同時是發佈者也是訂閱者,實現遠端監控與控制。
服務質量 (QoS)提供三種層級(0: 最多一次、1: 至少一次、2: 剛好一次),確保訊息傳遞的可靠性。
遺囑功能 (LWT)當裝置意外斷線時,Broker 會自動發佈「遺囑訊息」告知其他訂閱者該裝置已斷線。
  • HTTP 像打電話:每次想知道資料都要主動問(Request),伺服器才回答(Response),且封包很大,很浪費資源。

  • MQTT 像訂閱電子報:你只需要訂閱一次,一旦有新資料,Broker 就會主動「推播」給你,效率極高。


4. 實務應用舉例

想像一個智慧家庭系統:

  1. 冷氣機 訂閱了 home/ac/control 主題。

  2. 手機 App 發佈訊息 "ON" 到 home/ac/control

  3. MQTT Broker 收到後,立刻將 "ON" 傳給冷氣機。

  4. 冷氣機收到訊息,啟動電源。


1. 硬體連接 (Wokwi 建議)

在 Wokwi 模擬器中,請確保添加以下元件:

  • ESP32 DevKit V1

  • LCD16x2 (I2C 介面):這比普通並列介面省線。

    • GND -> GND

    • VCC -> 5V

    • SDA -> GPIO 21

    • SCL -> GPIO 22


2. 程式碼實作

請將以下程式碼貼入 Wokwi 的 sketch.ino 中。你需要安裝 PubSubClientLiquidCrystal I2C 函式庫。

#include <WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>

// --- 設定區 ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "mqtt-dashboard.com"; // 已更換 Broker

const char* outTopic = "alex9ufo/basic/outTopic";
const char* inTopic = "alex9ufo/basic/inTopic";

// 物件初始化 (ESP32 I2C 預設 SDA: 21, SCL: 22)
WiFiClient espClient;
PubSubClient client(espClient);
LiquidCrystal_I2C lcd(0x27, 16, 2);

unsigned long lastMsg = 0;
int count = 1;

// --- 訂閱訊息處理 (接收 inTopic) ---
void callback(char* topic, byte* payload, unsigned int length) {
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
 
  // 輸出到 Serial Monitor
  Serial.print("\n[收到訂閱訊息] 主題: ");
  Serial.println(topic);
  Serial.print("內容: ");
  Serial.println(message);

  // 輸出到 LCD 第二行
  lcd.setCursor(0, 1);
  lcd.print("                "); // 清行
  lcd.setCursor(0, 1);
  lcd.print(message.substring(0, 16)); // 限制 16 字元避免溢出
}

void setup_wifi() {
  delay(10);
  Serial.println("\nConnecting to WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi Connected!");
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // 建立隨機 Client ID 避免連線衝突
    String clientId = "ESP32Client-" + String(random(0xffff), HEX);
    if (client.connect(clientId.c_str())) {
      Serial.println("Connected to HiveMQ");
      client.subscribe(inTopic); // 重新連線後訂閱主題
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
 
  // 初始化 LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("WiFi Connecting");

  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  unsigned long now = millis();
  if (now - lastMsg > 5000) { // 每 5 秒執行一次
    lastMsg = now;
   
    // 格式化訊息
    String msg = "Hello ESP32 #" + String(count);
    String fullMsg = "Hello WOKWI ESP32 #" + String(count);
   
    // 1. 輸出到 Serial Monitor
    Serial.println("Publishing: " + fullMsg);
   
    // 2. 輸出到 MQTT (發送完整內容)
    client.publish(outTopic, fullMsg.c_str());
   
    // 3. 輸出到 LCD 第一行 (因為寬度有限,縮短顯示內容)
    lcd.setCursor(0, 0);
    lcd.print("                "); // 清行
    lcd.setCursor(0, 0);
    lcd.print(msg);
   
    count++;
  }
}

3. 功能說明

  • 自動遞增發送:使用 millis() 計時器,每 5000 毫秒(5秒)會自動將計數器 count 加 1,並格式化為 Hello WOKWI ESP32 #n 發送到 outTopic

  • 即時訂閱:當 inTopic 收到訊息時,會觸發 callback 函式,將內容顯示在 LCD 的第二行。

  • LCD 管理:第一行顯示發送狀態,第二行顯示接收到的訊息。

4. 如何測試?

  1. 在 Wokwi 啟動模擬

  2. 打開一個 MQTT 客戶端(如 HiveMQ Web Client)。

  3. 測試發送:在 Web Client 訂閱 alex9ufo/basic/outTopic,你會看到每 5 秒跳出一次訊息。

  4. 測試接收:在 Web Client 向 alex9ufo/basic/inTopic 發送一段文字(例如 "Hi Alex"),你的 Wokwi LCD 第二行就會立即更換文字。














沒有留言:

張貼留言

經由MQTT協定的2個WOKWI ESP32 雙向通訊 (ESP32 to ESP32 MQTT Communication )

 經由MQTT協定的2個WOKWI ESP32 雙向通訊  (ESP32  to ESP32 MQTT Communication ) 使用兩個 ESP32 建立一個遠端控制系統。 MQTT Broker: mqtt-dashboard.com Topic (主題): ale...