Home Assistant 中文文档 下载 App

Home Assistant 事件总线架构

事件总线是什么

Home Assistant 的事件总线(Event Bus)是整个系统的心脏——所有组件之间的通信都是通过事件完成的。理解事件总线就能理解 Home Assistant 的架构为什么这么灵活。

架构总览

          ┌─────────────┐
          │  实体状态变化  │ ← 传感器上报、设备操作、自动化动作
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │  Event Bus   │ ← 所有事件的中转站
          └──────┬──────┘
         ┌───────┼───────┐
         ▼       ▼       ▼
    ┌────────┐ ┌────────┐ ┌──────────┐
    │ 自动化  │ │ 仪表盘  │ │ 脚本/通知  │ ← 监听事件并响应
    └────────┘ └────────┘ └──────────┘

整个架构是发布-订阅(Publish-Subscribe)模式——任何组件都可以发布事件、任何组件都可以订阅事件。发布者和订阅者互相不知道对方的存在。

核心事件类型

state_changed(最重要)

任何实体状态变化时发出。包含:

{
  "event_type": "state_changed",
  "event": {
    "entity_id": "light.living_room",
    "old_state": {"state": "off", "attributes": {...}},
    "new_state": {"state": "on", "attributes": {...}}
  }
}

自动化的 state 触发器底层就是监听 state_changed 事件。

automation_triggered

每次自动化触发时发出。适合做自动化的自动化(比如"如果某个自动化频繁触发超过 10 次 → 发通知")。

homeassistant_started / homeassistant_stopped

Home Assistant 启动和停止时发出。适合做"启动后恢复某个状态"、"停止前保存数据"。

call_service

任何服务被调用时发出。可以监听特定服务调用做额外逻辑。

user_logged_in

有人登录 Home Assistant 时发出。

timer_out

定时器到期时发出(如果你用了 timer 实体)。

custom

社区集成可以发出自己的自定义事件(比如 xiaomi_aqara.movement_timeout——小米人体传感器 2 分钟没检测到人)。

在自动化里监听事件

用 event 触发器

trigger:
  - platform: event
    event_type: state_changed
    event_data:
      entity_id: sensor.motion_living_room
      to_state: "on"

这和 state 触发器的效果一样——但 event 触发器可以监听任意事件,包括自定义事件。

监听特定属性变化

trigger:
  - platform: event
    event_type: state_changed
    event_data:
      entity_id: climate.living_room
      # 不指定 to_state → 任何状态变化都触发

在 Developer Tools 里监听事件

  1. Developer Tools → Events
  2. 选 Listen to → state_changed
  3. 点 Start Listening
  4. 手动操作家里的设备(比如开个灯)→ 右边实时显示事件 JSON

这是调试自动化最有用的工具——在写自动化之前先监听一下事件,看实体状态变化时实际发出的事件是什么样的。

用 events: all 监听所有事件

trigger:
  - platform: event
    event_type: state_changed
action:
  - service: notify.mobile_app_me
    data:
      message: >
        {{ trigger.event.data.entity_id }}
        {{ trigger.event.data.old_state.state }} →
        {{ trigger.event.data.new_state.state }}

注意:all 触发非常频繁——整个 Home Assistant 每秒都可能有几十个 state_changed 事件。不要在这个触发器里做"发通知"之类的动作,否则你的手机会被刷屏。适合做日志记录或限流后的聚合处理。

自定义事件(fire_event)

你可以在自动化里主动发出事件,让其他自动化监听:

# 自动化 A:检测到有人回家
alias: 检测到家
trigger:
  - platform: zone
    entity_id: person.me
    zone: zone.home
    event: enter
action:
  - service: homeassistant.fire_event
    data:
      event_type: my_custom_home_arrival
      event_data:
        person: "{{ trigger.entity_id }}"
        time: "{{ now().strftime('%H:%M') }}"

# 自动化 B:监听自定义事件
alias: 欢迎回家
trigger:
  - platform: event
    event_type: my_custom_home_arrival
action:
  - service: tts.piper_say
    data:
      entity_id: media_player.kitchen
      message: "{{ trigger.event.data.person.split('.')[-1] }} 欢迎回家"

事件总线的可扩展性

Home Assistant 的事件总线是同步且轻量的——每个事件会被立即分发给所有订阅者。Python 级别的事件监听器可以做任何事:

这是 Home Assistant 比其他平台(米家、HomeKit)扩展性强得多的根本原因——没有黑盒、所有事件都可访问。

常见问题

事件丢了怎么办

事件总线本身是可靠的——不会主动丢事件。但如果 Home Assistant 正在重启、或者某个监听者崩溃了,那部分事件会错过。自动化有 for 参数可以做防抖,配合正确的实体选择一般能覆盖绝大多数场景。

事件总线会不会过载

不会。即使你有 1000 个实体,每秒 state_changed 事件也不会超过几十条。Home Assistant 核心用 asyncio 异步处理,轻松应对。

怎么知道某个实体有哪些属性

看 Developer Tools → States → 找到实体 → 右边的 Attributes 列。每个实体的属性取决于它的设备类型和集成。