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

    讓 ESPHome 裝置在 HA 掛掉時還能運作:on_boot 與備援邏輯

    [複製鏈接]

    !lvup!   100%

    363

    主題

    27

    回帖

    2200萬

    積分

    管理員

    積分
    22005752
    發表於 3 天前 | 顯示全部樓層 |閱讀模式
    ESPHome 最被低估的優勢:它可以完全不依賴 HA。

    這篇講怎麼設計「HA 掛了也不影響」的裝置。



    為什麼重要

    想像一個情境:


    • 你用 ESPHome 做了一個燈開關
    • 邏輯寫在 HA 的自動化裡
    • HA 在升級、或者掛掉
    • 牆上的開關按了沒反應


    這時候家人會很生氣。

    第一原則:本地能做的就在本地做
    1. # 壞:按鈕 → 呼叫 HA → HA 叫繼電器
    2. binary_sensor:
    3.   - platform: gpio
    4.     pin: GPIO13
    5.     on_press:
    6.       - homeassistant.service:
    7.           service: switch.toggle
    8.           data:
    9.             entity_id: switch.living_room_relay
    10. # 好:按鈕 → 直接控制同一片板子上的繼電器
    11. binary_sensor:
    12.   - platform: gpio
    13.     pin: GPIO13
    14.     on_press:
    15.       - switch.toggle: relay1
    複製代碼

    後者在斷網、HA 掛掉的情況下照樣運作。

    而且狀態會自動同步給 HA —— 你不會失去任何東西。



    第二:斷電後的狀態(restore_mode)

    這個決定「停電復電之後,繼電器是開還是關」。
    1. switch:
    2.   - platform: gpio
    3.     pin: GPIO12
    4.     id: relay1
    5.     name: "客廳燈"
    6.     restore_mode: RESTORE_DEFAULT_OFF
    複製代碼

    選項


    • RESTORE_DEFAULT_OFF —— 恢復斷電前的狀態,不知道的話預設關
    • RESTORE_DEFAULT_ON —— 恢復,不知道的話預設開
    • ALWAYS_OFF —— 永遠關
    • ALWAYS_ON —— 永遠開
    • RESTORE_INVERTED_DEFAULT_OFF —— 恢復成相反的(少用)


    怎麼選


    • → RESTORE_DEFAULT_OFF(停電後不要自己亮起來)
    • 冰箱、魚缸的插座ALWAYS_ON(絕對不能關)
    • 熱水器 → RESTORE_DEFAULT_OFF(安全考量)
    • 網路設備 → ALWAYS_ON


    ALWAYS_ON 對「不能關的東西」很重要 ——
    就算 HA 掛了、就算你的自動化寫錯,它永遠是開的。

    第三:on_boot(開機時要做什麼)
    1. esphome:
    2.   name: bedroom-controller
    3.   on_boot:
    4.     priority: 600          # 數字越大越早執行
    5.     then:
    6.       - logger.log: "開機了"
    7.       - switch.turn_off: relay_heater      # 安全起見先關掉加熱器
    複製代碼

    priority 的常用值


    • 800 —— 最早,硬體剛初始化
    • 600 —— 一般元件已經好了
    • -100 —— 最晚,Wi-Fi 和 API 都連上了


    要用到 HA 的資料就用 -100(那時候才連得上)。



    第四:本地的備援邏輯

    範例:溫度太高就開風扇(不依賴 HA)
    1. sensor:
    2.   - platform: aht10
    3.     temperature:
    4.       id: temp
    5.       name: "溫度"
    6.       on_value:
    7.         then:
    8.           - if:
    9.               condition:
    10.                 lambda: 'return x > 30.0;'
    11.               then:
    12.                 - switch.turn_on: relay_fan
    13.           - if:
    14.               condition:
    15.                 lambda: 'return x < 27.0;'
    16.               then:
    17.                 - switch.turn_off: relay_fan
    18. switch:
    19.   - platform: gpio
    20.     pin: GPIO12
    21.     id: relay_fan
    22.     name: "風扇"
    23.     restore_mode: RESTORE_DEFAULT_OFF
    複製代碼

    開 30 度、關 27 度,中間有三度的遲滯。

    完全在裝置上執行,HA 掛了也照樣運作。

    範例:HA 斷線時啟用備援模式
    1. binary_sensor:
    2.   - platform: status
    3.     name: "連線狀態"
    4.     id: api_connected
    5. # 用一個全域變數記住是不是在備援模式
    6. globals:
    7.   - id: fallback_mode
    8.     type: bool
    9.     restore_value: false
    10.     initial_value: 'false'
    11. interval:
    12.   - interval: 60s
    13.     then:
    14.       - if:
    15.           condition:
    16.             not:
    17.               api.connected:
    18.           then:
    19.             - globals.set:
    20.                 id: fallback_mode
    21.                 value: 'true'
    22.             - logger.log: "HA 斷線,啟用本地備援邏輯"
    23.           else:
    24.             - globals.set:
    25.                 id: fallback_mode
    26.                 value: 'false'
    複製代碼

    然後在感測器的 on_value 裡判斷
    1.       on_value:
    2.         then:
    3.           - if:
    4.               condition:
    5.                 lambda: 'return id(fallback_mode);'
    6.               then:
    7.                 # 只有在備援模式才自己做決定
    8.                 - if:
    9.                     condition:
    10.                       lambda: 'return x > 30.0;'
    11.                     then:
    12.                       - switch.turn_on: relay_fan
    複製代碼

    平常讓 HA 做(邏輯比較聰明),HA 掛了才自己接手。

    第五:安全邏輯一定要在本地

    這一條沒有例外。

    範例:加熱器的過熱保護
    1. sensor:
    2.   - platform: dallas
    3.     address: 0x1234567890abcdef
    4.     id: heater_temp
    5.     name: "加熱器溫度"
    6.     on_value:
    7.       then:
    8.         - if:
    9.             condition:
    10.               lambda: 'return x > 70.0;'
    11.             then:
    12.               - switch.turn_off: relay_heater
    13.               - logger.log: "過熱保護觸發!"
    14.               - homeassistant.event:
    15.                   event: esphome.overheat
    16.                   data:
    17.                     device: heater
    18.     # 感測器讀不到值也要保護
    19.     filters:
    20.       - lambda: |-
    21.           if (isnan(x)) {
    22.             // 讀不到溫度,關掉加熱器
    23.             id(relay_heater).turn_off();
    24.             return {};
    25.           }
    26.           return x;
    複製代碼

    兩層保護


    • 溫度超過 70 度 → 關
    • 讀不到溫度(感測器壞了)→ 也關


    第二層很重要 —— 很多人只做第一層,
    但感測器壞掉回傳 NaN 的話,「超過 70 度」的判斷永遠不會成立。

    第六:看門狗(watchdog)
    1. interval:
    2.   - interval: 5min
    3.     then:
    4.       - if:
    5.           condition:
    6.             not:
    7.               wifi.connected:
    8.           then:
    9.             - logger.log: "Wi-Fi 斷線超過五分鐘"
    10. # Wi-Fi 連不上超過 15 分鐘就重開
    11. wifi:
    12.   reboot_timeout: 15min
    13. # API 連不上超過 30 分鐘就重開
    14. api:
    15.   reboot_timeout: 30min
    複製代碼

    api.reboot_timeout 的取捨


    • 設了的話:HA 長時間掛掉,你的裝置會一直重開
    • 設 0 的話:永遠不因為 API 斷線而重開


    如果你的裝置有本地邏輯(不需要 HA),建議設 0
    1. api:
    2.   reboot_timeout: 0s
    複製代碼

    這樣 HA 在升級的時候,你的裝置不會莫名其妙重開。

    一個完整的「不依賴 HA」的開關範例
    1. esphome:
    2.   name: bathroom-switch
    3.   on_boot:
    4.     priority: -100
    5.     then:
    6.       - logger.log: "開機完成"
    7. api:
    8.   encryption:
    9.     key: !secret api_key
    10.   reboot_timeout: 0s        # HA 掛了也不重開
    11. wifi:
    12.   ssid: !secret wifi_ssid
    13.   password: !secret wifi_password
    14.   reboot_timeout: 0s        # 連不上 Wi-Fi 也不重開(本地功能還能用)
    15. switch:
    16.   - platform: gpio
    17.     pin: GPIO12
    18.     id: relay_light
    19.     name: "浴室燈"
    20.     restore_mode: RESTORE_DEFAULT_OFF
    21. binary_sensor:
    22.   # 牆上的實體按鈕 → 直接控制繼電器
    23.   - platform: gpio
    24.     pin:
    25.       number: GPIO13
    26.       mode: {input: true, pullup: true}
    27.       inverted: true
    28.     name: "浴室開關"
    29.     filters:
    30.       - delayed_on: 30ms
    31.     on_press:
    32.       - switch.toggle: relay_light
    33.   # 人體感應 → 也是本地控制
    34.   - platform: gpio
    35.     pin: GPIO14
    36.     name: "浴室感應"
    37.     device_class: motion
    38.     on_press:
    39.       - switch.turn_on: relay_light
    40.     on_release:
    41.       - delay: 3min
    42.       - switch.turn_off: relay_light
    複製代碼

    這個裝置完全不需要 HA 就能運作。

    HA 只是「額外的控制介面和記錄」



    設計原則總結


    • 同一片板子上的東西,用本地控制
    • 安全邏輯一定在本地,而且要處理「感測器壞掉」的情況
    • restore_mode 要想清楚,尤其是不能關的東西
    • 有本地邏輯的裝置,api.reboot_timeout 設 0
    • 複雜的邏輯(需要跨裝置、需要歷史)才交給 HA


    一個判斷標準

    「拔掉網路線,這個裝置還能做它最基本的工作嗎?」


    • → 設計正確
    • 不能 → 想想看有沒有辦法把核心功能搬到本地


    ---

    下一篇:ESPHome 除錯 ——
    連不上、一直重開、記憶體不足。
    您需要登入後纔可以回帖 登入 | 立即註冊

    本版積分規則

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

    GMT+8, 2026-9-24 12:20 , Processed in 0.086754 second(s), 24 queries .

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