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 里监听事件
- Developer Tools → Events
- 选 Listen to →
state_changed - 点 Start Listening
- 手动操作家里的设备(比如开个灯)→ 右边实时显示事件 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 级别的事件监听器可以做任何事:
- 写入数据库
- 推送到 MQTT
- 触发 Webhook
- 调用外部 API
- 甚至连接 TensorFlow 模型做 AI 推理
这是 Home Assistant 比其他平台(米家、HomeKit)扩展性强得多的根本原因——没有黑盒、所有事件都可访问。
常见问题
事件丢了怎么办
事件总线本身是可靠的——不会主动丢事件。但如果 Home Assistant 正在重启、或者某个监听者崩溃了,那部分事件会错过。自动化有 for 参数可以做防抖,配合正确的实体选择一般能覆盖绝大多数场景。
事件总线会不会过载
不会。即使你有 1000 个实体,每秒 state_changed 事件也不会超过几十条。Home Assistant 核心用 asyncio 异步处理,轻松应对。
怎么知道某个实体有哪些属性
看 Developer Tools → States → 找到实体 → 右边的 Attributes 列。每个实体的属性取决于它的设备类型和集成。