自动化的四要素:触发、条件、动作、模式
从「远程开关」到「不用管的系统」
装好 Home Assistant 之后,大多数人最先学会的是打开网页或手机 App,点一下把客厅灯关掉。这本质上还是「人操作」,只不过把墙上的物理面板换成了屏幕。真正让 HA 值得折腾的,是自动化——让系统在合适的时机自己干活,你不用管,它也办得妥当。
一条最小化的自动化,用一句话概括就是:当某件事发生时(触发),如果当时的情况允许(条件),就去做一件事(动作)。这三样,再加上一个专门处理「撞车」的 mode(模式),就是 HA 自动化的四要素。本章后续所有花活——模板、场景、事件总线、Node-RED——说到底都是在这四个位置上做加法。先把这四个位置认清楚,后面学什么都快。

触发:自动化的起点
trigger 决定「什么时候让这条自动化入场」。它不是某个具体的时间点,而是一个「信号发生了」的事件:门窗被打开、温度跨过某条线、时钟走到某一刻、太阳落山、有人从外面回到家,都可以成为触发。常见的触发器可以分成四大类:
| 触发类别 | 典型代表 | 适合做什么 |
|---|---|---|
| 状态类 | state、numeric_state | 门窗开合、温湿度跨阈值 |
| 时间类 | time、sun、template | 定时任务、日出日落联动 |
| 事件类 | event、webhook、mqtt | 第三方推送、自定义事件 |
| 位置类 | zone | 手机进出某个地理围栏 |
要建立的关键认知是:触发只管「发车」,不管「该不该去」。很多新手写出来的自动化会在凌晨三点把全屋灯打开,通常不是触发写错了,而是缺了条件。触发器的详细用法会在本系列「触发器全家桶」一篇展开,这里先记住它在流水线上的位置:一切从触发开始,但一切又不能止于触发。
另一条容易踩的坑是「触发太敏感」。温度传感器每跳一次数值都可能触发一次自动化,如果动作里还包含发通知,你的手机就会被刷屏。因此状态类触发通常配合 for 参数使用——「持续 5 分钟都高于 26 度」才算数,把抖动过滤掉,自动化才稳定。
条件:决定要不要执行
condition 是刹车。它在触发之后、动作之前被评估,所有条件全部通过,动作才会真正执行。HA 给的条件种类不少,常用的有这几种:
- state:某个实体正处于某个状态,比如「电视是开着的」。
- time:当前时间落在某个区间内,比如「晚上十点到早上六点」。
- sun:太阳在地平线以上或以下,适合做日出日落相关的判断。
- numeric_state:数值类的判断,比如「室温高于 26 度」。
- template:写一段 Jinja2 模板,返回真或假,表达力最强,也最容易翻车。
条件之间可以组合:AND 表示全部满足,OR 表示满足其一,NOT 表示取反。写条件时一个常见错误是「把条件当成触发」:比如你想要「回到家且天黑了才开灯」,其中「回到家」是触发,「天黑了」是条件——因为「回家」是瞬间发生的事件,而「天黑」是一个持续的状态。分清「事件」和「状态」,是写好自动化的第一道分水岭,很多「为什么不触发」的疑问,想通这一点就豁然开朗。
条件也可以写进 YAML 里,直观感受一下:
condition:
- condition: sun
after: sunset
- condition: time
after: "22:00:00"
before: "06:00:00"
- condition: state
entity_id: input_boolean.guest_mode
state: "on"
这段同时判断了「太阳下山」「夜里十点到早上六点」「访客模式开着」三件事,三个条件之间是 AND 关系,全部成立才会往下走。注意条件本身不带触发力:就算天黑了、时间也到了,只要你没回家,这条自动化依然纹丝不动。
动作:让设备真正动起来
action 是执行体,也是最容易写出花样的一环。核心动作是调用服务(service call),比如开灯、切换插座、发通知。除了直接调用服务,action 里还能放这些结构:
- delay:延迟若干秒,用来给窗帘、空调这类慢半拍的设备留出动作时间。
- wait_template:等到某个条件成立再继续,比死等固定秒数优雅得多。
- choose:条件分支,相当于 if/else,可以把多种情况塞进同一条自动化。
- repeat:循环,配合 wait_template 可以做轮询直到成功。
- service_template:根据模板动态决定调哪个服务,灵活但排查问题时会绕一些。
动作的顺序就是执行的顺序,从上到下一步步走。想跨设备并行,可以用后面章节讲的 script 和场景,也可以在自动化里调用一个脚本,把复杂度封装出去——这条思路在「场景与脚本的分工」一篇会详细展开。
动作里还有两个细节值得记住。其一,调用服务时可以带数据:开灯不只是「开」,还能指定亮度、色温甚至过渡时长,同样的 light.turn_on 配上不同数据就是完全不同的体验。其二,动作默认是阻塞式顺序执行的,遇到 delay 会真的停在那里等,所以一条自动化里塞太多等待会让整条流水线变得很钝——该拆成脚本的就拆出去。
模式:重叠触发时的行为
mode 是四要素里最容易被忽略、却最能决定体验的一个。它管的是:上一次执行还没结束,新的触发又来了,怎么办。HA 提供四种取值:
| 模式 | 行为 | 典型场景 |
|---|---|---|
| single | 忽略新触发(默认) | 通知类、不怕漏的轻任务 |
| restart | 中断当前执行,从头来 | 延迟熄灯、联动灯光 |
| queued | 排队依次执行 | 串行操作设备,避免冲突 |
| parallel | 多个实例并行跑 | 互不干扰的通知广播 |

举个例子:你写了一条「门一开就延时 3 分钟关灯」,用的是默认的 single。结果你前脚刚开过一次门,家人后脚又开门——第二次触发被忽略,灯可能就不按预期关了。同样的逻辑换成 restart,每次开门都重新计时,体验立刻顺滑。延时类自动化几乎都该用 restart,串行控制设备用 queued,这两条经验能解决大半的「自动化时灵时不灵」。
再补一个 queued 的场景:你家有两条自动化都要操作同一台电动窗帘,如果并行执行,电机收到的指令会打架。给它们都配上 queued,指令排队依次执行,硬件就不会犯迷糊。模式不是面子工程,它决定了一条自动化在「高频触发」下还靠不靠谱。
一个完整的例子
把四要素串起来,看一条真实可用的自动化:「晚上回家时,如果天已经黑了,就把玄关和客厅灯打开」。逻辑拆解:触发是「手机进入家庭围栏」,条件是「太阳已下山」,动作是「打开两盏灯」,模式用默认的 single 即可。
用 YAML 写出来大致是这个样子:
alias: 晚上回家开灯
trigger:
- platform: zone
entity_id: device_tracker.my_phone
zone: zone.home
event: enter
condition:
- condition: sun
after: sunset
action:
- service: light.turn_on
target:
entity_id:
- light.entry
- light.living
mode: single
这段配置相当于一个填空题:trigger 填「谁、在哪、进还是出」,condition 填「什么时候算天黑」,action 填「开哪几盏灯」。把其中任意一块换成模板或脚本,就能演化出复杂得多的玩法,但骨架永远是这个骨架。
运行环境也得跟上。如果你是把 HA 装在软路由上的玩家,可以参考 《软路由指南》 里关于旁路由与端口规划的章节,确保手机定位和外部访问这条链路通畅;若是装在 NAS 上,《NAS 搭建指南》 里虚拟机与 Docker 的部署方式同样适用,自动化跑起来之后并不占多少资源,配好「助手」分类下的 helper 实体就够用了。
延伸阅读
- 《群晖 DSM 指南》 中关于 Docker 套件与容器资源限制的部分,适合把 HA 长期挂在 NAS 上的读者。
- 触发器的完整清单与各平台参数,见本系列「触发器全家桶:时间、状态、事件、区域」一篇。
