|
|
自動化寫到一定數量之後,會開始遇到一種很難查的問題:
東西會自己動,但你不知道為什麼。
原因幾乎都一樣:你從來沒有想清楚「家」有哪些狀態。

症狀長什麼樣
- 離家模式開著,但燈還是會被感應器打開
- 睡覺時冷氣被「回家自動化」重新打開
- 兩個自動化搶著控制同一盞燈,燈一直閃
- 度假模式忘了關,回家後什麼都不會動
這些都不是程式錯誤,是狀態衝突。
核心觀念:家在任何時刻只能處於一種主要狀態
先把家的狀態列出來。我家是五個:
- 在家-日間
- 在家-夜間
- 睡覺
- 外出
- 度假(超過一天不在)
五個以內最好。超過八個的話,你大概是把「情境」(看電影、吃飯)
跟「狀態」混在一起了 —— 那些應該是另一個維度。
用 input_select 實作
- input_select:
- house_mode:
- name: 家的狀態
- options:
- - 在家-日間
- - 在家-夜間
- - 睡覺
- - 外出
- - 度假
- initial: 在家-日間
- icon: mdi:home-heart
複製代碼
接著畫轉換圖
不用畫得漂亮,紙筆就好。重點是回答三個問題:
- 從 A 可以到哪些狀態?
- 什麼事件會造成這個轉換?
- 轉換的時候要做什麼?
我家的轉換規則:
- 在家-日間 --(日落後 30 分)--> 在家-夜間
- 在家-夜間 --(23:00 或按睡覺鈕)--> 睡覺
- 睡覺 --(06:00 或偵測到起床)--> 在家-日間
- 任何狀態 --(所有人離家 10 分鐘)--> 外出
- 外出 --(有人回家)--> 在家-日間 或 在家-夜間(看時間)
- 外出 --(超過 24 小時)--> 度假
- 度假 --(有人回家)--> 在家-日間
複製代碼

實作:一個自動化管所有轉換
關鍵在那些 "{{ 目前 == ... }}" 條件。
它們確保只有合法的轉換會發生。
睡覺中不會因為「入夜」又跑回「在家-夜間」。
然後:所有其他自動化都只看狀態
這是整套設計的重點。
- # 感應燈
- alias: 走道感應燈
- triggers:
- - trigger: state
- entity_id: binary_sensor.走道感應
- to: "on"
- conditions:
- - condition: not
- conditions:
- - condition: state
- entity_id: input_select.house_mode
- state: 度假
- actions:
- - action: light.turn_on
- target: {entity_id: light.走道}
- data:
- brightness_pct: >
- {% set m = states('input_select.house_mode') %}
- {{ 5 if m == '睡覺' else (30 if m == '在家-夜間' else 80) }}
- mode: restart
複製代碼
一個實體、一個判斷,所有自動化行為一致。
狀態轉換時要做的事,另外寫
- alias: 狀態轉換時的動作
- triggers:
- - trigger: state
- entity_id: input_select.house_mode
- actions:
- - choose:
- - conditions: "{{ trigger.to_state.state == '外出' }}"
- sequence:
- - action: scene.turn_on
- target: {entity_id: scene.離家}
- - action: notify.mobile_app_charles
- data: {message: 已切換到外出模式}
- - conditions: "{{ trigger.to_state.state == '睡覺' }}"
- sequence:
- - action: script.turn_on
- target: {entity_id: script.睡前模式}
- - conditions: "{{ trigger.to_state.state == '度假' }}"
- sequence:
- - action: script.turn_on
- target: {entity_id: script.度假模式}
- mode: queued
複製代碼
把「狀態怎麼轉」和「轉了之後做什麼」分開,
兩個都會變得好讀很多。
怎麼檢查有沒有漏洞
畫完轉換圖之後,逐一問自己:
- 每個狀態都有「進來」的路徑嗎?(沒有的話那個狀態永遠到不了)
- 每個狀態都有「出去」的路徑嗎?(沒有的話會卡死)
- 有沒有兩條路徑會同時觸發?(會打架)
- 斷電重開之後,狀態會是什麼?
最後一個最常被忘記。
input_select 的 initial 只在第一次建立時生效,
之後 HA 會記住上次的值。所以重啟後可能停在「睡覺」但現在是下午。
我的解法是加一個啟動檢查:
- alias: 重啟後校正狀態
- triggers:
- - trigger: homeassistant
- event: start
- actions:
- - delay: "00:02:00" # 等感測器都回報了
- - action: input_select.select_option
- target: {entity_id: input_select.house_mode}
- data:
- option: >
- {% if not is_state('binary_sensor.家裡真的有人','on') %}外出
- {% elif now().hour >= 23 or now().hour < 6 %}睡覺
- {% elif now().hour >= 18 %}在家-夜間
- {% else %}在家-日間{% endif %}
- mode: single
複製代碼
---
我是在家裡的自動化超過二十個之後才被迫做這件事的。
早點做會省很多重寫的時間。
如果你現在只有五六個自動化,也建議先把狀態列出來 ——
就算暫時不實作,之後寫每個自動化的時候心裡會有一張圖。 |
|