2026年10月6日 星期二

MQTT 與 IoT 雙向通訊|Pico 2 W

Pico 2 W × Thonny|第 6 次課程

MQTT 與 IoT 雙向通訊

前一篇已把感測資料整理成 JSON。本篇將資料放進 MQTT 訊息,讓 Pico 2 W 發布感測資料,也訂閱控制主題接收命令。這樣裝置不只會「上傳」,也能從網路接收控制,形成 IoT 的雙向通訊。

一、MQTT 的三個角色

MQTT 使用 Broker(訊息代理伺服器)中轉訊息。Publisher 將訊息發布到某個 Topic;Subscriber 訂閱感興趣的 Topic。Broker 依照訂閱關係轉送訊息,因此 Publisher 通常不需要知道每一個 Subscriber 的網路位置。

Publisher 發布者把訊息送到指定 Topic,例如 Pico 上傳感測資料。
Broker 代理伺服器接收、管理並轉送訊息,是通訊中介。
Subscriber 訂閱者訂閱 Topic 並接收訊息,例如電腦 Dashboard。

同一台 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()檢查是否有新訊息。這個程式每五秒發布一次示範資料,實際量測值需由感測器取得。

套件與 Broker:不同 MicroPython 韌體不一定預先包含 umqtt.simple,需先確認課堂環境的套件安裝方式。此範例使用提示文字作為 Broker 主機,並非可直接連線的服務。

六、MQTT 與 HTTP 如何搭配?

HTTP常見為 Request/Response,適合網頁與 API 的一次性資料交換。
MQTT使用 Publish/Subscribe,適合設備持續發布遙測資料或接收命令。
共同點兩者都在 IP 網路上運作,都必須考慮斷線與錯誤處理。

HTTP 和 MQTT 各有適合的情境,IoT 系統也可以同時使用兩者。例如設備透過 MQTT 傳送即時遙測,而設定頁面或其他服務使用 HTTP API。

七、斷線與安全性

Wi-Fi 或 Broker 可能中斷,設備程式要能顯示連線狀態,並設計清楚的重新連線流程。重新連線後,通常也要重新訂閱控制 Topic。不要在故障時無限快速重試;可採用有限次數與間隔,並讓錯誤訊息容易辨識。

保護 Broker 憑證:不要把真實帳密、Token 或 API Key 放進公開投影片、部落格或 Git 儲存庫。控制 Topic 會影響實體輸出,應使用可信任的 Broker、限制可發布者,並在接收端檢查命令內容。

八、實作任務:完成第一個 MQTT IoT Node

  1. 連上課堂指定 Wi-Fi。
  2. 連接測試 MQTT Broker。
  3. 訂閱設備的 control Topic。
  4. 每五秒發布一筆感測器 JSON 到 telemetry Topic。
  5. 從 Dashboard 或測試用戶端發布控制命令,確認 Pico 收到後能更新 GPIO。
  6. 挑戰:Wi-Fi 或 Broker 斷線後,顯示狀態並完成重新連線與重新訂閱。

測試時,建議同時觀察 Pico 的 Thonny Shell 與 Broker 用戶端畫面,確認每一筆訊息的 Topic、Payload 和方向。

六次課程如何串成完整資料流

  1. 第 1 次:控制硬體,建立 GPIO 基礎。
  2. 第 2 次:連上 Wi-Fi,取得網路資訊。
  3. 第 3 次:建立 Web Server,讓瀏覽器控制 Pico。
  4. 第 4 次:透過 HTTP 與 API 交換資料。
  5. 第 5 次:以 JSON 建立一致的資料格式。
  6. 第 6 次:以 MQTT 發布遙測資料並接收控制命令。

完成這六次課程後,就具備 IoT 專題的基本通訊流程。下一階段可以接續設計 Dashboard 或 IoT 平台,讓資料能被觀察、整理與應用。

Pico 2 W × Thonny|第 6 次課程

MQTT 與 IoT 雙向通訊

前一篇已把感測資料整理成 JSON。本篇將資料放進 MQTT 訊息,讓 Pico 2 W 發布感測資料,也訂閱控制主題接收命令。這樣裝置不只會「上傳」,也能從網路接收控制,形成 IoT 的雙向通訊。

一、MQTT 的三個角色

MQTT 使用 Broker(訊息代理伺服器)中轉訊息。Publisher 將訊息發布到某個 Topic;Subscriber 訂閱感興趣的 Topic。Broker 依照訂閱關係轉送訊息,因此 Publisher 通常不需要知道每一個 Subscriber 的網路位置。

Publisher 發布者把訊息送到指定 Topic,例如 Pico 上傳感測資料。
Broker 代理伺服器接收、管理並轉送訊息,是通訊中介。
Subscriber 訂閱者訂閱 Topic 並接收訊息,例如電腦 Dashboard。

同一台 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()檢查是否有新訊息。這個程式每五秒發布一次示範資料,實際量測值需由感測器取得。

套件與 Broker:不同 MicroPython 韌體不一定預先包含 umqtt.simple,需先確認課堂環境的套件安裝方式。此範例使用提示文字作為 Broker 主機,並非可直接連線的服務。

六、MQTT 與 HTTP 如何搭配?

HTTP常見為 Request/Response,適合網頁與 API 的一次性資料交換。
MQTT使用 Publish/Subscribe,適合設備持續發布遙測資料或接收命令。
共同點兩者都在 IP 網路上運作,都必須考慮斷線與錯誤處理。

HTTP 和 MQTT 各有適合的情境,IoT 系統也可以同時使用兩者。例如設備透過 MQTT 傳送即時遙測,而設定頁面或其他服務使用 HTTP API。

七、斷線與安全性

Wi-Fi 或 Broker 可能中斷,設備程式要能顯示連線狀態,並設計清楚的重新連線流程。重新連線後,通常也要重新訂閱控制 Topic。不要在故障時無限快速重試;可採用有限次數與間隔,並讓錯誤訊息容易辨識。

保護 Broker 憑證:不要把真實帳密、Token 或 API Key 放進公開投影片、部落格或 Git 儲存庫。控制 Topic 會影響實體輸出,應使用可信任的 Broker、限制可發布者,並在接收端檢查命令內容。

八、實作任務:完成第一個 MQTT IoT Node

  1. 連上課堂指定 Wi-Fi。
  2. 連接測試 MQTT Broker。
  3. 訂閱設備的 control Topic。
  4. 每五秒發布一筆感測器 JSON 到 telemetry Topic。
  5. 從 Dashboard 或測試用戶端發布控制命令,確認 Pico 收到後能更新 GPIO。
  6. 挑戰:Wi-Fi 或 Broker 斷線後,顯示狀態並完成重新連線與重新訂閱。

測試時,建議同時觀察 Pico 的 Thonny Shell 與 Broker 用戶端畫面,確認每一筆訊息的 Topic、Payload 和方向。

六次課程如何串成完整資料流

  1. 第 1 次:控制硬體,建立 GPIO 基礎。
  2. 第 2 次:連上 Wi-Fi,取得網路資訊。
  3. 第 3 次:建立 Web Server,讓瀏覽器控制 Pico。
  4. 第 4 次:透過 HTTP 與 API 交換資料。
  5. 第 5 次:以 JSON 建立一致的資料格式。
  6. 第 6 次:以 MQTT 發布遙測資料並接收控制命令。

完成這六次課程後,就具備 IoT 專題的基本通訊流程。下一階段可以接續設計 Dashboard 或 IoT 平台,讓資料能被觀察、整理與應用。

沒有留言:

張貼留言