找回密碼
 立即註冊
惟家LINE群QRCODE
    查看: 1|回覆: 0

    MQTT 深入:自己發訊息給 HA,做出任何你想要的實體

    [複製鏈接]

    !lvup!   100%

    363

    主題

    27

    回帖

    2200萬

    積分

    管理員

    積分
    22005752
    發表於 3 天前 | 顯示全部樓層 |閱讀模式
    MQTT 是智慧家庭的萬用膠水。

    懂了它,你可以把任何東西接進 HA。



    基本概念

    MQTT 是一個「訊息轉發」的協定。


    • Broker(中介) —— 中央的郵局,通常是 Mosquitto
    • Publish(發布) —— 寄信到某個主題
    • Subscribe(訂閱) —— 我要收某個主題的信


    主題(Topic)的樣子
    1. zigbee2mqtt/客廳溫濕度
    2. home/浴室/濕度
    3. esphome/門口/狀態
    複製代碼

    用 / 分層,可以用萬用字元訂閱
    1. zigbee2mqtt/+       所有直屬的裝置(一層)
    2. zigbee2mqtt/#       所有底下的(任意層)
    複製代碼

    為什麼要懂它


    • Zigbee2MQTT、ESPHome(部分)、Tasmota 都用它
    • 可以接任何能發 HTTP 或 MQTT 的東西
    • 可以自己造實體(下面的重點)
    • 可以跟其他系統橋接(Node-RED、Python 腳本、NAS)


    安裝


    • 設定 → 附加元件 → Mosquitto broker
    • 安裝、啟動
    • 設定 → 裝置與服務 → MQTT 整合(通常會自動出現)


    建立一個專用帳號


    • 設定 → 人員 → 使用者 → 新增使用者
    • 取名 mqtt,設一個密碼
    • 取消勾選「可以登入」(如果有這個選項)


    Mosquitto 附加元件預設會用 HA 的使用者帳號做驗證。



    MQTT Discovery:自己造一個實體

    這是最強大的部分。

    只要發一則特定格式的訊息,HA 就會自動建立一個實體。

    主題的格式
    1. homeassistant/<類型>/<物件ID>/config
    複製代碼

    範例:建立一個溫度感測器

    主題
    1. homeassistant/sensor/我的溫度計/config
    複製代碼

    內容
    1. {
    2.   "name": "我的溫度計",
    3.   "unique_id": "my_temp_001",
    4.   "state_topic": "home/客房/溫度",
    5.   "unit_of_measurement": "°C",
    6.   "device_class": "temperature",
    7.   "state_class": "measurement",
    8.   "device": {
    9.     "identifiers": ["my_device_001"],
    10.     "name": "客房感測器",
    11.     "manufacturer": "自己做的",
    12.     "model": "v1"
    13.   }
    14. }
    複製代碼

    發出去之後,HA 裡就會出現 sensor.我的溫度計。

    然後發數值
    1. 主題:home/客房/溫度
    2. 內容:26.5
    複製代碼

    就這樣。

    retain 旗標一定要開

    發 config 的時候要加 retain


    • 這樣 broker 會記住這則訊息
    • HA 重啟之後會重新收到,實體不會消失
    • 沒有 retain 的話,HA 重啟後實體就不見了


    用開發者工具測試


    • 開發者工具 → 動作
    • mqtt.publish

    1. action: mqtt.publish
    2. data:
    3.   topic: homeassistant/sensor/我的溫度計/config
    4.   retain: true
    5.   payload: >-
    6.     {"name":"我的溫度計","unique_id":"my_temp_001",
    7.      "state_topic":"home/客房/溫度","unit_of_measurement":"°C",
    8.      "device_class":"temperature","state_class":"measurement"}
    複製代碼



    可以造哪些實體
    1. sensor           數值
    2. binary_sensor    開/關的狀態
    3. switch           開關(可控制)
    4. light            燈
    5. climate          冷氣
    6. cover            窗簾
    7. fan              風扇
    8. lock             鎖
    9. button           按鈕
    10. number           數字輸入
    11. select           下拉選單
    12. text             文字
    13. device_tracker   位置追蹤
    14. camera           攝影機(圖片)
    15. event            事件
    複製代碼

    造一個可以控制的開關
    1. {
    2.   "name": "我的開關",
    3.   "unique_id": "my_switch_001",
    4.   "state_topic": "home/裝置/開關/狀態",
    5.   "command_topic": "home/裝置/開關/設定",
    6.   "payload_on": "ON",
    7.   "payload_off": "OFF",
    8.   "optimistic": false
    9. }
    複製代碼


    • state_topic —— HA 從這裡讀狀態
    • command_topic —— HA 對這裡發指令
    • 你的程式訂閱 command_topic,收到之後做事,然後發回 state_topic


    用 Python 接任何東西進 HA
    1. import json
    2. import paho.mqtt.client as mqtt
    3. c = mqtt.Client()
    4. c.username_pw_set("mqtt", "密碼")
    5. c.connect("192.168.1.10", 1883)
    6. # 1. 宣告一個感測器
    7. config = {
    8.     "name": "伺服器溫度",
    9.     "unique_id": "server_temp",
    10.     "state_topic": "myserver/temp",
    11.     "unit_of_measurement": "°C",
    12.     "device_class": "temperature",
    13.     "state_class": "measurement",
    14. }
    15. c.publish("homeassistant/sensor/server_temp/config",
    16.           json.dumps(config, ensure_ascii=False), retain=True)
    17. # 2. 定期發數值
    18. import time
    19. while True:
    20.     溫度 = 讀取溫度()          # 你自己的函式
    21.     c.publish("myserver/temp", str(溫度))
    22.     time.sleep(60)
    複製代碼

    用途


    • 把 NAS 的溫度、硬碟狀態接進 HA
    • 把路由器的流量接進來
    • 把任何有 API 的服務接進來
    • 自己寫的程式回報狀態


    可用性(availability):讓 HA 知道裝置離線
    1. {
    2.   "name": "我的裝置",
    3.   "state_topic": "home/device/state",
    4.   "availability_topic": "home/device/status",
    5.   "payload_available": "online",
    6.   "payload_not_available": "offline"
    7. }
    複製代碼

    搭配「遺囑(Last Will)」
    1. c.will_set("home/device/status", "offline", retain=True)
    2. c.connect(...)
    3. c.publish("home/device/status", "online", retain=True)
    複製代碼

    遺囑的意思是「我斷線的時候,請 broker 幫我發這則訊息」 ——
    程式當掉或斷網,HA 會自動知道那個裝置離線了。

    這是 MQTT 最優雅的設計之一。



    除錯工具

    一、HA 的 MQTT 整合有監聽功能


    • 設定 → 裝置與服務 → MQTT → 設定
    • 監聽主題:填 # 可以看到所有訊息


    二、MQTT Explorer(電腦軟體)


    • 視覺化的主題樹
    • 可以看歷史、可以手動發訊息
    • 免費,強烈推薦


    三、命令列
    1. # 訂閱所有訊息
    2. mosquitto_sub -h 192.168.1.10 -u mqtt -P 密碼 -t '#' -v
    3. # 發一則訊息
    4. mosquitto_pub -h 192.168.1.10 -u mqtt -P 密碼 \
    5.   -t 'home/測試' -m 'hello'
    複製代碼

    常見問題

    一、實體出現但永遠是 unknown


    • state_topic 打錯
    • 還沒發過數值(config 只是宣告,要另外發值)
    • 發的數值格式不對(例如 JSON 但沒設 value_template)


    二、HA 重啟之後實體不見了


    • config 訊息沒有加 retain


    三、實體重複出現


    • unique_id 改了,HA 當成新裝置
    • 要刪舊的:發一則空訊息到那個 config 主題(帶 retain)

    1. action: mqtt.publish
    2. data:
    3.   topic: homeassistant/sensor/舊的ID/config
    4.   retain: true
    5.   payload: ""
    複製代碼

    四、JSON 格式的資料怎麼拆

    很多裝置會發一整包 JSON
    1. {"temperature": 26.5, "humidity": 60, "battery": 85}
    複製代碼

    用 value_template 取值
    1. {
    2.   "name": "溫度",
    3.   "state_topic": "home/裝置",
    4.   "value_template": "{{ value_json.temperature }}"
    5. }
    複製代碼

    一則訊息可以餵好幾個實體
    各自用不同的 value_template 取不同的欄位。

    這是 Zigbee2MQTT 的做法 —— 一個裝置發一包 JSON,HA 拆成好幾個實體。

    ---

    下一篇:智慧家庭的第一年 ——
    如果重來一次,我會用什麼順序。
    您需要登入後纔可以回帖 登入 | 立即註冊

    本版積分規則

    Archiver|手機版|惟家的智能論壇

    GMT+8, 2026-9-24 11:18 , Processed in 0.082474 second(s), 24 queries .

    快速回覆 返回頂部 返回列表