|
|
這些都是我自己或別人真的踩過的。
每一個都給「錯在哪」和「該怎麼寫」。

一、感應燈一直開開關關
錯誤的寫法:
- triggers:
- - trigger: state
- entity_id: binary_sensor.人體
- to: "off"
- actions:
- - action: light.turn_off
複製代碼
問題:人還在,只是剛好沒動,燈就關了。
正確的寫法:
- mode: restart ← 這個一定要
- triggers:
- - trigger: state
- entity_id: binary_sensor.人體
- to: "on"
- actions:
- - action: light.turn_on
- - wait_for_trigger:
- - trigger: state
- entity_id: binary_sensor.人體
- to: "off"
- for: "00:03:00" ← 沒人三分鐘才算
- timeout: "02:00:00"
- continue_on_timeout: true
- - action: light.turn_off
複製代碼
三個重點:
- mode: restart —— 又有人的時候重新計時
- for: 3 分鐘 —— 給緩衝
- timeout —— 感應器卡住時的保險
或者更簡單:在感應器上設 delay_off(上一篇講過)。
二、mode 沒設,自動化被默默忽略
症狀:自動化偶爾不動,但你找不出規律。
原因:
- 預設是 mode: single
- 前一次還在跑(例如卡在 delay)的時候,新的觸發會被丟掉
- 日誌裡會有警告,但你不會去看
怎麼發現:
- 設定 → 系統 → 日誌 → 搜尋 "already running"
複製代碼
解法:任何有 delay 或 wait 的自動化,想清楚 mode 要設什麼。

三、用了 numeric_state 但感測器變成 unavailable
症狀:自動化在裝置離線的時候亂觸發,或者完全不觸發。
問題:
- triggers:
- - trigger: numeric_state
- entity_id: sensor.溫度
- above: 28
複製代碼
感測器從 unavailable 變回 26 度的時候,
HA 可能把它當成「跨越了門檻」。
正確的寫法:加條件
- conditions:
- - condition: template
- value_template: "{{ has_value('sensor.溫度') }}"
複製代碼
或者在感測器端處理(用 availability,見上一篇)。
四、自動化互相觸發,變成迴圈
經典的例子:
- 自動化 A:燈開了 → 記錄狀態
- 自動化 B:記錄狀態改變 → 同步燈
複製代碼
症狀:CPU 100%、日誌爆量、HA 卡住。
怎麼發現:
- 看自動化的「追蹤」 —— 會顯示它被觸發幾百次
- 日誌裡會有 "Detected a loop" 之類的警告
解法:
- 用 context 判斷(上一篇的手動偵測就是這招)
- 或者加一個條件擋掉:
- - condition: template
- value_template: "{{ trigger.to_state.context.parent_id == none }}"
複製代碼
五、時間條件跨午夜寫錯
錯誤:
- - condition: time
- after: "07:00:00"
- before: "23:00:00"
複製代碼
這個是對的(白天)。但下面這個很多人寫錯:
- # 想表達「晚上 11 點到早上 7 點」
- - condition: time
- after: "07:00:00"
- before: "23:00:00" ← 這是反的!
複製代碼
正確:
- - condition: time
- after: "23:00:00"
- before: "07:00:00"
複製代碼
HA 的 time condition 支援跨午夜 ——
after 比 before 晚的話,它知道你是要跨日。
測試方法:在開發者工具的模板裡測:
- {{ today_at('23:00') <= now() or now() < today_at('07:00') }}
複製代碼

六、for 用在 numeric_state 上的陷阱
- - trigger: numeric_state
- entity_id: sensor.溫度
- above: 28
- for: "00:10:00"
複製代碼
意思是「連續超過 28 度十分鐘」。
陷阱:中途只要掉到 28 以下一秒,計時就重來。
如果你的感測器會小幅震盪(27.9 / 28.1 跳來跳去),
這個自動化可能永遠不會觸發。
解法:
- 門檻拉開(用 30 而不是 28)
- 或者在感測器端加平滑(filter 或 statistics 的移動平均)
七、忘記自動化本身會被重新載入
症狀:改了 YAML 之後自動化沒生效。
原因:
- YAML 的自動化要「重新載入自動化」才會生效
- 開發者工具 → YAML → 重新載入自動化
但是:
- 新增 template sensor 要重新載入「模板實體」
- 改 configuration.yaml 的某些區塊要重啟
- 不確定就重啟
重要:重新載入會讓「正在跑的自動化」中斷,
卡在 delay 的那些會直接消失。
八、條件寫在錯的地方
conditions 區塊只在「觸發的瞬間」檢查一次。
- triggers:
- - trigger: state
- entity_id: binary_sensor.人體
- to: "on"
- conditions:
- - condition: state
- entity_id: sun.sun
- state: below_horizon
- actions:
- - action: light.turn_on
- - delay: "00:30:00"
- - action: light.turn_off
複製代碼
問題:如果在這 30 分鐘內天亮了,燈還是會照樣關掉
(這個例子沒差),但如果是「只在天黑時做某事」的長流程就會出錯。
要在中途再檢查的話,把條件放進 actions:
- actions:
- - action: light.turn_on
- - delay: "00:30:00"
- - condition: state ← 動作區塊裡的條件
- entity_id: sun.sun
- state: below_horizon
- - action: light.turn_off
複製代碼
actions 裡的 condition 不成立會直接停止整個自動化。

九、通知洗版
症狀:門磁一直開關,手機響三十次。
解法一:用 for
- - trigger: state
- entity_id: binary_sensor.門
- to: "on"
- for: "00:05:00"
複製代碼
解法二:用 mode: single 加冷卻
- mode: single
- max_exceeded: silent
- actions:
- - action: notify.mobile_app_phone
- data: ...
- - delay: "00:10:00" ← 這段期間不會再觸發
複製代碼
這招很聰明:single 模式下,還在 delay 的時候新觸發會被忽略,
等於天然的冷卻時間。
解法三:用 input_datetime 記錄上次通知時間
最精確但最囉嗦。
十、沒有「自動化壞了會怎樣」的規劃
這是最嚴重的一個。
問自己:
- HA 掛了,我還能開燈嗎?
- 網路斷了,門還打得開嗎?
- 感測器沒電了,會發生什麼?
原則:
- 保留實體開關(不要拆掉)
- 重要的東西用 Zigbee 綁定(不經過 HA)
- 任何「等待」都要有 timeout
- 電池裝置設低電量提醒
低電量提醒的寫法:
- template:
- - binary_sensor:
- - name: 有裝置快沒電
- state: >
- {{ states.sensor
- | selectattr('attributes.device_class', 'defined')
- | selectattr('attributes.device_class', 'eq', 'battery')
- | selectattr('state', 'is_number')
- | selectattr('state', 'lt', '20')
- | list | count > 0 }}
- attributes:
- 清單: >
- {{ states.sensor
- | selectattr('attributes.device_class', 'defined')
- | selectattr('attributes.device_class', 'eq', 'battery')
- | selectattr('state', 'is_number')
- | selectattr('state', 'lt', '20')
- | map(attribute='name') | list }}
複製代碼
一個很有用的除錯習慣
每個自動化都加一個「追蹤用」的動作:
- actions:
- - action: logbook.log
- data:
- name: 浴室除濕
- message: >
- 開始(濕度差 {{ states('sensor.浴室濕度差') }})
- - ...實際的動作
複製代碼
這樣在「記錄簿」裡就能看到完整的事件流,
出問題的時候很好回溯。
也可以用自動化的「追蹤」功能:
- 設定 → 自動化 → 點那個 → 右上角三個點 → 追蹤
- 會顯示最近幾次執行走了哪些分支、每一步的結果
- 這是 HA 最好用的除錯工具,很多人不知道
---
下一篇:通知系統的設計 ——
怎麼讓重要的訊息不被淹沒。 |
|