跳转到内容

miot(小米设备)

小米的 WiFi 设备(插座、风扇、电饭煲……)走局域网 miIO 协议,不经云端。 接一台设备要三样东西:IP、token、型号。

[[device]]
name = "plug_bedroom"
adapter = "miot"
ip = "192.168.52.60"
token = "00112233445566778899aabbccddeeff"
model = "cuco.plug.v3"
device_id = 584348197

token 在设备里,出厂后只能从米家云端拿:

Terminal window
rha miot-token --username <米家账号>

它一行一台,把账号下每台设备的 model、IP、didtoken 一并打印出来——开头说的 三样东西全在这一行里,型号不用再去别处查。did 就是下面的 device_id

DHCP 租约会漂,只按 ip 寻址是脆的——设备换了地址就表现成「莫名离线」。 配上 device_id 之后握手会校验身份,ip 上没有设备时还会自动扫同网段把它找回来。 详见下表里 device_id 的说明。

字段类型默认说明
cold_poll_msinteger300000

没被任何规则引用的属性多久问一次。

从官方 spec 生成型号表后, 一台插座暴露 25+ 个实体, 其中真被规则用到的通常只有 一两个。全部按 poll_ms 问是白给设备加压, 所以其余的走这条慢节奏。

缺省 5 分钟而不是"完全不问": 一份还没写规则的配置(全新部署就是这样)会因为 后者而所有实体都没有值, rha status 一片空白 —— 比不分层还糟。慢速轮询把负载 降一个数量级, 同时保住"每个实体都有值"。

device_idinteger可省略

米家云端的 did(rha miot-token 会打印), 跟设备绑定、永不变。

配了它就多两件事: ① 握手拿到的 device_id 与之不符时立刻失败而不是继续对着 错设备发包; ② ip 上找不到设备时自动扫同网段把它找回来。 不配则完全保持旧行为(只按 ip 寻址)。

ip*string

上次已知地址。只是提示 —— 配了 device_id 的话, 这里不对会自动重新定位 (见 crate::resolver); 同时它决定扫哪个 /24。

max_timeoutsinteger3

连续超时多少次后放弃会话并返回 Err(交给 supervise 标 unavailable + 退避重启)。

model*string

米家云端的型号串(形如 cuco.plug.v3), rha miot-token 每台设备那行的 model= 就是它, 照抄即可。

它是 spec.d/*.toml 那张型号表的主键, 决定的是全套东西: 这台设备有哪些实体、 每个实体打到哪个 siid/piid、以及说哪种方言(MIoT 的 get_properties 还是老式的 get_prop)。表里没有这个型号, rha check 就会失败并让你跑 rha spec-gen; 而 spec-gen 恰恰是拿 devices.toml 里的这个字符串去官方目录里查的 —— 拼错了 两边一起失败, 不会有"差不多就行"的模糊匹配。

填成一个存在但不是这台设备的型号不会被拦下: 实体照样建出来, 只是问的 siid/piid 落在别的服务上, 设备回的错误码会被静默跳过 —— 症状是实体列表看着正常, 值却一直是 null、命令也没反应。

poll_msinteger15000

hot 层的轮询间隔, 默认 15 秒 —— 只有被规则引用到的实体按它问, 其余的走 cold_poll_ms(见下条)。

hot 集合每轮重新取, 所以改完规则热加载即可生效, 不必重启 adapter。

这台设备还没被任何规则引用时它也不会闲着: 仍按这个节奏发一次探活请求。所以它 同时是"掉线多快被发现"的上限 —— 连续 max_timeouts 轮拿不到响应才判失联。

poll_timeout_msinteger3000

单次请求等待响应的超时(毫秒)。测试用小值加速; 生产默认 3000。

token*string
Secret

敏感值。建议写成 ${ENV} 由环境变量插值, 不要把明文提交进配置文件。该值绝不进日志与 trace。