|
|
用 Zigbee2MQTT 的人都知道,裝置配對完就自動出現在 HA 裡。
那個魔法叫 MQTT Discovery。
搞懂它之後,你可以把任何東西變成 HA 裡的實體 ——
一個 Python 腳本、一台舊機器、甚至是網頁爬下來的數字。

原理:一個特定格式的訊息
HA 的 MQTT 整合會訂閱一個前綴(預設 homeassistant/)底下的設定主題。
只要你往那裡發一則符合格式的 JSON,HA 就會生出一個實體。
主題格式:
- homeassistant/<元件類型>/<物件ID>/config
複製代碼
動手做:一個溫度感測器
先發設定訊息(注意要 retain):
- mosquitto_pub -h 192.168.1.20 -u mqttuser -P mqttpass \
- -t "homeassistant/sensor/study_temp/config" -r \
- -m '{
- "name": "書房溫度",
- "unique_id": "study_temp_001",
- "state_topic": "home/study/temperature",
- "unit_of_measurement": "°C",
- "device_class": "temperature",
- "state_class": "measurement",
- "device": {
- "identifiers": ["study_sensor_box"],
- "name": "書房感測盒",
- "manufacturer": "DIY",
- "model": "ESP32-v1"
- }
- }'
複製代碼
然後發實際的值(這個不要 retain,或者要看你的需求):
- mosquitto_pub -h 192.168.1.20 -u mqttuser -P mqttpass \
- -t "home/study/temperature" -m "26.4"
複製代碼
去 HA 看,書房溫度就出現了。
-r(retain)為什麼重要
retain 的意思是「broker 幫我記住這則訊息,之後有人訂閱就直接給他」。
設定訊息一定要 retain,否則HA 重啟後那個實體就消失了 ——
因為它重新訂閱的時候,沒有人再發一次設定。
這也是為什麼刪除 MQTT 裝置的方法是發一則空訊息到同一個設定主題:
- mosquitto_pub -h 192.168.1.20 -t "homeassistant/sensor/study_temp/config" -r -m ""
複製代碼

做一個開關(雙向)
感測器是單向的(裝置 → HA)。開關要雙向:
- {
- "name": "抽風機",
- "unique_id": "bath_fan_001",
- "state_topic": "home/bath/fan/state",
- "command_topic": "home/bath/fan/set",
- "payload_on": "ON",
- "payload_off": "OFF",
- "availability_topic": "home/bath/fan/available",
- "device": {
- "identifiers": ["bath_controller"],
- "name": "浴室控制器"
- }
- }
複製代碼
- state_topic — 你的裝置在這裡回報目前狀態
- command_topic — HA 在這裡下指令,你的裝置要訂閱它
- availability_topic — 發 online/offline,裝置掉線時 HA 會顯示「不可用」
availability_topic 強烈建議加。
沒有它的話,裝置斷線了 HA 還是顯示最後的狀態,你會被騙。
搭配 MQTT 的遺囑訊息(Last Will):裝置連線時設定
「如果我斷線,幫我發 offline 到這個主題」,斷電也會正確顯示離線。
device 區塊讓多個實體合併成一台裝置
同一個 identifiers 的實體,在 HA 裡會被歸到同一台裝置底下。
所以一個 ESP32 上的溫度、濕度、光照,發三則設定訊息但 device.identifiers 相同,
HA 裡就會是一台「書房感測盒」有三個實體。乾淨很多。
實際應用:用 Python 把任何數據送進 HA
- import json, time
- import paho.mqtt.client as mqtt
- c = mqtt.Client()
- c.username_pw_set("mqttuser", "mqttpass")
- c.connect("192.168.1.20", 1883)
- # 開機時發一次設定(retain)
- c.publish("homeassistant/sensor/rain_prob/config", json.dumps({
- "name": "今日降雨機率",
- "unique_id": "rain_prob_tw",
- "state_topic": "home/weather/rain_prob",
- "unit_of_measurement": "%",
- "icon": "mdi:weather-rainy",
- "device": {"identifiers": ["weather_scraper"], "name": "天氣抓取"}
- }, ensure_ascii=False), retain=True)
- while True:
- value = get_rain_probability() # 你自己的取值邏輯
- c.publish("home/weather/rain_prob", str(value))
- time.sleep(1800)
複製代碼
把這個腳本丟到 NAS 上用 Docker 跑,就多了一個 HA 原生沒有的感測器。
除錯:一定要會看 MQTT 流量
- # 看所有 discovery 訊息
- mosquitto_sub -h 192.168.1.20 -u mqttuser -P mqttpass \
- -t "homeassistant/#" -v
- # 看某個裝置的所有主題
- mosquitto_sub -h 192.168.1.20 -u mqttuser -P mqttpass \
- -t "home/study/#" -v
複製代碼
或者用 MQTT Explorer(圖形介面,Windows/Mac 都有),
可以樹狀瀏覽整個 broker,找問題快很多。
HA 裡也能直接聽:設定 → 裝置與服務 → MQTT → 設定 → 監聽主題。
常見問題
- 實體沒出現 → JSON 格式錯了。用 jq . 先驗證一次
- 實體出現但狀態是 unknown → 設定發了但值還沒發,或 state_topic 打錯
- 重啟後消失 → 設定訊息沒有 retain
- 名稱重複或變成 sensor_2 → unique_id 撞到了,換一個
---
我自己用這招把一台沒有任何智能功能的除濕機接進來 ——
用智能插座量功率,Python 判斷「有沒有在運轉」,
發一個 binary_sensor 進 HA。成本不到四百塊。
有人用 MQTT Discovery 做過什麼有趣的東西嗎? |
|