Skip to content

小米米家 · 消息与规则引擎:事件驱动与App联动

技术栈:小米云事件路由 + 规则引擎 + 小爱同学(以小米米家 / MiOT 为案例) 适用场景:设备事件如何驱动 App 联动与场景编排

米家设备连上网只是开始。真正让消费级 IoT「有灵魂」的,是「开门了灯就亮、温度高了空调就降」这种联动。

本质是一个事件流:设备产生事件 → 小米云判断规则 → 推给 App 或其他设备。用户的诉求不是「看一个设备状态」,而是「让一堆设备按我的生活节奏协同」。工业里由 SCADA 脚本写死,消费级里必须由用户自助定义,甚至说一句「我睡了」就生效。

小米米家 消息与规则引擎

1.问题背景:米家事件驱动与联动的真实痛点

  • 触发链长且跨端:一个「开门」事件,既要推给 App 通知主人,又要下发给灯去开,还要写日志、联动摄像头。单点硬编码很快变成意大利面
  • 用户要的是「如果…就…」:米家 App 里的智能场景就是一套低代码 if-this-then-that 引擎,对普通用户要可读、可改、可撤销
  • 离线消息不能丢:灯在门开的瞬间正好离线,开灯指令不能丢了。要能在设备上线后补发,且保证最终一致
  • 十亿级的洪峰:每台设备都会上报事件,十亿台设备下规则匹配不能慢、推送不能丢、离线队列不能爆

2.设计理念:事件总线 + 离线补发 + 小爱入口

米家把消息层设计为四个组件:

组件职责
事件总线设备上报 → 统一 topic 路由 → 多消费者订阅
规则引擎用户定义的「如果…就…」场景,命中后执行动作列表
离线队列设备不在线时缓存下行指令,上线即补发
小爱映射口语「打开客厅灯」→ 物模型写操作,与规则引擎共用动作出口

不同消息选不同可靠性:心跳用最多一次,门锁状态用至少一次,必要场景才用恰好一次。高优消息(告警、控制)优先落盘与重试,低优消息允许丢弃。

设备不在线时,小米云把下行指令缓存到设备影子(见第四篇),待设备上线立即补发。影子里的 desired(期望)与 reported(实际)对账,是弱网下状态不失控的关键。

这种分级的可靠性策略让米家避免了"为所有消息付出恰好一次的成本"。十亿台设备的心跳如果全部按至少一次处理,云端存储和重试开销会指数级膨胀——心跳丢了就丢了,下一轮还会来。

3.实际应用:从事件到联动的完整链路

3.1 事件上报与分发

米家设备经连接层(第二篇)上报属性变化事件(如门锁 opened = true)。小米云事件总线按 topic 分发,同时推给规则引擎、日志、监控等消费者。

3.2 规则引擎匹配

用户定义的「开门 → 开灯」命中后,规则引擎并发执行动作:给 App 推通知、向灯设备下发开灯指令、写一条日志。一条规则内部表达为 if 条件 then 动作列表,条件可叠加「时间窗」「人在家」等上下文。

3.3 小爱同学入口

用户说「打开客厅灯」,小爱解析意图后映射到具体设备的物模型写操作。超级小爱(大模型加持)还能听懂口语化表达,支持「语音创建自动化」——说一句即可生成一条规则。

3.4 推送与离线补发

关键事件(门锁异常)走高优先级系统推送,普通状态变化仅更新 App 内设备卡片,避免通知轰炸。设备休眠时下行指令进离线队列,设 TTL 防止堆积——门锁离线期间缓存了「反锁」指令,上线后补发一次即可。

一个典型场景:用户在公司远程关家里空调。空调此刻离线(家人拔了插头)。小米云把"关机"指令缓存到设备影子 desired 字段,设 30 分钟 TTL。30 分钟内空调上线,拉取 desired 后执行关机并上报 reported 对账;超时则丢弃并在 App 提示"设备离线过久,指令未送达"。

推送通道对 Android/iOS 分别走系统推送服务。关键事件(门锁异常)走高优先级通知确保用户及时感知,普通状态变化仅更新 App 内设备卡片,避免通知轰炸——十亿台设备如果每条心跳都推通知,用户手机早炸了。

4.注意事项

  • 事件去重与幂等:弱网下同一事件可能重复上报,规则引擎要按事件 ID 去重,避免「开灯」被执行两次。
  • 离线队列要设上限:队列满时必须选择丢弃最旧还是最新,并在 App 侧提示用户「设备离线过久,指令已过期」。
  • 小爱与规则共用动作出口:避免「小爱开了灯,规则又关掉」,需要在动作层做冲突检测或优先级排序。

5.小结

米家消息层的核心是「事件总线 + 规则引擎 + 离线补发 + 小爱入口」四件套。事件总线负责一对多分发,规则引擎负责声明式联动,离线消息靠设备影子对账保证最终一致,小爱同学把口语变成物模型操作——是消费级「零门槛」的关键入口。

下一篇(四),我们钻进「物模型」——MIoT-Spec 如何用一套统一的词汇描述千奇百怪的设备。

参考链接