自动化的调试与日志追踪

自动化写完才是开始

Automated 系统有个反直觉的特点:调试时间远大于编写时间。一条自动化写完两分钟,但你可能在之后两周里反复琢磨「为什么昨晚它没触发」。本篇把 HA 提供的调试工具和排查套路打通,让你的自动化可观察、可回放、可验证。

一句话原则:不可观察的自动化就不可信任。所有排查都围绕一件事——把「发生了什么」变成看得见的东西。

一个常见心态误区也值得先点破:出问题时第一反应往往是「HA 是不是有 bug」,但经过无数人的血泪验证,绝大多数问题的根源是自己的配置——条件写错、实体 ID 拼错、时区不对、网络不稳。调试的第一步是把「怀疑系统」换成「怀疑自己」,查起来快得多。记住这条,能帮你省下大量翻 GitHub issue 的时间。

排查的四个工具

工具 位置 看什么
实体状态 开发者工具 → 状态 实体现值与最近变化
事件监听 开发者工具 → 事件 事件总线实时流
日志 设置 → 系统 → 日志 系统与集成报错
历史/日志簿 历史与日志簿 实体过去的变化轨迹

四个工具对应四个经典问题:传感器值对不对(状态)、事件发没发(监听)、系统有没有报错(日志)、这条自动化最近跑过没有(历史)。

实体状态页除了现值,还有两个宝贝:实体的属性区(attributes)藏着集成给出的元数据,很多时候「数值类型不对」「单位变了」的答案就藏在里面;以及「相关性」区域,显示哪些实体与此实体相关,找连坐问题利器。

事件监听页则建议每次写新自动化前开着它,把设备实际操作一遍——先验证信号存在,再写触发器。顺序永远是:先看见信号,再写配置,反着来必然返工。

日志级别与配置

默认日志输出有限,调试期可以临时调高级别:

logger:
  default: info
  logs:
    homeassistant.components.automation: debug
    homeassistant.components.zha: debug

debug 级别会把该组件的详细信息(包括自动化被评估的过程)刷进日志,定位问题后记得调回,否则日志文件会膨胀。一个好习惯:调试时 temporary 开 debug,确认正常后恢复 info 或 warning。

日志簿:自动化的「行车记录仪」

日志簿(logbook)是调试自动化最被低估的工具。它按时间记录「谁在什么时候发生了什么」——包括服务调用、状态变化、自动化执行,过滤到某个实体后尤其清晰。

典型用法:今早 7 点的浇花自动化没跑。打开日志簿,过滤浇花相关的实体或自动化本身:如果连「触发」记录都没有,问题在触发端(时间没到、条件被跳过、自动化被禁用);如果有触发记录但没有后续服务调用,问题在动作端。先有记录,再谈分析,日志簿就是那个记录。

日志簿还能反过来自检:每天扫一眼,确认关键自动化都按预期跑过。比起等「灯怎么没开」才发现问题,这种主动巡检能把故障消灭在家人抱怨之前。

常见故障与排查路径

一条条走,十分钟内基本能定位:

  1. 完全没触发:检查实体状态是否真的变化(监听页验证);时间触发注意时区;自动化是否被禁用。
  2. 触发了但没执行:条件未通过——在调试器里逐步评估条件,或临时在动作前加一条通知看走得到哪一步。
  3. 执行了但结果不对:服务参数问题——在开发者工具的「服务」页单独调用同样服务,验证参数。
  4. 间歇性失败:多半是设备响应慢或网络抖动——给动作加 wait_template 与 timeout,或检查设备信号。
  5. 重启后失效:状态依赖问题——回顾「状态持久化」一篇的检查清单。
  6. 时好时坏地重复执行:mode 没选对——延时类自动化换 restart,操作同一设备的自动化换 queued。

第 6 条值得多讲一句:它是「四要素」章节埋的伏笔。很多人把间歇性问题怪到设备头上,排查半天,最后发现只要把 mode 改掉就好了。只要自动化会重复或并发触发,先问 mode 选对了吗。

排查六步法

trace:自动化执行追踪

HA 的「追踪」功能(编辑器右侧的「追踪信息」)会把一次完整执行的每一步记下来:触发是否命中、每个条件 evaluated 的结果、动作执行到哪。打开一条最近执行过的自动化,就能看到最近几次运行的 trace。

这是最接近「单步调试」的体验:哪一步是 false,一目了然,不用再靠猜。配合 temporary 在动作里插入日志,几乎所有逻辑错误都能现形。

trace 只保存最近若干次运行,所以「昨晚那一次」可能已经看不到。正因为如此,上节的日志探针才有存在价值——trace 管近期细查,探针管长期留痕。两者搭配才完整。

调试模式与「执行」按钮的区别

新手常混淆两个动作:编辑器右上角的「执行」按钮触发的是只跑动作的测试,它绕过触发器和条件;而「调试」里可以选一次真实触发来完整回放。「执行」用来验证动作本身通不通,完整回放用来验证整条链路。先「执行」确认动作没写错,再等真实触发看链路,这个顺序最高效。

顺带提醒:编辑器里还有「在新建中测试」的入口,改动未保存也能逐步预演。改配置最怕「保存后才发现整个坏了」,这个功能就是帮你卸下这道心理负担的。

给自动化加「探针」

非调试期也想观察?三个廉价探针:

  • 动作末尾发通知:只给管理员推送,家人不受打扰;出问题时你能立刻知道。
  • 写入 helper 记录执行时间:input_datetime 记「上次执行时间」,仪表盘摆张卡片,没跑的日子一眼可见。
  • 日志自定义输出:在脚本里用 system_log.write 之类的服务写一条带上下文的日志,排查时按关键字过滤。

通知探针有个进阶用法:加上 {{ trigger.platform }}、触发实体等上下文,推送内容本身就成为诊断信息。「浇花自动化在 time 触发了,但被降雨条件拦下」这类有因有果的通知,比一句「没执行」信息量大十倍。

action:
  - service: system_log.write
    data:
      message: "浇水自动化执行,来源触发:{{ trigger.platform }}"
      level: info

三种探针对比

让自动化自带「自检」

成熟玩家的自动化通常长这样:开机时跑一次自检,检查依赖的实体是否存在、关键设备是否在线,异常就推一条预警而不是默默装死。这类「健康检查」自动化写一次受益终身,尤其适合家里设备多、网络环境复杂(比如 HA 跑在软路由上,还挂着 NAS 上的一堆服务)的玩家。

自检的核心就一句话:把「可能出问题的地方」提前列成清单,让系统自己巡检。

一个最小自检脚本的骨架:

script:
  health_check:
    alias: 系统自检
    mode: single
    sequence:
      - choose:
          - conditions:
              - condition: template
                value_template: >-
                  {{ states('sensor.living_temp') in ['unavailable', 'unknown', 'none'] }}
            sequence:
              - service: notify.notify
                data:
                  message: 客厅温度传感器离线

照着这个模式把关键传感器逐个检查一遍,每天跑两次。家人还没感觉到异常,你的手机就已经先收到提醒了——这才是自动化系统该有的样子。

排查完成后的收尾

问题解决后别急着收工,三件事能避免下次重蹈覆辙:把临时加的探针变成常驻通知或留痕;把这次故障的成因写进配置的 note 或自动化别名备注;给相关自动化补上 timeout 或容错逻辑。调试的终点不是「修好了」,而是「同样的错不会再犯」。

如果家里是多人协作维护配置,再补一条:把排查过程记一笔到配置目录的笔记里。下次同样故障,家人或未来的自己按图索骥,不用从头猜起——知识沉淀下来,系统才越用越顺手。

延伸阅读

  • 持久化机制见本系列「状态持久化与开机还原」。
  • 追踪与总线事件关系见「事件总线与自定义事件」。
  • 网络层排查可参考 《软路由指南》,备份容灾见 《NAS 搭建指南》。