一個基於 ESP32 的物聯網系統架構,描述了硬體端、雲端代理伺服器(Broker)以及多個客戶端(Clients)之間的互動關係
以下是根據圖片內容對該系統關係的詳細說明:
1. 硬體終端 (CLIENT 3 / ESP32)
這是系統的實體感測與執行層
感測器數據採集:透過 DHT22 感測器讀取環境的溫度與濕度數據
。 在地顯示:將溫濕度數值即時顯示於 I2C 16x2 LCD 螢幕上(例如:Temp: 23.7 C, Humi: 76.5%)
。 訊息發布 (Publish):將讀取的數據上傳至 MQTT Broker
。 溫度主題:
alex9ufo/mqtt/ex1/Temp。 濕度主題:
alex9ufo/mqtt/ex1/Humi。
執行器控制:訂閱主題
alex9ufo/mqtt/ex1/led以接收控制指令,操作 LED 的狀態(如亮、滅、閃爍或計時)。
2. MQTT 雲端代理伺服器 (SERVER / BROKER)
該系統使用 MQTTGO (NMking Technology) 作為核心通訊中轉站
訊息路由:負責接收來自 ESP32 的溫濕度訊息,並將其轉發給所有訂閱該主題的客戶端(如 Python 介面)
。 指令轉發:接收來自控制端(Client 1 或 2)的 LED 指令,並發送給 ESP32
。
3. 監控與控制端 (CLIENT 1 & 2)
這些客戶端負責與使用者互動:
Python GUI 介面 (Client 2)
: 數據監測:訂閱溫濕度主題,並以圓餅圖或文字形式顯示「當前溫度: 23.7°C」與「當前濕度: 76.5%」
。 連線狀態:顯示 MQTT 的連線指示燈
。 遠端控制:提供按鈕發送指令至
led主題,包含 ON(亮)、OFF(滅)、Flash(閃爍)及 Timer: 5s(計時 5 秒)。
MQTTBOX (Client 1)
: 作為通訊測試工具,用於監看或手動發布主題訊息,確保系統通訊正常
。
總結關係流程
數據流:[ESP32] → 發布溫濕度 → [MQTT Broker] → 轉送訊息 → [Python 介面]
。 指令流:[Python 介面] → 發布 LED 指令 → [MQTT Broker] → 轉送指令 → [ESP32] → 控制 LED 動作
。
在 MQTT(Message Queuing Telemetry Transport)架構中,核心概念是**「發行(Publish)」與「訂閱(Subscribe)」**,這是一種「非同步」的通訊方式,所有訊息都透過一個中間人(Broker)來傳遞。
以下根據你的接線圖
1. 角色定義
發行者 (Publisher):產生訊息並發送到特定「主題 (Topic)」的客戶端。在你的案例中,ESP32 與 Python 程式都同時扮演這個角色。
訂閱者 (Subscriber):向 Broker 登記想要接收某個「主題」訊息的客戶端。
代理伺服器 (Broker):即
mqttgo.io。它負責接收所有發行者的訊息,並將訊息精準地轉發給所有有訂閱該主題的客戶端。
2. 數據流:從感測器到監控介面 (上行)
這是將環境數據傳送到雲端與電腦的過程:
動作:發行 (Publish)
發行者:ESP32
。 主題與內容:
主題:
alex9ufo/mqtt/ex1/Temp,內容:例如23.7。 主題:
alex9ufo/mqtt/ex1/Humi,內容:例如76.5。
頻率:每 5 秒發送一次。
DHT22 的感測極限(溫度 -40 C ~ +80 C ,濕度 0% ~ 100%)
動作:訂閱 (Subscribe)
訂閱者:Python Tkinter 程式 (Client 2) 與 MQTTBOX (Client 1)
。 結果:當 Broker 收到 ESP32 的溫濕度時,會立刻推播給 Python 程式,進而更新介面上的圓餅圖
。
3. 指令流:從電腦控制硬體 (下行)
這是遠端控制 LED 燈光的過程:
動作:發行 (Publish)
發行者:Python Tkinter 程式
。 主題:
alex9ufo/mqtt/ex1/led。 指令內容:根據按下不同的按鈕,發送
on、off、flash或timer。
動作:訂閱 (Subscribe)
訂閱者:ESP32 (Client 3)
。 行為邏輯:
ESP32 一直在監聽
.../led這個主題。 一旦收到
on,ESP32 的程式碼會將 GPIO 2 輸出高電位,點亮 LED。 一旦收到
timer,ESP32 啟動內部計時器,5 秒後自動熄滅 LED。
4. 運作特性總結
解耦性:ESP32 並不需要知道是誰在控制它(可能是 Python 程式,也可能是 MQTTBOX),它只需要訂閱正確的主題並對指令做出反應
。 多對多:如果同時有五台電腦執行 Python 程式並訂閱了溫濕度主題,這五台電腦都會同時看到最新的數據
。 即時性:MQTT 是一種極輕量化的協定,非常適合像 ESP32 這種記憶體有限的嵌入式設備,能達成毫秒等級的指令反應
。
在物聯網開發中,選擇一個穩定且免費的 MQTT Broker 進行測試是非常重要的。
根據你的架構圖,你目前使用的是 MQTTGO (NMking Technology)
除了 MQTTGO 之外,以下是全球開發者社群中最常用且穩定的免費公共 MQTT Broker:
1. HiveMQ Public Broker
這是目前最受歡迎的公共測試伺服器之一,擁有非常友善的線上查看工具。
伺服器位址:
broker.hivemq.com連接埠: 1883 (TCP), 8000 (WebSockets)
優點: 提供
,不需要安裝軟體就能檢查訊息是否發行成功。線上網頁客戶端
2. Mosquitto (test.mosquitto.org)
由 Eclipse 基金會維護,是 MQTT 協定的官方參考實作。
伺服器位址:
test.mosquitto.org連接埠: 1883 (不加密), 8883 (SSL 加密)
優點: 支援多種安全連線模式(TLS/SSL),適合需要測試加密連線的專案。
3. EMQX Public Broker
EMQX 是目前效能極高的分散式 MQTT Broker。
伺服器位址:
broker.emqx.io連接埠: 1883, 8083 (WebSockets)
優點: 延遲極低,全球擁有多個節點,穩定性高。
4. Shiftr.io
這是一個非常特殊的視覺化 Broker。
特性: 它可以將你所有連接的設備與主題(Topic)以互動式地圖的方式呈現,非常直觀。
免費額度: 提供一定數量的免費連接數,適合教學與展示。
公共 Broker 使用注意事項 (重要)
在使用這些免費伺服器時,請務必遵守以下規範:
隱私風險: 公共 Broker 是完全公開的。任何人只要訂閱
#(通配符),就能看到你發送的所有數據。請勿傳送機密資訊(如真實密碼、個人住址)。 主題唯一性: 為了避免跟別人的專案衝突,建議你的主題名稱要包含獨特的 ID,例如像你現在使用的
alex9ufo/...。 不保證持久性: 免費伺服器隨時可能重啟或清除數據,不建議用於商業或需要 24/7 運作的正式環境。
總結建議
如果你在台灣開發,MQTTGO
WOKWI程式
程式碼是一個完整的 IoT 智慧溫濕度監控系統。它結合了硬體感測(DHT22)、在地顯示(LCD 1602)以及遠端雲端控制(MQTT)。
以下我為你將這段程式碼拆解為四大核心模組進行詳細說明:
1. 網路連線模組 (WiFi & MQTT)
這部分負責讓 ESP32 能夠「上網」並與 mqttgo.io 伺服器溝通。
setup_wifi(): 這是標準的 WiFi 連線流程。它會不斷檢查狀態直到連上為止。在 Wokwi 模擬器中,Wokwi-GUEST是免密碼的。reconnect(): 這是 MQTT 的生命線。如果網路斷掉或伺服器失聯,它會自動嘗試重新連線,並在成功後重新訂閱 LED 控制的主題 (alex9ufo/mqtt/ex1/led)。clientId: 程式碼中使用了隨機生成的 ID,這是為了避免多人同時使用同一個伺服器時產生踢人斷線的問題。
2. 感測與發布模組 (DHT22 & LCD)
這部分負責「採集數據」並「對外展示」。
每 5 秒更新一次: 透過
millis() - lastMsg > 5000判斷時間,這比使用delay(5000)好,因為它不會讓系統卡死,讓 MQTT 能持續接收指令。數據發布: 讀取到的溫度與濕度會分別轉換成字串,推送到
.../Temp和.../Humi兩個主題。在地顯示:
lcd.print會同步更新資訊到 16x2 的螢幕上。
3. 遠端指令處理 (MQTT Callback)
當你從手機或電腦發送訊息到 alex9ufo/mqtt/ex1/led 時,callback() 函數會被觸發。
它會根據接收到的內容 (
on,off,timer,flash) 來改變ledMode變數。這就像是 ESP32 的耳目,隨時監聽遠端的命令。
4. LED 行為邏輯 (核心控制)
這是在 loop() 中根據 ledMode 執行的具體動作:
| 模式 | 行為邏輯 |
| :--- | :--- |
| on | 恆亮(在 callback 中直接設定)。 |
| off | 恆滅(在 callback 中直接設定)。 |
| flash | 透過 millis() 計算,每 500ms 切換一次電位,達成閃爍效果。 |
| timer | 收到指令時亮起,並記錄當下時間,滿 5 秒後程式會自動將其設為 off。 |
Python 程式碼是一個結合了 GUI(Tkinter)、數據視覺化(Matplotlib)與物聯網通訊(MQTT)的完整客戶端。
以下是逐行詳細說明:
1. 匯入庫與環境設定
import tkinter as tk # 建立視窗介面的標準庫
import paho.mqtt.client as mqtt # MQTT 通訊協定庫
import matplotlib.pyplot as plt # 繪圖工具
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # 將圖表嵌入 Tkinter 的工具
import matplotlib
這部分載入了所有必要的工具,特別是
FigureCanvasTkAgg,它是連接「圖表」與「視窗視窗」的橋樑。
2. 中文字型補丁
matplotlib.rcParams['font.family'] = ['Microsoft JhengHei', 'sans-serif']
matplotlib.rcParams['axes.unicode_minus'] = False
第 1 行:指定 Matplotlib 使用「微軟正黑體」,否則圖表中的中文會變「豆腐塊」。
第 2 行:確保座標軸上的負號 (
-) 能正常顯示。
3. 常數設定
MQTT_SERVER = "mqttgo.io"
TOPIC_TEMP = "alex9ufo/mqtt/ex1/Temp"
TOPIC_HUMI = "alex9ufo/mqtt/ex1/Humi"
TOPIC_LED = "alex9ufo/mqtt/ex1/led"
定義了 MQTT 伺服器位址與三個通訊主題(訂閱溫濕度、發布 LED 指令)。
4. 類別初始化 __init__
class MQTTApp:
def __init__(self, root):
self.root = root
self.root.title("ESP32 MQTT 控制面板 (2026 版)")
self.root.geometry("600x650")
self.temp_val = 0.0 # 儲存目前的溫度值
self.humi_val = 0.0 # 儲存目前的濕度值
self.setup_ui() # 初始化介面佈局
self.setup_mqtt() # 初始化通訊連線
這是程式的起點,設定視窗大小並準備存放數據的變數。
5. 建立 UI 介面 setup_ui
def setup_ui(self):
# --- 連線狀態指示燈 ---
status_frame = tk.Frame(self.root)
status_frame.pack(pady=10)
tk.Label(status_frame, text="連線狀態: ").pack(side=tk.LEFT)
self.canvas_status = tk.Canvas(status_frame, width=20, height=20)
self.canvas_status.pack(side=tk.LEFT)
self.status_light = self.canvas_status.create_oval(2, 2, 18, 18, fill="red")
建立一個圓形指示燈(預設紅色),代表 MQTT 是否連線成功。
# --- LED 控制按鈕 ---
ctrl_frame = tk.LabelFrame(self.root, text="LED 遠端控制", padx=10, pady=10)
ctrl_frame.pack(pady=10, fill="x", padx=20)
btns = [ ("亮燈 (ON)", "on"), ("滅燈 (OFF)", "off"), ... ]
for text, cmd in btns:
btn = tk.Button(ctrl_frame, text=text, ...,
command=lambda c=cmd: self.publish_led(c))
btn.pack(side=tk.LEFT, padx=5, expand=True)
利用迴圈產生四個按鈕。這裡用了
lambda技巧,讓不同按鈕被按下時,會帶入不同的指令字串(如 "on" 或 "flash")到發送函數。
# --- 圖表區 ---
self.fig, (self.ax1, self.ax2) = plt.subplots(1, 2, figsize=(6, 3))
self.canvas_plt = FigureCanvasTkAgg(self.fig, master=self.root)
self.canvas_plt.get_tk_widget().pack(pady=20)
建立一個包含左右兩個子圖的畫布,並將其置於視窗中心。
6. MQTT 連線邏輯 setup_mqtt
def setup_mqtt(self):
self.client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
self.client.on_disconnect = self.on_disconnect
self.client.connect(MQTT_SERVER, 1883, 60)
self.client.loop_start() # 開啟背景線程持續監聽
設定回呼函數(Callback)。
loop_start()非常關鍵,它讓 MQTT 在背景運作,不會卡住視窗的滑鼠點擊動作。
7. 事件處理函數
on_connect: 當連上伺服器時,指示燈轉為綠色,並訂閱溫濕度主題。on_message: 當 ESP32 回傳數據時,解析數值,並呼叫root.after(0, self.update_charts)。注意:這裡使用
after是為了確保繪圖動作是在視窗的主執行緒中完成,避免程式崩潰。publish_led: 呼叫client.publish()將按鈕對應的字串送往 MQTT Broker。
8. 繪圖更新 update_charts
def update_charts(self):
self.ax1.clear() # 清除舊圖
# ... 繪製 Pie 圖 ...
self.ax1.pie([self.temp_val, max(0.1, 50-self.temp_val)], ...)
# ...
self.canvas_plt.draw() # 刷新畫布顯示
這是視覺化的核心。我們用
50-當前溫度或100-當前濕度來算出圓餅圖的剩餘比例。max(0.1, ...)是為了防止數據超過範圍導致繪圖錯誤。
9. 主程式進入點
if __name__ == "__main__":
root = tk.Tk() # 初始化視窗
app = MQTTApp(root) # 啟動我們的程式邏輯
root.mainloop() # 保持視窗運行
這份程式展示了現代 IoT 應用的標準架構:硬體採集 (ESP32) -> 雲端中轉 (MQTT) -> 桌面監控 (Python)。














