第 10 章

腳本 Scripts

把「一連串動作」打包起來取名字。之後自動化、按鈕、語音都能一句話喚起它。第 8 章的自動化是「一個獨立完整運作的東西」;腳本則是「一段被叫的動作」。

為什麼需要腳本

當你發現自己在很多個自動化裡重複貼同一段動作,例如:

  • 「關全家燈 + 冷氣關 + 掃地機開始 + 玄關燈延遲 30 秒關」— 出門情境
  • 「所有窗簾拉起 + 主燈 20% + 音響播早安歌單」— 起床情境
  • 「主臥燈慢慢淡到 5% 再關」— 睡覺淡出

直接把這一整段包成一個腳本,例如 script.leaving_home,之後:

  • 離家自動化 → 只要「呼叫 script.leaving_home」一行
  • 玄關 Zigbee 按鈕長按 → 也呼叫 script.leaving_home
  • 語音助理說「我要出門了」→ 也呼叫 script.leaving_home
  • 儀表板放一顆大按鈕 → 也呼叫 script.leaving_home

之後你想改「出門要不要順便關飲水機」,只改腳本這一個地方,四個入口全部同步。這就是把邏輯集中的價值。

腳本 vs 自動化 vs 場景

三個名詞新手常混淆,先分清楚:

  • 自動化 Automation:三段式(觸發/條件/動作),會「自己啟動」。例:日落時觸發。
  • 腳本 Script:只有動作段,不會自己啟動,要被叫。可以有延遲、迴圈、條件分支,比場景強大很多。
  • 場景 Scene:一組實體「狀態快照」(燈 60% / 冷氣 26°C / 窗簾 100%)。呼叫時瞬間把所有實體切到指定狀態。不能有延遲或邏輯
簡單決策樹:
  • 「一次把 5 顆燈調成固定亮度」→ 場景(最單純)
  • 「先做 A,等 3 秒,再做 B,如果 X 才做 C」→ 腳本(有邏輯)
  • 「早上 7 點自動做 X」→ 自動化(有觸發)
場景常被腳本「呼叫」— 場景是磚塊,腳本是砌牆的方法。

動手做:第一個腳本「離家模式」

名稱改過了:以前的「服務(Service)」現在叫「動作(Action)」——介面上的「呼叫服務」變成「執行動作」,YAML 裡的 service: 要寫成 action:(HA 2024.8 起)。另外「開發者工具」在 2026.2 從側欄搬進設定 → 工具,2026.8 又把 Developer Tools 簡化成 Tools(工具),裡面原本的「服務」分頁現在叫「動作」。舊寫法 HA 目前還讀得懂,但介面上已經找不到舊名字了。
  1. 設定 → 自動化與場景 → 腳本頁籤

    右下角「+ 新增腳本」→ 選「建立新腳本」。(如果選「從藍圖」也可,但先從空白開始。)

    腳本頁面
    圖 10-1腳本管理頁 — 顯示所有已建立的腳本。
  2. 填寫名稱與 icon

    名稱:「離家模式」
    Iconmdi:door-open(可從 pictogrammers.com 找)
    頁面下方會自動生成 entity_id:script.leaving_home。這個 ID 之後用來呼叫,取個好記的名字。

  3. 加動作:關掉所有燈

    「+ 新增動作」→「執行動作」(舊版叫「呼叫服務」)→ 選 light.turn_off
    目標:不要一顆一顆選;用「區域」選「全部」,或用「標籤」(第 4 章教的)選「燈光」。這樣之後新加的燈會自動被涵蓋。

    新增動作
    圖 10-2用「區域」或「標籤」當目標,比一顆一顆選穩健。
  4. 加動作:關冷氣

    「+ 新增動作」→ climate.turn_off → 目標選所有 climate 實體或用「冷氣」標籤。

  5. 加動作:等 30 秒

    「+ 新增動作」→「延遲」→ 30 秒。這是腳本比場景強的地方,可以排時序。

  6. 加動作:關玄關燈

    「+ 新增動作」→ light.turn_off → 目標選玄關燈單一實體。用意:前面已經關全家燈,玄關燈延遲 30 秒才關,讓你有時間穿鞋出門。

  7. 加動作:推播通知

    「+ 新增動作」→ notify.mobile_app_你的手機(見第 7 章)→ 訊息:「離家模式已啟動 ✅」。這樣就算按錯,手機會提示你。

  8. 右上角「儲存」→ 點試跑(▶)

    儲存後上方會出現橘色「儲存」變綠 → 按「執行腳本」測試。如果動作正確,手機應收到通知。

    驗證:到「設定 → 工具 → 動作」呼叫 script.leaving_home,也應該完整跑一次。同一個入口從腳本頁、設定 → 工具、儀表板、自動化叫都是等價的。

加參數(Fields)— 讓腳本可被客製

剛才的腳本寫死了「30 秒延遲」,如果晚上想 60 秒、白天想 15 秒怎麼辦?加一個 Field(欄位)

  1. 編輯腳本 → 右上「⋮」→「編輯 YAML」

    UI 也能加欄位(在腳本頁面下方「欄位」區),但 YAML 一次看得清楚。加入:

    fields:
      delay_seconds:
        name: 玄關燈延遲秒數
        description: 幾秒後關玄關燈
        default: 30
        selector:
          number:
            min: 5
            max: 300
            unit_of_measurement: 秒
  2. 把動作裡的 30 改成變數

    - delay:
        seconds: "{{ delay_seconds }}"

    之後呼叫時就能傳參數:script.leaving_home + delay_seconds: 60

  3. UI 呼叫也能填欄位

    加了 fields 後,在儀表板卡片、自動化的動作、設定 → 工具呼叫這隻腳本時,會自動出現一個可以填「延遲秒數」的欄位,非工程師也能改。

常用 selector: number(數字)、text(文字)、boolean(開關)、entity(選實體)、area(選區域)、time(選時間)。有 selector UI 就會渲染成對應元件,比純文字友善。

執行模式 Single / Restart / Queued / Parallel

當腳本正在跑,又被叫一次會怎樣?這由「模式」決定,跟自動化一樣:

模式 行為 適合場景
single(預設) 已經在跑就忽略新的呼叫 離家、睡覺這種一次性情境
restart 停止目前這次、從頭再跑 動作感應器亮燈(有人再動就重算延遲)
queued 依序排隊執行 推播訊息、記錄事件
parallel 同時開多份 大量獨立事件同時觸發
坑:離家腳本如果留 single,你在門口不小心連按兩下按鈕,第二次會被丟掉(正確);但如果是「客廳燈慢慢淡出」的腳本用 single,你按第二次想「再淡一次」就不會動。這種場景改成 restart

實用範例集

1. 睡覺淡出(restart 模式)

從當前亮度開始 30 秒內淡到 1%,再過 5 秒關掉。中途再按會重來。

alias: bedroom_fade_out
mode: restart
sequence:
  - action: light.turn_on
    target:
      entity_id: light.bedroom_main
    data:
      brightness_pct: 1
      transition: 30
  - delay: "00:00:35"
  - action: light.turn_off
    target:
      entity_id: light.bedroom_main

2. 迴圈通知直到有人回應(repeat until)

洗衣機洗完每 3 分鐘推播一次,直到有人到洗衣間(Zigbee 動作感應器觸發)為止。

alias: nag_until_laundry_picked
mode: restart
sequence:
  - repeat:
      until:
        - condition: state
          entity_id: binary_sensor.laundry_motion
          state: "on"
      sequence:
        - action: notify.mobile_app_dad
          data:
            message: 洗衣機洗完了,快去拿!
        - delay: "00:03:00"

3. 條件分支(choose)

回家時根據時段做不同事:白天只開空調、晚上開燈+空調、深夜只開夜燈。

alias: arriving_home
sequence:
  - choose:
      - conditions:
          - condition: sun
            before: sunset
        sequence:
          - action: climate.turn_on
            target: { entity_id: climate.livingroom }
      - conditions:
          - condition: time
            after: "23:00:00"
        sequence:
          - action: light.turn_on
            target: { entity_id: light.hallway }
            data: { brightness_pct: 20 }
    default:
      - action: light.turn_on
        target: { area_id: livingroom }
      - action: climate.turn_on
        target: { entity_id: climate.livingroom }

4. 並行動作(parallel)— 全開全關的最快版本

正常一連串動作是序列跑,用 parallel 可以同時發,快很多:

sequence:
  - parallel:
      - action: light.turn_off
        target: { area_id: livingroom }
      - action: cover.close_cover
        target: { area_id: livingroom }
      - action: media_player.turn_off
        target: { entity_id: media_player.tv }

5. 呼叫其他腳本 / 場景

sequence:
  - action: scene.turn_on
    target: { entity_id: scene.movie_night }
  - delay: "00:00:02"
  - action: script.turn_on
    target: { entity_id: script.close_all_curtains }

差別:用 script.turn_on 呼叫是「發射後不管」,主腳本繼續往下跑;直接寫 action: script.其他腳本(不加 turn_on)則是「等它跑完再繼續」。想同步等就用後者。

如何呼叫腳本(4 種入口)

  1. 從自動化的動作段

    自動化 → 動作 → 選「執行動作」→ script.leaving_home(或直接選腳本 entity)。有 fields 時會顯示欄位。

  2. 從儀表板卡片

    加一顆按鈕卡(Button card)→ 點擊動作選「執行動作」→ script.turn_on → 目標選腳本。想更花俏用 Tile card + 客製 icon。

  3. 從 Zigbee 遙控器 / 場景面板

    用第 8 章講的「MQTT 事件」或「ZHA 事件」抓按鈕,動作段呼叫這隻腳本。長按、短按、雙擊都可映射到不同腳本。

  4. 從語音助理 Assist

    「暴露 Expose」給 Assist(設定 → 語音助理 → 暴露腳本),之後可以說「Hey,離家模式」直接叫。這是內建功能,不用寫任何整合。

常見卡關

腳本執行到一半停住不繼續?
  • 檢查是不是某個 wait_templatewait_for_trigger 沒 timeout — 加 timeout: "00:00:30" + continue_on_timeout: true
  • 某個動作執行失敗會拋錯中止,加 continue_on_error: true 讓它跳過繼續。
  • 去「設定 → 工具 → 動作」單獨測那個動作,看是不是實體不存在或參數錯。
fields 加了,儀表板按鈕卡沒出現填寫欄位?
按鈕卡預設「按下就跑」,不會問欄位。想要彈出對話框請用「Entity card」或設定「hold_action → more-info」,會顯示欄位;或改用 Mushroom Template card(HACS)自己畫。
「執行腳本」按了沒反應?
去「設定 → 系統 → 日誌」看有沒有錯。腳本失敗常見是:實體 ID 拼錯、目標裝置離線、權限不夠(非管理員帳號跑管理員的腳本)。
腳本裡的 {{ variable }} 沒被取代?
要用引號包起來:value: "{{ my_var }}"。純數字或布林可以省,但字串必須引號。另外 {{ }} 只在 data: 值裡工作,key 名不能用模板。

常見問題

腳本可以自己觸發嗎?
不行,腳本沒有觸發段。想要「條件到就自己跑」,寫一個自動化,它的動作是呼叫這隻腳本。
腳本可以呼叫腳本嗎?巢狀幾層?
可以,實務上不限層數(HA 官方沒設硬上限)。但每呼叫一層就多一層難以追蹤,超過 3 層通常代表結構要重整。可以把共用步驟拉出來,父腳本只管流程。
腳本刪掉後,用到它的自動化會怎樣?
會壞掉,執行到那一行時動作執行失敗。刪腳本前用「設定 → 自動化 → 三個點 → 追蹤器」或到「設定 → 工具 → 事件」監聽 service_registered 找誰在用它。
Blueprint 是什麼?跟腳本什麼關係?
Blueprint 是腳本或自動化的模板,第 8 章有講。把常用邏輯做成 Blueprint,任何人匯入後只填幾個參數(哪個燈、哪個感應器)就有一份可用的腳本,適合分享和大量部署。