Pico 2 W × Thonny|第 6 次課程
MQTT 與 IoT 雙向通訊
前一篇已把感測資料整理成 JSON。本篇將資料放進 MQTT 訊息,讓 Pico 2 W 發布感測資料,也訂閱控制主題接收命令。這樣裝置不只會「上傳」,也能從網路接收控制,形成 IoT 的雙向通訊。
一、MQTT 的三個角色
MQTT 使用 Broker(訊息代理伺服器)中轉訊息。Publisher 將訊息發布到某個 Topic;Subscriber 訂閱感興趣的 Topic。Broker 依照訂閱關係轉送訊息,因此 Publisher 通常不需要知道每一個 Subscriber 的網路位置。
同一台 Pico 可以同時扮演 Publisher 與 Subscriber:它發布感測值,也訂閱控制命令。
二、Topic 是訊息的分類路徑
Topic 用來標示訊息的類別或用途。好的命名方式能看出位置、設備與功能,讓多個裝置加入時仍然容易管理。
farm/room01/pico01/telemetry
farm/room01/pico01/status
farm/room01/pico01/control
farm/room02/pico02/telemetry
telemetry:感測器或設備定期發布的遙測資料。status:設備目前狀態。control:送往設備的控制命令。
Topic 名稱要在發布端和訂閱端完全一致;斜線分隔的層級也要保持規則一致。
三、Publish:Pico 發布感測資料
發布時要指定 Topic 和 Payload(訊息內容)。Topic 說明這是哪一類訊息,Payload 則放實際資料。本課程沿用上一堂的 JSON 格式,因此接收端可以依照欄位名稱解析資料。
import json
topic_telemetry = b"farm/room01/pico01/telemetry"
# 這些數字只用來示範資料格式
payload = {
"temperature": 28.3,
"humidity": 71.2
}
client.publish(
topic_telemetry,
json.dumps(payload)
)
範例中的數字只是格式示意,不是實際場域資料。實作時應換成感測器讀值,並確認欄位名稱、型態與單位已事先約定。
四、Subscribe:Pico 訂閱控制命令
Dashboard 或電腦可以把控制命令發布到設備的 control Topic。Pico 訂閱這個 Topic,收到訊息後解析 JSON,再依內容控制 GPIO。
import json
from machine import Pin
led = Pin("LED", Pin.OUT)
def on_message(topic, message):
print("Topic:", topic)
print("Message:", message)
try:
command = json.loads(message.decode())
if "relay" in command:
led.value(1 if command["relay"] else 0)
print("LED updated:", led.value())
except (ValueError, KeyError) as error:
print("Invalid command:", error)
topic_control = b"farm/room01/pico01/control"
client.set_callback(on_message)
client.subscribe(topic_control)
命令可以是 {"relay": true}或 {"relay": false}。實際系統應依設備功能設計命令欄位,並確認收到的內容合法後才執行控制。
五、Pico 連接 Broker 並雙向交換訊息
以下是教學架構範例,假設 Pico 已先連上 Wi-Fi,且韌體已提供相容的 umqtt.simple用戶端。請把 Broker 主機、帳號與密碼替換成教師提供的測試設定。Broker 的網路位置與連線方式依服務而異。
import json
import time
from umqtt.simple import MQTTClient
BROKER = "請填入 MQTT Broker 主機"
CLIENT_ID = b"pico-room01-device01"
TOPIC_TELEMETRY = b"farm/room01/pico01/telemetry"
TOPIC_CONTROL = b"farm/room01/pico01/control"
# 若測試 Broker 不需要帳密,可依用戶端規格省略相關參數
client = MQTTClient(CLIENT_ID, BROKER)
def on_message(topic, message):
print("Received:", topic, message)
# 在此解析控制命令並更新 GPIO
client.set_callback(on_message)
client.connect()
client.subscribe(TOPIC_CONTROL)
print("MQTT connected and subscribed")
while True:
# 示範內容;實作時改成感測器的實際讀值
telemetry = {
"temperature": 28.3,
"humidity": 71.2
}
client.publish(
TOPIC_TELEMETRY,
json.dumps(telemetry)
)
# 檢查是否有訂閱訊息;有訊息時會呼叫 on_message
client.check_msg()
time.sleep(5)
set_callback()設定收到訊息時要執行的函式;subscribe()訂閱控制 Topic;publish()發布感測資料;check_msg()檢查是否有新訊息。這個程式每五秒發布一次示範資料,實際量測值需由感測器取得。
umqtt.simple,需先確認課堂環境的套件安裝方式。此範例使用提示文字作為 Broker 主機,並非可直接連線的服務。六、MQTT 與 HTTP 如何搭配?
HTTP 和 MQTT 各有適合的情境,IoT 系統也可以同時使用兩者。例如設備透過 MQTT 傳送即時遙測,而設定頁面或其他服務使用 HTTP API。
七、斷線與安全性
Wi-Fi 或 Broker 可能中斷,設備程式要能顯示連線狀態,並設計清楚的重新連線流程。重新連線後,通常也要重新訂閱控制 Topic。不要在故障時無限快速重試;可採用有限次數與間隔,並讓錯誤訊息容易辨識。
八、實作任務:完成第一個 MQTT IoT Node
- 連上課堂指定 Wi-Fi。
- 連接測試 MQTT Broker。
- 訂閱設備的 control Topic。
- 每五秒發布一筆感測器 JSON 到 telemetry Topic。
- 從 Dashboard 或測試用戶端發布控制命令,確認 Pico 收到後能更新 GPIO。
- 挑戰:Wi-Fi 或 Broker 斷線後,顯示狀態並完成重新連線與重新訂閱。
測試時,建議同時觀察 Pico 的 Thonny Shell 與 Broker 用戶端畫面,確認每一筆訊息的 Topic、Payload 和方向。
六次課程如何串成完整資料流
- 第 1 次:控制硬體,建立 GPIO 基礎。
- 第 2 次:連上 Wi-Fi,取得網路資訊。
- 第 3 次:建立 Web Server,讓瀏覽器控制 Pico。
- 第 4 次:透過 HTTP 與 API 交換資料。
- 第 5 次:以 JSON 建立一致的資料格式。
- 第 6 次:以 MQTT 發布遙測資料並接收控制命令。
完成這六次課程後,就具備 IoT 專題的基本通訊流程。下一階段可以接續設計 Dashboard 或 IoT 平台,讓資料能被觀察、整理與應用。