找回密碼
 立即註冊
    查看: 162|回覆: 0

    wait_for_trigger 與 wait_template 完整實作:寫出「會等待」的流程式自動化

    [複製鏈接]

    !lvup!   100%

    386

    主題

    27

    回帖

    2200萬

    積分

    管理員

    積分
    22006063
    發表於 2026-9-21 08:38:49 | 顯示全部樓層 |閱讀模式
    大部分自動化的形狀是「觸發 → 做事 → 結束」,三秒鐘跑完。但生活裡很多流程不是這樣:洗衣機開始運轉,然後你要等它洗完;你出門了,然後要等五分鐘再確認門鎖;系統問你一個問題,然後要等你按下按鈕。

    這種「做一件事 → 等某件事發生 → 再做下一件」的流程,靠的是 wait。

    wait

    這篇會做完的事


    • 搞懂兩種 wait 的差別,以及為什麼選錯會讓自動化永遠卡住
    • 做一個用功率判斷的洗衣機完成通知(不需要洗衣機本身是智慧家電)
    • 做一個「離家後確認門鎖」,含可以按的通知按鈕
    • 學會 wait.completed / wait.remaining / wait.trigger 三個變數
    • 處理「同一條自動化跑兩次,按鈕會互相搶」這個官方明文的問題
    • 加上兩層保險:卡住的偵測,以及重新啟動後的補救
    • 學會在不等兩小時的情況下,把整條鏈路測完


    全部做完約兩小時。需要一個智慧插座(有功率量測的那種)、一台裝了 Home Assistant 手機 App 的手機。沒有智慧插座的話,第三步會給一個用其他感測器替代的方法。

    第零步:確認你的起點

    0-1 找出你的通知服務名稱

    到 開發者工具 → 動作,在搜尋框打 notify。

    你會看到一串以 notify. 開頭的動作,其中會有 notify.mobile_app_xxx,xxx 是你手機在 Home Assistant 裡的名稱。

    一個 mobile_app 都沒有 → 手機還沒裝 App 或還沒登入。到 App Store 或 Google Play 裝 Home Assistant,登入之後回來重新整理這一頁。

    把那個完整名稱抄下來,這篇所有 notify.mobile_app_charles 都要換成你自己的。

    0-2 如果有智慧插座,找出功率感測器

    開發者工具 → 狀態,篩選欄打 power 或你的插座名稱。

    你會看到類似:
    1. sensor.xi_yi_ji_gong_lu    3.2    unit_of_measurement: W
    2.                                   device_class: power
    複製代碼

    0-3 量出洗衣機的功率門檻(這一步不能猜)

    不要抄任何教學給的數字。 每一台洗衣機的待機功率和運轉功率都不一樣。

    方法:把洗衣機接上智慧插座,跑一次完整的洗衣程序,然後到那個感測器的歷史頁看曲線。

    你會看到三段很不一樣的數值:
    1. 待機(沒在洗)         0 到 5 W       ← 記下上限,叫它「待機上限」
    2. 運轉(洗、脫水)       150 到 800 W   ← 記下下限,叫它「運轉下限」
    3. 中間換程序的短暫低谷    0 到 20 W      ← 記下它持續多久
    複製代碼

    那三個數字後面都會用到。中間那個低谷特別重要 —— 很多洗衣機在進水、排水、換程序的時候功率會短暫掉到接近零,持續幾十秒到兩分鐘。沒有量過就寫判斷式的話,洗到一半就會通知你洗好了。

    沒有智慧插座怎麼辦:改用其他訊號。震動感測器(貼在機身上)、門磁(貼在洗衣機門上)、或者洗衣機本身如果有 Wi-Fi 就直接用它的實體。判斷邏輯完全一樣,只是把「功率低於 5 瓦」換成「震動感測器是 off」。

    第一步:兩種 wait 的差別(選錯會永遠卡住)
    1. wait_for_trigger  等一個「事件發生」—— 狀態從 A 變成 B 的那一瞬間
    2.                   已經是 B 了也不算,它會繼續等下一次變化
    3. wait_template     等一個「條件成立」—— 現在就成立的話立刻通過
    複製代碼

    用一個具體的例子看差別:
    1. # A:等門「變成」開
    2. - wait_for_trigger:
    3.     - trigger: state
    4.       entity_id: binary_sensor.men
    5.       to: "on"
    6. # 執行到這一行時門已經是開的 → 它會繼續等,
    7. # 直到門關起來再打開一次。門如果一直開著,它永遠不會通過
    8. # B:等門「是」開
    9. - wait_template: "{{ is_state('binary_sensor.men', 'on') }}"
    10. # 執行到這一行時門已經是開的 → 立刻通過
    複製代碼

    九成的情況你要的是 wait_template,因為你在意的是狀態,不是變化那一瞬間。

    什麼時候才該用 wait_for_trigger:


    • 等一個事件(按下通知按鈕、收到 webhook、遙控器被按)—— 事件本來就沒有「狀態」可言
    • 等好幾種情況其中之一,而且要知道是哪一種發生的
    • 需要用到 for:(持續多久)這種只有觸發器才有的修飾


    1-1 wait_template 有一個官方明文的限制,一定要知道

    官方原話:「The template is re-evaluated whenever an entity ID that it references changes state. If you use non-deterministic functions like now() in the template it will not be continuously re-evaluated, but only when an entity ID that is referenced is changed.」

    翻成白話:wait_template 只在「它引用到的實體」變化時才重算。用 now() 寫時間條件,它不會自己重算。

    所以這樣寫會永遠卡住:
    1. # 錯:這個 wait 可能永遠不會通過
    2. - wait_template: "{{ now() > today_at('07:00') }}"
    複製代碼

    兩個正解:
    1. # 正解一:改用 wait_for_trigger 等時間
    2. - wait_for_trigger:
    3.     - trigger: time
    4.       at: "07:00:00"
    5.   timeout: "12:00:00"
    6. # 正解二:在範本裡引用一個會定期變化的實體
    7. # 先到 設定 → 裝置與服務 → 新增整合 → 搜尋 Time & Date,勾選「時間」
    8. - wait_template: >
    9.     {{ states('sensor.time') is not none
    10.        and now() > today_at('07:00') }}
    複製代碼

    第二步:一定要加 timeout(先做最小版本)

    沒有 timeout 的 wait 會無限期卡在那裡。 它會一直佔著一個執行位置,在「執行中的自動化」裡看得到,但你不會注意到 —— 直到某天發現這條自動化再也沒動過。

    以下還有約 80% 的內容
    登入後即可閱讀完整教學

    登入繼續閱讀使用 Google 登入
    您需要登入後纔可以回帖 登入 | 立即註冊

    本版積分規則

    延伸閱讀

    加入惟家 LINE 群 QR Code加入惟家 LINE 群

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

    GMT+8, 2026-11-10 00:37 , Processed in 0.149481 second(s), 25 queries .

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