HA 自动化翻车 10 例:从反复亮灭到循环触发,一次讲清根因和修法
自动化这东西,写的时候觉得自己想得很清楚,跑起来却总在奇怪的地方翻车。我整理了 10 个最高频的翻车现场——没有一个是"逻辑想错了",全是触发器、条件、上下文这三件套没吃透。每个都给根因和可直接抄的 YAML 修法,照着改就能避坑。
基础概念(trigger / condition / action、mode)先复习 自动化入门;模板报错这一类专门看 Jinja2 模板排障。
第 1 例:人体传感器抖动,灯反复亮灭
现象:人坐那没动,灯自己一闪一闪;或者人走了灯还亮、回来又灭。
根因:人体/红外传感器边缘会抖动,一次经过可能触发好几次;门窗磁也一样,信号偶尔跳变。自动化每次都被带着重跑,灯就跟着抽风。
修法:要么让触发"持续一小段时间才算数",要么让同一次事件只跑一遍:
trigger:
- platform: state
entity_id: binary_sensor.hall_motion
to: "on"
for: "00:00:05" # 持续 5 秒才认定有人,抖一下不算
或者把自动化 mode 设成不叠加:
结论:传感器抖动是第一大坑,for: 去抖 + mode: single 基本能灭掉九成的反复亮灭。
第 2 例:两个自动化抢同一盏灯
现象:一个自动化说"有人开灯",另一个说"没人关灯",结果灯在开/关之间反复横跳。
根因:把"开"和"关"拆成两条独立自动化,它们各自判断、各自执行,谁也不知对方存在,于是互相打架。
修法:同一设备的所有逻辑合并进一个自动化,用 choose 分支:
trigger:
- platform: state
entity_id: binary_sensor.hall_motion
action:
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.hall_motion
state: "on"
sequence:
- service: light.turn_on
target: { entity_id: light.hall }
- conditions:
- condition: state
entity_id: binary_sensor.hall_motion
state: "off"
sequence:
- service: light.turn_off
target: { entity_id: light.hall }
结论:控制面收敛到一处。同一盏灯的所有逻辑在一个自动化里用 choose 分流,别让两条自动化各管各的。
第 3 例:condition 写对了却从不触发
现象:加了 condition 之后自动化干脆不跑了,去掉又乱跑。
根因:把"某个状态等于 X"写成了 trigger 上下文里的判等。trigger 类条件只在"由触发引起"的上下文里有值;你想判断"当前实时状态是不是 X",得用 state 触发或在 condition 里显式写实体。
修法:分清两种判等:
trigger 与 condition 的区别、trigger 上下文变量怎么用,看 trigger 与 condition 区别。
结论:trigger 上下文只活在"触发那一刻",判断实时状态必须用 state 条件写实体 id。
第 4 例:晚上自动化大白天跑
现象:设了"日落后开灯",结果下午也开;或定时任务时间点全差了 8 小时。
根因:时区没设对。HA 的 time / sun 触发器按系统时区算,装完没配 timezone 或 Docker 没传 TZ,就按 UTC 跑,比本地晚 8 小时。
修法:先确认时区:
设置 → 系统 → 常规里把时区设成本地(如 Asia/Shanghai);- Docker 启动务必传
-e TZ=Asia/Shanghai,否则容器内时间还是 UTC。
docker run -d --name ha \
-e TZ=Asia/Shanghai \
-p 8123:8123 \
ghcr.io/home-assistant/home-assistant:stable
结论:所有"时间不对"的怪事,先查时区,再查自动化的时间窗口。
第 5 例:模板报错,整条自动化挂掉
现象:改了个模板,自动化直接不执行,日志里一堆 Jinja 报错。
根因:模板语法错(少了括号、变量不存在、用了列表当字符串),HA 解析 YAML 时整条挂。
修法:上线前先到 开发者工具 → 模板 里把模板跑一遍,能渲染出预期结果再粘进自动化。常见写法:
# 先判断变量存在,避免 None 当字符串用
action:
- service: notify.mobile_app
data:
message: "温度 {{ states('sensor.living_temp') }}"
模板排错的完整套路看 Jinja2 模板排障。
结论:模板先 dev tools 测、再进自动化,能省掉一半"改完就挂"的来回。
第 6 例:设备离线,condition 永远不过
现象:某个设备掉线后,依赖它的自动化要么卡死、要么永远不执行。
根因:condition 判某个实体状态,但设备离线时实体是 unavailable,既不是你判的 on 也不是 off,于是条件永远不满足。
修法:用 availability 把离线状态显式处理,或给状态判断加兜底:
condition:
- condition: state
entity_id: binary_sensor.door
state: "on"
- condition: template
value_template: "{{ states('binary_sensor.door') not in ['unavailable','unknown'] }}"
或直接在 action 里判断可用性再执行,避免对离线设备发指令。
结论:凡依赖外部设备状态的自动化,都要显式处理 unavailable,否则设备一掉线逻辑就失聪。
第 7 例:升级之后自动化失效
现象:某次升级后,原本好用的自动化不动了,也没报错。
根因:用了 device 触发器/条件。设备重新接入或重命名后 device id 会变,绑定 device 的自动化就断了;而 entity id 稳定得多。
修法:一律用 entity 写触发器和条件,别用 device:
# 不推荐:platform: device,device_id 一变就断
# 推荐:
trigger:
- platform: state
entity_id: light.hall # 实体稳定,改名也只改这一处
结论:device 图省事但脆弱,entity 才是长期不坏写法。升级后失效先查是不是用了 device。
第 8 例:灯一亮又触发自身再开灯(循环触发)
现象:自动化开灯 → 灯状态变 on → 又触发"灯变 on 就开灯" → 无限循环或卡死。
根因:trigger 监听了"灯状态变化",而 action 本身又改变了灯状态,事件回灌把自己喂死了。
修法:trigger 只听"人/传感器",不听"灯自己";或用 trigger 上下文过滤掉自身引起的变化:
trigger:
- platform: state
entity_id: binary_sensor.hall_motion
to: "on"
# 注意:别把 light.hall 放进 trigger,否则开关灯都会反噬
结论:触发源和动作目标要隔离——听传感器,别听被控制的设备自己。
第 9 例:只在工作日执行的自动化,周末也跑
现象:"上班时间离家关灯"周末也触发了,人还在家灯就灭了。
根因:只用时间窗口判断,没区分工作日/周末。
修法:接 workday 集成(或 binary_sensor.workday),把"是不是工作日"作为 condition:
结论:涉及"工作日/节假日"的逻辑,别靠手写时间,用 workday 集成兜底。
第 10 例:2FA 挡住了 service 调用
现象:自动化调用某个 service 时报权限错,手动点却正常。
根因:该 service 需要管理员上下文,而自动化默认上下文被 2FA / 管理员保护挡下。
修法:确认 service 本身是否需要提权;用 HA 自动化入门 里讲到的 automation 上下文,或在调用前显式声明所需权限。更稳妥的是把敏感操作拆成需要人工确认的步骤,而不是让自动化偷偷提权。
结论:自动化不是万能钥匙,涉及管理员权限的 service 要显式授权,别让自动化绕过 2FA。
10 例实操的最小避坑清单
- 传感器抖动 → trigger 加
for:或自动化mode: single(第 1 例)。 - 多自动化抢设备 → 合并到一处用
choose(第 2 例)。 - condition 不触发 → 判实时状态用
state条件写实体(第 3 例)。 - 时间全错 → 先查时区
TZ(第 4 例)。 - 模板报错 → 上线前 dev tools 测(第 5 例)。
- 设备离线失聪 → 显式处理
unavailable(第 6 例)。 - 升级失效 → 用 entity 别用 device(第 7 例)。
- 循环触发 → 触发源隔离,别听被控设备(第 8 例)。
- 周末漏逻辑 → 接 workday 集成(第 9 例)。
- 权限被挡 → automation 上下文显式授权(第 10 例)。
一句话总结:自动化翻车几乎都落在"触发谁、条件判什么、上下文是谁"这三件事上。把这三件套想清楚,再复杂的联动也能稳。想用节点流替代 YAML 的,参考 Node-RED 自动化。
相关教程
- 自动化入门:trigger / condition / action 三段式与 10 个可抄 YAML 模板。
- trigger 与 condition 区别:trigger 上下文变量、state 触发与模板条件的坑。
- Jinja2 模板排障:六类报错决策树与生产模板防错范式。
- Node-RED 自动化:用节点流写复杂联动,绕开 YAML 嵌套。