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

    智能家居的「可維護性」:三個我後來才懂的原則

    [複製鏈接]

    !lvup!   100%

    363

    主題

    27

    回帖

    2200萬

    積分

    管理員

    積分
    22005752
    發表於 3 天前 | 顯示全部樓層 |閱讀模式
    玩了一段時間之後,我發現真正的分水嶺不是「會不會寫自動化」,
    而是「半年後你還敢不敢動它」

    這篇講三個讓系統能長期活下去的原則。



    原則一:每個判斷只寫一次

    這是最重要的一條。

    壞的樣子
    1. # 自動化 A
    2. conditions:
    3.   - "{{ now().hour >= 23 or now().hour < 6 }}"
    4. # 自動化 B
    5. conditions:
    6.   - "{{ now().hour >= 23 or now().hour < 6 }}"
    7. # 自動化 C(這裡不小心寫成 22)
    8. conditions:
    9.   - "{{ now().hour >= 22 or now().hour < 6 }}"
    複製代碼

    同一個「夜間」的定義散在三個地方,而且已經不一致了
    你不會發現,因為只差一小時。

    好的樣子
    1. template:
    2.   - binary_sensor:
    3.       - name: 夜間模式
    4.         unique_id: night_mode
    5.         state: >
    6.           {{ now().hour >= 23 or now().hour < 6 }}
    複製代碼

    三個自動化都改成:
    1. conditions:
    2.   - condition: state
    3.     entity_id: binary_sensor.夜間模式
    4.     state: "on"
    複製代碼

    三個額外的好處


    • 改定義只要改一個地方
    • 可以在介面上直接看「現在是不是夜間」,除錯超快
    • 可以拉到儀表板上,家人也知道現在是什麼模式


    這條原則的一般形式:任何出現第二次的判斷,就該抽出來變成實體。



    原則二:名字要能自我說明

    半年後你看到這個:
    1. - action: script.turn_on
    2.   target:
    3.     entity_id: script.1690234871234
    複製代碼

    完全不知道它在幹嘛。

    命名的三個層次


    • 實體 ID —— 英文、結構化。light.bedroom_ceiling
    • 顯示名稱 —— 中文、人話。主臥天花板燈
    • 自動化 alias —— 要能看出「什麼時候會發生什麼事」


    自動化命名的壞例子和好例子:
    1. # 壞
    2. alias: 燈光自動化 2
    3. alias: 感應器
    4. alias: test
    5. # 好
    6. alias: 浴室有人時開燈,離開三分鐘關
    7. alias: 離家後五分鐘提醒門沒鎖
    8. alias: 濕度超過門檻自動抽風
    複製代碼

    好的 alias 讀起來就是一句完整的規則。
    這樣自動化列表本身就是一份文件。

    還有一件事:給自動化 id
    1. automation:
    2.   - alias: 浴室感應燈
    3.     id: bathroom_motion_light
    複製代碼

    沒有 id 的自動化不能在 UI 編輯、不能被追蹤、
    而且重新排序後 entity_id 會跑掉(變成 automation.unnamed_2)。

    原則三:讓系統能告訴你它壞了

    這條最容易被忽略,但影響最大。

    智能家居最可怕的不是壞掉,是「安靜地壞掉」。

    感應器沒電了、Zigbee 裝置掉線了、某個整合壞了 ——
    這些都不會報錯,只是那個自動化再也不會觸發。
    你可能三個月後才發現。

    做法一:不可用實體的每日巡檢
    1. template:
    2.   - trigger:
    3.       - trigger: time
    4.         at: "09:00:00"
    5.     sensor:
    6.       - name: 不可用的實體
    7.         unique_id: unavailable_entities
    8.         state: >
    9.           {{ states
    10.              | selectattr('state', 'in', ['unavailable', 'unknown'])
    11.              | rejectattr('entity_id', 'search', '^(device_tracker|person)\\.')
    12.              | list | count }}
    13.         attributes:
    14.           清單: >
    15.             {{ states
    16.                | selectattr('state', 'in', ['unavailable', 'unknown'])
    17.                | rejectattr('entity_id', 'search', '^(device_tracker|person)\\.')
    18.                | map(attribute='entity_id') | list }}
    複製代碼

    配一個自動化:數量 > 0 就推播。

    做法二:電池低電量提醒
    1. template:
    2.   - sensor:
    3.       - name: 低電量裝置數
    4.         unique_id: low_battery_count
    5.         state: >
    6.           {{ states.sensor
    7.              | selectattr('attributes.device_class', 'defined')
    8.              | selectattr('attributes.device_class', 'eq', 'battery')
    9.              | map(attribute='state') | map('int', 100)
    10.              | select('lt', 20) | list | count }}
    複製代碼

    做法三:「太久沒動」偵測

    這個最有用。一個平常每天觸發的感應器,三天沒動就是有問題:
    1. template:
    2.   - trigger:
    3.       - trigger: time_pattern
    4.         hours: "/6"
    5.     binary_sensor:
    6.       - name: 有裝置失聯
    7.         unique_id: stale_devices
    8.         state: >
    9.           {{ states.binary_sensor
    10.              | selectattr('attributes.device_class', 'defined')
    11.              | selectattr('attributes.device_class', 'eq', 'motion')
    12.              | selectattr('last_changed', 'lt', now() - timedelta(days=3))
    13.              | list | count > 0 }}
    14.         attributes:
    15.           失聯清單: >
    16.             {{ states.binary_sensor
    17.                | selectattr('attributes.device_class', 'defined')
    18.                | selectattr('attributes.device_class', 'eq', 'motion')
    19.                | selectattr('last_changed', 'lt', now() - timedelta(days=3))
    20.                | map(attribute='name') | list }}
    複製代碼

    做法四:自動化健康檢查

    每個月提醒你去看一次:
    1. alias: 每月自動化健康檢查
    2. triggers:
    3.   - trigger: time
    4.     at: "10:00:00"
    5. conditions:
    6.   - "{{ now().day == 1 }}"
    7. actions:
    8.   - action: notify.mobile_app_charles
    9.     data:
    10.       title: 每月檢查
    11.       message: >
    12.         停用中的自動化:
    13.         {{ states.automation | selectattr('state','eq','off')
    14.            | map(attribute='name') | list | join('、') }}
    15.         三十天沒觸發過的:
    16.         {{ states.automation
    17.            | selectattr('attributes.last_triggered', 'defined')
    18.            | selectattr('attributes.last_triggered', 'lt',
    19.                         now() - timedelta(days=30))
    20.            | map(attribute='name') | list | join('、') }}
    21. mode: single
    複製代碼

    「三十天沒觸發過」這個清單特別有價值。
    上面的東西不是壞了,就是根本不需要 —— 兩種都該處理。



    一個額外的建議:定期刪東西

    我每季會做一次「砍掉不用的」:


    • 三十天沒觸發的自動化 → 看是壞了還是沒用,沒用就刪
    • 儀表板上從來沒點過的卡片 → 刪
    • 買來玩過一次就放著的裝置 → 從 HA 移除(不然它永遠是 unavailable)
    • 測試用的輔助元件 → 刪


    刪東西比加東西難,但對可維護性的幫助更大。

    系統越小,你越清楚它在做什麼;越清楚,你越敢改。

    ---

    回頭看,這三個原則其實可以濃縮成一句:

    「讓半年後的自己,能在十分鐘內搞懂並安全地改動任何一部分。」

    做得到的話,這套系統就能一直長大。做不到的話,
    它會慢慢變成一個你不敢碰的黑盒子,最後整個重做。

    (我重做過一次,所以知道那有多痛。)
    您需要登入後纔可以回帖 登入 | 立即註冊

    本版積分規則

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

    GMT+8, 2026-9-24 12:16 , Processed in 0.081094 second(s), 23 queries .

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