全屋智能 · 设备清单 → 自动化 + 场景
> 客户给我们一台网关的设备清单,我们给他:变量设计 + 功能库匹配 + 节点库。不涉及采购、不涉及报价——那是销售的事。
一句话定位
> MCP 拿到的设备清单就是全部输入。 我们不脑补设备名、不脑补 did、不假装客户有调光灯——按现有设备能力落地自动化和场景,写不出来的功能标"差硬件"留给销售跟进。
一、三道输入通路(任一即可)
| 通路 | 怎么拿 | 拿到什么 |
|---|---|---|
| A · MCP 在线 | mijia_read(devices) |
did / name / room / model / online(最全) |
| B · 解包 .bak | mijia_rule_kit.unpack_bak + device_registry.py |
did / urn / 哪些规则引用(无设备名/房间,需人工补) |
| C · 手输 | 按下方 schema 在 templates/功能勾选单.md 里手填 |
缺啥填啥 |
统一输入 schema(本技能只吃这个):
{
"customer": "客户代号(不要写真名外发)",
"gatewayIp": "192.168.0.x",
"devices": [
{
"did": "1004885182",
"name": "罗格朗一位开关 3",
"room": "厨房",
"model": "lhz.switch.1gang",
"online": true
}
]
}
二、设备能力分级(L0–L8)
判定规则在 assets/device-capability-rules.json(按 model 前缀正则匹配,团队可持续扩充)。
| 级别 | 含义 | 典型 |
|---|---|---|
| L0 | 网关本体 / 虚拟服务 | 米家中枢网关、虚拟事件源 |
| L1 | 开关级 | on/off(罗格朗、苏米智能开关、Yeelight 开关、插座) |
| L2 | 调光级 | on/off + 亮度 |
| L3 | 调色级 | + 色温 / 色彩 ← 色温场景门槛 |
| L4 | 窗帘级 | 开 / 合 / 行程 % |
| L5 | 传感级 | 存在 / 人体 / 光照 / 门磁 / 水浸 / 烟感 |
| L6 | 语音级 | 智能音箱(TTS、语音入口) |
| L7 | 门锁级 | 智能门锁(开门 / 反锁事件) |
| L8 | 面板级 | 带屏场景面板(免手机切模式) |
规则表里没匹配的型号 → 标 LEVEL_UNKNOWN → 人工确认后回填规则表(一次确认、长期受益)。
三、全局状态变量 homeState(先建变量再写规则)
3.1 默认 9 个状态
变量名: homeStateSumi scope: global type: string
合法值(可增减):
回家 | 离家 | 明亮 | 温馨 | 休闲 | 放松 | 观影 | 就餐 | 休憩
id 必须是 11 位纯字母数字(含下划线会被静默丢弃——这是坑,变量"消失了"先查这里)。
3.2 两层解耦架构(homeState 模式)
入口层(N 个,互不重复) 出口层(M 条,一状态一链)
┌ 按键 ────────┐
├ 门锁/人脸 ───┼→ varSetString(homeState, "观影") ┌ varChange(homeState,"=","观影") → 批量 deviceOutput
├ 语音/虚拟事件┤ ├ varChange(homeState,"=","就餐") → …
└ 定时/自动化 ─┘ └ varChange(homeState,"=","离家") → 全关 + TTS
为什么这么设计:
- 入口层只写变量 → 新增任何入口(语音/门锁/面板/定时)零重复
- 出口层只挂在 varChange 上 → 触发源与动作彻底解耦
- 实测直连式(设备链焊死在按键上)的代价:每加一个入口要把整条设备链重抄一遍,137 节点里一半是重复链
3.3 四条硬规则
- 变量值只允许声明的枚举(用 nop 注释卡提醒)
- 入口层用
varSetString(elements:[{type:"const", value:"观影"}]) - 出口层用
varChange,字符串比较用operator:"="+ 标量 v1 - 变量 id 11 位纯字母数字
3.4 灯具能力决定出口层写法
| 灯具级别 | 出口层 deviceOutput 形态 |
|---|---|
| L3 调色级 | 变量驱动写:{did, siid, piid, dtype:"number", scope, id, min, max, step}(不写 value)——改模式只改变量,所有灯自动跟随。实测 1 个色温变量可被 57 个 deviceOutput 同时引用 |
| L1 开关级 | 直接写:{value: true/false},每模式一条链 |
四、功能库匹配(21 条,分 5 类)
库在 assets/function-library.json(流程在 SKILL,数据在那里——团队可扩充条目)。
| 类别 | 条数 | 典型范式 |
|---|---|---|
| 自动化 | 5 | 人走关灯 / 进门开灯 / 夜起 / 人来开 / 定时 |
| 联动 | 3 | 离家全关 / 多手机防抖 / 窗帘联动 |
| 场景 | 8 | 明亮/温馨/休闲/放松/观影/就餐/休憩/一键全关 |
| 守卫 | 2 | 洗手间守卫循环 / 无人后延时关 |
| 安全 | 2 | 离家布防 / 水浸报警 |
匹配规则(每条功能声明 requires.minLevels + logic: all|any):
| 判定 | 落进哪栏 |
|---|---|
| ✅ 现有设备满足 | 可做栏(功能勾选单) |
| ⚠️ 现有设备有但离线 | 可做栏,标注阻塞原因(如"传感器离线,先修") |
| 🛒 差硬件 | 可做栏 · 阻塞项(差哪个 L? 标清楚) |
节点量参考是硬指标(用来校准工作量):开关级场景每模式 6–10 节点;调光调色场景每条模式链 30–140 节点。
五、节点库(极客版实战写法)
> 权威源:_mijiaflow_source/docs/node-catalog.md(写任何 graph 前必读,禁止凭记忆)。
5.1 deviceOutput 三种形态(最关键)
| 形态 | 用途 | props 形态 | 何时用 |
|---|---|---|---|
| ① 直写常量 | 写固定开/关 | {did, siid, piid, value: true/false} |
简单开关级场景 |
| ② 调用动作 | 切换 / 脉冲 / 场景 | {did, siid, aiid, ins:[...]} |
toggle、电机动作 |
| ③ 变量驱动写 | 跟随 homeState | {did, siid, piid, dtype:"number", scope, id, min, max, step}(无 value) |
调光调色场景(B 线场景性能最高) |
5.2 deviceInput 三种形态
| 形态 | props 形态 | 何时用 |
|---|---|---|
| 属性事件(整数枚举) | {did, siid, piid, dtype:"int", operator:"include", v1:[...]} |
存在传感器([0,1] 有人/无人) |
| 属性事件(布尔) | {did, siid, piid, dtype:"boolean", operator:"=", v1:true} |
⚠️ boolean 必须用 "=" + 标量 |
| 事件通道(按键/门锁) | {did, siid, eiid, arguments:[{piid, dtype:"string", operator:"=", v1:"模式名"}]} |
4 模式按键、门锁开门事件 |
5.3 statusLast 防抖
- 节点:
statusLast,props.timeout(毫秒)+cfg{unit:"s", value:30}(双写且必须一致) - 用途:状态维持 N 秒才向下传(防误触)
5.4 varSetNumber / varSetString
varSetString(homeState, "观影")入口层用varSetNumber给亮度/色温变量赋值用elements:[{type:"const", value:N}]写常量- 多个 varSet 串行时插 3ms
delay(防同帧竞争)
5.5 varChange(出口层触发)
varChange(homeState, "=", "观影")字符串比较- ⚠️
v1只在include时才是数组;其他都是标量 - 出口层
v1是字符串,dtype用string
5.6 group.* 群组 did
- 真实方案实测:李府 R1 客厅用 8 个 group.*
- 把同区域同类型设备打组,
deviceOutput(did="group.xxx", ...)一次写一群 - MijiaFlow / .bak 看不到群组名,必须让客户在米家 App 或极客版画布里确认
5.7 虚拟事件("虚拟服务-产生虚拟事件")
- 极客版网关自带的虚拟设备
- 用于规则间通信:F-LINK-002 离家防抖广播 → 各处"收到"触发器
- 比 hardcode 写多触发器灵活
5.8 counter + 状态复查(守卫循环 P9)
- 模式:F-GUARD-001 洗手间守卫
- 链路:无人 → counter 累 30 次 → delay 10 分钟 → deviceGet 复查仍无人 → 关闭
5.9 8 大范式(A 线)
| # | 范式 | 节点组合 | 典型 |
|---|---|---|---|
| P1 | 进门开灯 | deviceInput + deviceOutput | 门锁 + 灯 |
| P2 | 人走关灯 | deviceInput + statusLast + deviceGet + deviceOutput | 厨房关灯 |
| P3 | 时段门禁 | deviceInput + timeRange | 22:00-06:00 才生效 |
| P4 | 多传感器合并 | deviceInput×N + signalOr | 任一传感器发现人就开 |
| P5 | 延时防抖 | deviceInput + statusLast | 停留 20 秒才开 |
| P6 | 写前预检 | deviceGet + deviceOutput | 仅用于固定状态写入 |
| P7 | 调试开关 | 变量门控 TTS | 调试期开播报 |
| P8 | 工作日门 | 定时 + 工作日判定 | 周末不执行 |
| P9 | 守卫循环 | counter + delay + deviceGet | 洗手间 |
| P10 | 多源防抖 | statusLast×N + 状态与 + 虚拟事件 | 离家防抖 |
> ⚠️ P6 边界:只适用于"设为固定状态"(开/关)。toggle/脉冲/场景/其它动作不套用——先查状态再切换会改变语义;切换请用 call_action(siid/aiid/ins)。
六、产出物
填 templates/功能勾选单.md:
功能勾选单-<客户代号>-<日期>.md
一、设备能力盘点
二、功能勾选
✅ 现有设备可做(按 L 级别 + 节点量 + 是否需状态变量)
⚠️ 阻塞(设备离线)
🛒 差硬件(说明差哪个 L,不替销售报价)
三、homeState 变量设计
四、客户签字 / 日期
勾选结果是 S4 规则生成的唯一需求来源(没勾的功能不做)。
七、流水线衔接
sumi-export-bak 客户导出 .bak 路径
↓
sumi-analyze-bak AI 解包 → 设备+区域
↓
sumi-scene-planner ★ 你在这里 MCP 设备 → 变量 + 功能库匹配 + 节点库
↓ 客户勾完
sumi-mijia-debug-suite S4 mijia_rule_kit 生成规则
↓
S5 守护写入 → S6 验证 → S7 收尾
八、红线
- ❌ 不写任何规则——本步只出变量设计 + 功能勾选单
- ❌ 不脑补设备名/did——只用
设备台账.json中status: confirmed的条目 - ❌ 不替销售报价——差硬件的功能只标"差哪个 L",请购走销售流程
- ❌ 不把"差硬件"的功能混进"可做"栏凑数
- ✅ homeState 变量必须先
create_variable建好再写规则 - ✅ 外发版本零私密数据(客户真名 / IP / did / 内部命名一律不出现)
九、配套文件
sumi-scene-planner/
├── SKILL.md ← 本文件(流程,不含客户数据)
├── README.md ← 安装与分发说明
├── assets/
│ ├── function-library.json ← 功能库(21 条,团队可扩充)
│ └── device-capability-rules.json ← 型号→能力级别(L0-L8)匹配规则
└── templates/
└── 功能勾选单.md
写 graph 前必读:_mijiaflow_source/docs/node-catalog.md(极客版节点 schema 权威文档)。