跳转到内容

HomeKit

HomeKit 桥(HAP over IP)已经默认编进二进制,但编进去不等于跑起来:feature 只 决定 "homekit" 是不是一个认得的 bridge 类型;要不要真的监听端口、要不要往局域网广播, 全看 bridges.toml 里有没有一条 enabled 的 [[bridge]]。

[[bridge]]
name = "home"
type = "homekit"
pin = "031-45-154"
port = 51826
export = [
"plug_bedroom.switch_s2_on_p1",
"thermo_demo.temperature",
"thermo_demo.humidity",
]

name / export / exclude / enabled 是所有 bridge 共有的字段,说明在 bridges.toml;本页只讲 type = "homekit" 的私有参数。

配对状态(含长期身份私钥)落在 <配置目录>/bridges/<name>/pairing.toml,这个文件的 mode 是 0600(创建时就带上,不留「先 0644 再 chmod」的窗口)。删掉它等于把所有已配对的 iPhone 踢掉,需要全部重新配对。

export 必须显式写,而且别写 设备名.*

Section titled “export 必须显式写,而且别写 设备名.*”

这是本页最容易踩坏的地方,两件事要一起讲。

第一,没有「默认全导」。 一台 cuco.plug.v3 插座有 28 个实体,全导会把上电默认 状态、充电保护功率、超用电量告警阈值一股脑推到 HomeKit 里。

第二,通配写法多半过不了 rha check。 一台设备上大多数实体推不出语义(风扇有 7 个: 指示灯、蜂鸣、定时三条、自然风、摆头角度),而选中没有语义类的实体是硬错误。就算把 它们 exclude 掉,还剩一个 fan_s2_fan_level_p2(1-4 档)——它和 p6(1-100 无级)都是 档位,而 HomeKit 只有一根转速滑条,落选的那个照样报错。

逐条列出来是唯一稳妥的写法,也更说明意图:

export = [
"fan_circulator.fan_s2_on_p1",
"fan_circulator.fan_s2_fan_level_p6",
"fan_circulator.fan_s2_horizontal_swing_p4",
"fan_circulator.physical_controls_locked_s7_physical_controls_locked_p1",
]

差在哪 rha check 都会当场列清楚,不会留到真机上。另外 power(瞬时功率)与 weight (体重)在 HAP 里没有标准 Service,导出它们会在 check 时被点名——这不是 bug,是明说 「这两个出不去」,好过运行时静默少几个开关。

同一台设备的多个实体会组合成一个配件,而不是散成一堆开关:风扇的开关、档位、摆头、 童锁合起来是「家庭」里的一个风扇,带转速滑条和摆头开关。这不需要额外配置,把那几个实体 列进 export 就行。

组合靠的是每个实体的语义类(class),见 devices.toml 的语义类。miot 设备的 class 由官方 spec 自动 推导,不用手标。

自动推导覆盖不到时才需要:设备是 legacy 方言(官方 spec 里根本没有这个型号,推不出任何 语义)、厂商私有属性、或者你不同意推导结果。

[[bridge.accessory]]
device = "fan_circulator"
[[bridge.accessory.service]]
type = "fanv2"
active = "fan_s2_on_p1"
rotation_speed = "fan_s2_fan_level_p6"
swing_mode = "fan_s2_horizontal_swing_p4"
lock_physical_controls = "physical_controls_locked_s7_physical_controls_locked_p1"

槽值写能力名(实体 id 点号之后那半)。也可以写成表来显式给档位——spec 没有取值域、 或取值域是字符串时用:

rotation_speed = { entity = "fan_level", steps = ["small_fan", "medium_fan", "large_fan"] }

下面 accessory 那行说明列了两条规则,这里补它没讲的道理:

  • 「完全接管」是为了让配置可读——写了块就以块为准,你在配置里看到什么就是什么,不会 有隐形多出来的服务。
  • 「必须同时列进 export」被做成硬错误,正因为不拦就没有任何输出:不在 export 里的 那一槽会在组装时被静静丢掉,它压根没进候选集,连 check 的「表达不了」清单里都不会出现。 device 写错是同一类:它不会悄悄退回自动推导,那样你看到的是「我明明配了绑定,怎么还是 老样子」。两种都是静默的缺口,所以必须报出来。

Service / Characteristic 的目录(UUID、格式、权限、必需项)不可配:UUID 打错一个 字符,控制端只会静默忽略那条特征;漏一个必需特征,iOS 判废整台配件。这类错误的共同点 是不报错、只是不工作,而且看起来像网络故障。可配置的是绑定,不是目录。

同样的道理,accessory_information 与 protocol_information 是内部服务,写进 [[bridge.accessory.service]] 会被当场拒掉:前者每个配件已经自动带一份且固定占 iid 1..=7,手写会造成同一配件上有两份;后者只挂在桥自身(aid=1)上,不属于任何 用户配件。它们不出现在下面的表里。

字段类型默认说明
accessoryarray可省略

手动绑定。自动推导覆盖不到时才需要(legacy 方言、厂商私有属性、或你不同意 推导结果)。写了这个块就完全接管这台设备, 块里没提到的实体不会再自动 冒出来; 块里绑的实体必须同时列进 export。

pin*string—

HomeKit 配对码, XXX-XX-XXX 的 8 位数字, 例 "031-45-154"。 不能用 Apple 的弱口令黑名单值(如 111-11-111), iOS 会拒绝配对。

portinteger
≥ 1,≤ 65535
51826

HAP 监听端口。

字段类型默认说明
device*string—

设备名, 必须与 devices.toml 里的 name 一致。写错会报错, 不会悄悄退回自动推导。

service*array—

这台设备上的服务, 一条一个 [[bridge.accessory.service]]。每条必须有 type, 其余键是该服务的特征槽。

每条 service 必须有 type,其余键是该服务的特征槽。槽值统一写能力名,或写成 表显式给档位(见上文)——「值」那一列说的是这个槽期望的取值范围,不是 TOML 类型。

必填槽一个都不能少:漏一个 iOS 会判整台配件非法,现象是配对成功之后全部 No Response。

rha check 在加载期拦掉这些,都是不拦就会静默出错的:

写错了什么 不拦的话真机上是什么样
服务名 / 槽名不认得、必需槽缺失 配对成功之后全部 No Response
实体的值类型换算不出该槽要的类型 控件永远显示占位值,不报错也不打日志
可写的槽绑了只读实体 「家庭」显示成可操作控件,点了必然失败
档位槽的实体既没有取值域、也没写 steps 把设备原值当百分比——4 档风扇显示 4%
steps 的元素类型和实体对不上 档位按相等匹配,一个档位都索引不到

最后两条专门针对 legacy 方言:官方 spec 里没有的型号推不出取值域,档位顺序只能由 steps 显式给出。空调伴侣 lumi.acpartner.mcn02 的 fan_level 真机报的是 "small_fan" / "medium_fan" / "large_fan",就是这一类。

air_purifier

空气净化器。开关、当前在干什么、手动/自动模式三件必填, 转速与摆头可选。空气质量读数不在这里 —— 那是独立的 air_quality_sensor, 挂进同一台配件即可。

槽值必填说明
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
current_air_purifier_state*0 / 1 / 2必填净化器当前在干什么。0 = 未运转, 1 = 待机, 2 = 净化中。只读。0 表示整机没开, 而设备侧的电源与模式通常是两个实体, 一个槽只绑一个源 —— 关机时这里会不准。
target_air_purifier_state*0 / 1必填净化器工作模式。0 = 手动, 1 = 自动。
lock_physical_controls0 / 1可省略童锁, 锁住设备机身上的物理按键。0 = 未锁, 1 = 已锁。
name文本可省略这个服务在「家庭」里显示的名字。
rotation_speed0 ~ 100%, 步长 1可省略转速, 「家庭」里的那根滑条。设备侧的 1-4 档或 1-100 无级都会归一到 0-100(取值域读不出来时用 steps 显式给); 滑到 0 等于关机 —— 会改成给 active 下发关。
swing_mode0 / 1可省略摆头。0 = 不摆, 1 = 摆。

air_quality_sensor

空气质量传感器。只有总评 air_quality 必填, 各种浓度(PM2.5 / PM10 / CO₂ / VOC…)都是可选的补充, 「家庭」优先显示总评。

槽值必填说明
air_quality*0 / 1 / 2 / 3 / 4 / 5必填空气质量总评。0 = 未知, 1 = 优, 2 = 良, 3 = 一般, 4 = 差, 5 = 很差。只读。这是 air_quality_sensor 唯一的必填槽 —— 各种浓度都只是可选的补充。
carbon_dioxide_level0 ~ 100000, 步长 1可省略二氧化碳浓度, ppm。只读。
carbon_monoxide_level0 ~ 100, 步长 1可省略一氧化碳浓度, ppm。只读。
name文本可省略这个服务在「家庭」里显示的名字。
nitrogen_dioxide_density0 ~ 1000, 步长 1可省略二氧化氮浓度, μg/m³。只读。
ozone_density0 ~ 1000, 步长 1可省略臭氧浓度, μg/m³。只读。
pm10_density0 ~ 1000, 步长 1可省略PM10 浓度, μg/m³。只读。
pm2_5_density0 ~ 1000, 步长 1可省略PM2.5 浓度, μg/m³。只读。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。
sulphur_dioxide_density0 ~ 1000, 步长 1可省略二氧化硫浓度, μg/m³。只读。
voc_density0 ~ 1000, 步长 1可省略挥发性有机物浓度, μg/m³。只读。

battery

电池。挂进同一台配件, 「家庭」在配件详情里显示电量与低电告警。

槽值必填说明
battery_level*0 ~ 100%, 步长 1必填剩余电量百分比。只读。
charging_state*0 / 1 / 2必填充电状态。0 = 未充电, 1 = 充电中, 2 = 不可充电。只读。
status_low_battery*0 / 1必填低电告警。0 = 正常, 1 = 电量低。只读。
name文本可省略这个服务在「家庭」里显示的名字。

carbon_dioxide_sensor

二氧化碳传感器。必填的是超标与否这个判断, 具体浓度可选。

槽值必填说明
carbon_dioxide_detected*0 / 1必填二氧化碳是否超标。0 = 正常, 1 = 超标。只读。置 1 时「家庭」推告警通知。
carbon_dioxide_level0 ~ 100000, 步长 1可省略二氧化碳浓度, ppm。只读。
carbon_dioxide_peak_level0 ~ 100000, 步长 1可省略二氧化碳浓度的历史峰值, ppm。只读。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

carbon_monoxide_sensor

一氧化碳传感器。必填的是超标与否这个判断, 具体浓度可选。

槽值必填说明
carbon_monoxide_detected*0 / 1必填一氧化碳是否超标。0 = 正常, 1 = 超标。只读。置 1 时「家庭」推告警通知。
carbon_monoxide_level0 ~ 100, 步长 1可省略一氧化碳浓度, ppm。只读。
carbon_monoxide_peak_level0 ~ 100, 步长 1可省略一氧化碳浓度的历史峰值, ppm。只读。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

contact_sensor

触点传感器, 门磁窗磁用这个。注意取值方向: 0 = 闭合 = 门关着。

槽值必填说明
contact_sensor_state*0 / 1必填触点状态。0 = 闭合, 1 = 断开。只读。门磁的 0 是「门关着」, 与直觉相反; 绑反了「家庭」会一直显示门开着。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

door

电动门。位置按百分比表达, 槽与 window / window_covering 完全相同, 区别只在「家庭」里的图标与措辞。

槽值必填说明
current_position*0 ~ 100%, 步长 1必填当前开合位置百分比。0 = 全关, 100 = 全开。只读。门/窗/窗帘共用。
position_state*0 / 1 / 2必填开合正往哪个方向走。0 = 关闭中, 1 = 打开中, 2 = 已停。只读。门/窗/窗帘的必填槽 —— 设备不报方向的话写死 { value = 2 } 即可。
target_position*0 ~ 100%, 步长 1必填希望开合到百分之几。0 = 全关, 100 = 全开。「家庭」里窗帘那根滑条写的就是它。
hold_positiontrue / false可省略只写。写 true 让门/窗/窗帘立刻停在当前位置。它是一次动作, 没有读值。
name文本可省略这个服务在「家庭」里显示的名字。
obstruction_detectedtrue / false可省略是否被异物挡住。只读。置 true 时「家庭」会提示, 车库门与窗帘用得上。

doorbell

门铃。与 stateless_programmable_switch 的特征相同, 但「家庭」认得它是门铃 —— 门铃图标, 按下时推门铃通知。没有默认绑定, 要手动绑。

槽值必填说明
programmable_switch_event*0 / 1 / 2必填按键事件。0 = 单击, 1 = 双击, 2 = 长按。只推事件、读不到值, 用来触发自动化。
name文本可省略这个服务在「家庭」里显示的名字。

fan

风扇(旧版)。新配置优先用 fanv2 —— 那个有独立的电源特征, 还支持童锁。这个留给只有开关和转速的简单设备。

槽值必填说明
on*true / false必填开关状态。「家庭」里那个开关按钮, 可读可写。
name文本可省略这个服务在「家庭」里显示的名字。
rotation_direction0 / 1可省略旋转方向。0 = 顺时针, 1 = 逆时针。
rotation_speed0 ~ 100%, 步长 1可省略转速, 「家庭」里的那根滑条。设备侧的 1-4 档或 1-100 无级都会归一到 0-100(取值域读不出来时用 steps 显式给); 滑到 0 等于关机 —— 会改成给 active 下发关。

fanv2

风扇。Apple 的现行风扇服务(不是老的 Fan), 装得下转速、摆头与童锁。

槽值必填说明
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
lock_physical_controls0 / 1可省略童锁, 锁住设备机身上的物理按键。0 = 未锁, 1 = 已锁。
name文本可省略这个服务在「家庭」里显示的名字。
rotation_speed0 ~ 100%, 步长 1可省略转速, 「家庭」里的那根滑条。设备侧的 1-4 档或 1-100 无级都会归一到 0-100(取值域读不出来时用 steps 显式给); 滑到 0 等于关机 —— 会改成给 active 下发关。
swing_mode0 / 1可省略摆头。0 = 不摆, 1 = 摆。

faucet

水龙头。它自己只有一个开关, 出水控制要另外挂一个 valve 到同一台配件上。

槽值必填说明
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
name文本可省略这个服务在「家庭」里显示的名字。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。

filter_maintenance

滤芯保养。挂进净化器或空调那台配件, 「家庭」会在配件详情里提示该换滤芯了。

槽值必填说明
filter_change_indication*0 / 1必填滤芯是否该换了。0 = 正常, 1 = 需更换。只读。
filter_life_level0 ~ 100, 步长 1可省略滤芯剩余寿命百分比。只读。
name文本可省略这个服务在「家庭」里显示的名字。
reset_filter_indication1 ~ 1, 步长 1可省略只写, 且只能写 1。告诉设备滤芯已换, 让它把 filter_change_indication 清回正常。

garage_door_opener

车库门。与 door 的区别: 只有开/关两个目标状态而没有百分比, 并且障碍物检测是必填的。

槽值必填说明
current_door_state*0 / 1 / 2 / 3 / 4必填车库门当前状态。0 = 已开, 1 = 已关, 2 = 开启中, 3 = 关闭中, 4 = 停住。只读。
target_door_state*0 / 1必填希望车库门处于什么状态。0 = 开, 1 = 关。
obstruction_detected*true / false必填是否被异物挡住。只读。置 true 时「家庭」会提示, 车库门与窗帘用得上。
lock_current_state0 / 1 / 2 / 3可省略锁实际处于什么状态。0 = 未上锁, 1 = 已上锁, 2 = 卡住, 3 = 未知。只读。取值比 lock_target_state 多两个 —— 卡住和未知是结果, 不是能设的目标。
lock_target_state0 / 1可省略希望锁处于什么状态。0 = 开锁, 1 = 上锁。「家庭」里那个锁按钮写的就是它, 执行结果由 lock_current_state 回报。
name文本可省略这个服务在「家庭」里显示的名字。

heater_cooler

冷暖设备(空调、暖风机)。四件必填: 开关、当前在干什么、目标模式、当前温度。目标温度不在必填里 —— HAP 用 cooling_threshold_temperature / heating_threshold_temperature 两个阈值表达, 哪个生效由目标模式决定。当前温度可以跨设备取自一个独立的温度计。

槽值必填说明
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
current_heater_cooler_state*0 / 1 / 2 / 3必填冷暖设备当前在干什么。0 = 未运转, 1 = 待机, 2 = 制热中, 3 = 制冷中。只读。0 表示整机没开, 而设备侧的电源与模式通常是两个实体, 一个槽只绑一个源 —— 关机时这里会停在上一次的模式。
target_heater_cooler_state*0 / 1 / 2必填希望冷暖设备工作在什么模式。0 = 自动, 1 = 制热, 2 = 制冷。这里没有「关」 —— 开关是独立的 active 特征。
current_temperature*-270 ~ 100℃, 步长 0.1必填当前温度, 摄氏度。只读。
cooling_threshold_temperature10 ~ 35℃, 步长 0.1可省略制冷启动阈值, 摄氏度。高于它开始制冷。heater_cooler 用它当制冷模式下的目标温度; Auto 模式下与 heating_threshold_temperature 一起划出舒适区间。
heating_threshold_temperature0 ~ 25℃, 步长 0.1可省略制热启动阈值, 摄氏度。低于它开始制热。heater_cooler 用它当制热模式下的目标温度; Auto 模式下与 cooling_threshold_temperature 一起划出舒适区间。
lock_physical_controls0 / 1可省略童锁, 锁住设备机身上的物理按键。0 = 未锁, 1 = 已锁。
name文本可省略这个服务在「家庭」里显示的名字。
rotation_speed0 ~ 100%, 步长 1可省略转速, 「家庭」里的那根滑条。设备侧的 1-4 档或 1-100 无级都会归一到 0-100(取值域读不出来时用 steps 显式给); 滑到 0 等于关机 —— 会改成给 active 下发关。
swing_mode0 / 1可省略摆头。0 = 不摆, 1 = 摆。
temperature_display_units0 / 1可省略设备面板上用什么温标显示。0 = 摄氏, 1 = 华氏。只影响设备自己的显示, HAP 上传的温度永远是摄氏度。设备没有这个概念就写死: { value = 0 }。

humidifier_dehumidifier

加湿/除湿机。当前湿度是必填的 —— 设备自己不报湿度的话, 得跨设备绑一个湿度计, 否则这个服务用不了。

槽值必填说明
current_relative_humidity*0 ~ 100%, 步长 1必填当前相对湿度, 百分比。只读。
current_humidifier_dehumidifier_state*0 / 1 / 2 / 3必填加湿/除湿机当前在干什么。0 = 未运转, 1 = 待机, 2 = 加湿中, 3 = 除湿中。只读。
target_humidifier_dehumidifier_state*0 / 1 / 2必填希望设备工作在什么模式。0 = 加湿或除湿(自动), 1 = 只加湿, 2 = 只除湿。
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
lock_physical_controls0 / 1可省略童锁, 锁住设备机身上的物理按键。0 = 未锁, 1 = 已锁。
name文本可省略这个服务在「家庭」里显示的名字。
relative_humidity_dehumidifier_threshold0 ~ 100%, 步长 1可省略除湿目标湿度, 百分比。高于它开始除湿。
relative_humidity_humidifier_threshold0 ~ 100%, 步长 1可省略加湿目标湿度, 百分比。低于它开始加湿。
rotation_speed0 ~ 100%, 步长 1可省略转速, 「家庭」里的那根滑条。设备侧的 1-4 档或 1-100 无级都会归一到 0-100(取值域读不出来时用 steps 显式给); 滑到 0 等于关机 —— 会改成给 active 下发关。
swing_mode0 / 1可省略摆头。0 = 不摆, 1 = 摆。
water_level0 ~ 100%, 步长 1可省略水箱水位百分比。只读。

humidity_sensor

湿度传感器。

槽值必填说明
current_relative_humidity*0 ~ 100%, 步长 1必填当前相对湿度, 百分比。只读。
name文本可省略这个服务在「家庭」里显示的名字。

input_source

电视信号源。不能单独存在: 要与 television 挂在同一台配件上, 由后者的 active_identifier 指向它的 identifier。

槽值必填说明
configured_name*文本必填用户给这个服务起的名字。与 name 的区别是它可写 —— 在「家庭」里改名会写回配件。
input_source_type*0 / 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 / 10必填这一路信号源的接口类型。0 = 其他, 1 = 主界面, 2 = 调谐器, 3 = HDMI, 4 = 复合视频, 5 = S-Video, 6 = 色差分量, 7 = DVI, 8 = AirPlay, 9 = USB, 10 = 应用。只读。
is_configured*0 / 1必填这一路是否已配置好。0 = 未配置, 1 = 已配置。未配置的阀门/信号源在「家庭」里会被折叠起来。
current_visibility_state*0 / 1 / 2 / 3必填这一路信号源在电视的输入列表里是否可见。0 = 显示, 1 = 隐藏。只读 —— 改可见性走 target_visibility_state。
identifier整数可省略这一路信号源在本台电视里的编号, active_identifier 指向它。只读, 且不推送变更。
input_device_type0 / 1 / 2 / 3 / 4 / 5可省略这一路信号源背后是什么设备。0 = 其他, 1 = 电视, 2 = 录像, 3 = 调谐器, 4 = 播放器, 5 = 音响。只读。
name文本可省略这个服务在「家庭」里显示的名字。
target_visibility_state0 / 1可省略希望这一路信号源在列表里显示还是隐藏。0 = 显示, 1 = 隐藏。

irrigation_system

灌溉系统。通常与若干 valve 组合 —— 这个服务管总开关与排程, 每一路出水各挂一个阀门。

槽值必填说明
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
program_mode*0 / 1 / 2必填灌溉排程状态。0 = 无排程, 1 = 有排程, 2 = 有排程但当前是手动。只读。
in_use*0 / 1必填阀门是否真的有水流过。0 = 未使用, 1 = 使用中。只读。与 active 的分工: active 是「已打开」的意图, 这里是实际出水, 两个都必填, 别绑成同一个实体。
name文本可省略这个服务在「家庭」里显示的名字。
remaining_duration0 ~ 3600, 步长 1可省略本次运行还剩多少秒。只读。阀门与灌溉用。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。

leak_sensor

漏水传感器。触发时「家庭」推告警通知。

槽值必填说明
leak_detected*0 / 1必填是否漏水。0 = 无, 1 = 漏水。只读。置 1 时「家庭」推告警通知。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

light_sensor

光照传感器。读数是 lux, 下限 0.0001 而不是 0。

槽值必填说明
current_ambient_light_level*0.0001 ~ 100000lux, 步长 1必填环境光照度, lux。只读。下限是 0.0001 而不是 0。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

lightbulb

灯。目前只有开关, 不支持亮度与色温。

槽值必填说明
on*true / false必填开关状态。「家庭」里那个开关按钮, 可读可写。
name文本可省略这个服务在「家庭」里显示的名字。

lock_mechanism

门锁。目标状态与当前状态分开: 写目标发指令, 读当前看结果 —— 中间可能卡住(lock_current_state = 2)。

槽值必填说明
lock_current_state*0 / 1 / 2 / 3必填锁实际处于什么状态。0 = 未上锁, 1 = 已上锁, 2 = 卡住, 3 = 未知。只读。取值比 lock_target_state 多两个 —— 卡住和未知是结果, 不是能设的目标。
lock_target_state*0 / 1必填希望锁处于什么状态。0 = 开锁, 1 = 上锁。「家庭」里那个锁按钮写的就是它, 执行结果由 lock_current_state 回报。
name文本可省略这个服务在「家庭」里显示的名字。

microphone

麦克风。音量与静音都必填。

槽值必填说明
volume*0 ~ 100%, 步长 1必填音量百分比。
mute*true / false必填静音。
name文本可省略这个服务在「家庭」里显示的名字。

motion_sensor

移动传感器。表达的是瞬时事件; 要表达「屋里有人」用 occupancy_sensor。

槽值必填说明
motion_detected*true / false必填是否检测到移动。只读。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

occupancy_sensor

人体存在传感器。表达的是持续状态; 要表达「刚有东西动了一下」用 motion_sensor。

槽值必填说明
occupancy_detected*0 / 1必填区域内是否有人。0 = 无人, 1 = 有人。只读。与 motion_detected 的分工: 移动是瞬时的, 有人是持续的。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

outlet

插座。比 switch 多一个「使用中」指示。

槽值必填说明
on*true / false必填开关状态。「家庭」里那个开关按钮, 可读可写。
outlet_in_use*true / false必填插座上是否有负载在用电。只读, 「家庭」显示成「使用中」。
name文本可省略这个服务在「家庭」里显示的名字。

security_system

安防系统。当前状态比目标状态多一个「已触发报警」 —— 报警是发生的事, 设不了。

槽值必填说明
security_system_current_state*0 / 1 / 2 / 3 / 4必填安防系统实际处于什么状态。0 = 在家布防, 1 = 离家布防, 2 = 夜间布防, 3 = 撤防, 4 = 已触发报警。只读。比目标状态多一个 4 —— 报警是发生的事, 设不了。
security_system_target_state*0 / 1 / 2 / 3必填希望安防系统处于什么状态。0 = 在家布防, 1 = 离家布防, 2 = 夜间布防, 3 = 撤防。
name文本可省略这个服务在「家庭」里显示的名字。
security_system_alarm_type0 ~ 1, 步长 1可省略报警类型。0 = 无已知报警, 1 = 有报警但类型未知。只读。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

service_label

服务标签。给多按键设备用: 挂一个它, 再给每个按键服务标上 service_label_index, 「家庭」才知道哪个是 1 号键。

槽值必填说明
service_label_namespace*0 / 1必填按键怎么编号。0 = 圆点, 1 = 阿拉伯数字。只读, 且不推送变更。
name文本可省略这个服务在「家庭」里显示的名字。

slat

导风叶片。挂进空调或净化器那台配件, 表达叶片的朝向与摆动。

槽值必填说明
slat_type*0 / 1必填叶片朝向。0 = 水平, 1 = 垂直。只读, 且不推送变更 —— 它是设备的固有属性, 通常写死。
current_slat_state*0 / 1 / 2必填叶片当前状态。0 = 固定, 1 = 卡住, 2 = 摆动中。只读。
current_tilt_angle-90 ~ 90arcdegrees, 步长 1可省略叶片当前倾角, 度。-90 ~ 90。只读。slat 服务用它; 窗帘用带方向后缀的那两个。
name文本可省略这个服务在「家庭」里显示的名字。
swing_mode0 / 1可省略摆头。0 = 不摆, 1 = 摆。
target_tilt_angle-90 ~ 90arcdegrees, 步长 1可省略希望叶片倾到多少度。-90 ~ 90。

smoke_sensor

烟雾传感器。触发时「家庭」推告警通知。

槽值必填说明
smoke_detected*0 / 1必填是否检测到烟雾。0 = 无, 1 = 有烟。只读。置 1 时「家庭」推告警通知。
name文本可省略这个服务在「家庭」里显示的名字。
status_activetrue / false可省略设备是否在正常工作。只读。置 false 时「家庭」把这个传感器标成不响应。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。
status_low_battery0 / 1可省略低电告警。0 = 正常, 1 = 电量低。只读。
status_tampered0 / 1可省略是否被拆动或破坏。0 = 正常, 1 = 被拆动。只读。

speaker

扬声器。只有静音必填, 音量可选 —— 有些设备只能静音, 调不了音量。

槽值必填说明
mute*true / false必填静音。
name文本可省略这个服务在「家庭」里显示的名字。
volume0 ~ 100%, 步长 1可省略音量百分比。

stateless_programmable_switch

无状态按键。没有开/关状态, 按一下推一个事件, 用来触发自动化。

槽值必填说明
programmable_switch_event*0 / 1 / 2必填按键事件。0 = 单击, 1 = 双击, 2 = 长按。只推事件、读不到值, 用来触发自动化。
name文本可省略这个服务在「家庭」里显示的名字。

switch

开关。「家庭」里显示成一个通用开关。

槽值必填说明
on*true / false必填开关状态。「家庭」里那个开关按钮, 可读可写。
name文本可省略这个服务在「家庭」里显示的名字。

television

电视。四件必填, 其中 configured_name 与 sleep_discovery_mode 通常写死。信号源列表要另外挂若干 input_source。

槽值必填说明
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
active_identifier*整数必填电视当前选中的信号源, 值等于某个 input_source 服务的 identifier。
configured_name*文本必填用户给这个服务起的名字。与 name 的区别是它可写 —— 在「家庭」里改名会写回配件。
sleep_discovery_mode*0 / 1必填电视待机时还能不能被发现。0 = 不可发现, 1 = 始终可发现。只读, 通常写死 { value = 1 }。
brightness0 ~ 100%, 步长 1可省略亮度百分比。它与开关是两个特征: 调到 0 不等于关灯, 关灯要写 on。
closed_captions0 / 1可省略字幕。0 = 关, 1 = 开。
current_media_state0 / 1 / 2 / 3可省略播放状态。0 = 播放中, 1 = 暂停, 2 = 停止, 3 = 未知。只读。
picture_mode0 / 1 / 2 / 3 / 4 / 5 / 6 / 7可省略画面模式。0 = 其他, 1 = 标准, 2 = 校准, 3 = 暗场校准, 4 = 鲜艳, 5 = 游戏, 6 = 电脑, 7 = 自定义。
power_mode_selection0 / 1可省略只写。让电视显示或隐藏它自己的设置菜单。0 = 显示, 1 = 隐藏。
remote_key0 / 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 / 10 / 11 / 15可省略只写。遥控按键。0 = 快退, 1 = 快进, 2 = 下一个, 3 = 上一个, 4/5/6/7 = 上/下/左/右, 8 = 确定, 9 = 返回, 10 = 退出, 11 = 播放暂停, 15 = 信息。
target_media_state0 / 1 / 2可省略希望播放器做什么。0 = 播放, 1 = 暂停, 2 = 停止。

temperature_sensor

温度传感器。

槽值必填说明
current_temperature*-270 ~ 100℃, 步长 0.1必填当前温度, 摄氏度。只读。
name文本可省略这个服务在「家庭」里显示的名字。

thermostat

温控器(地暖、壁挂炉)。与 heater_cooler 的区别: 它用单一的 target_temperature, 关机是把目标模式写 0, 没有独立的电源特征。空调更适合用 heater_cooler。

槽值必填说明
current_heating_cooling_state*0 / 1 / 2必填温控器当前在干什么。0 = 停, 1 = 制热中, 2 = 制冷中。只读。thermostat 用它, heater_cooler 用 current_heater_cooler_state, 两者不通用。
target_heating_cooling_state*0 / 1 / 2 / 3必填希望温控器工作在什么模式。0 = 关, 1 = 制热, 2 = 制冷, 3 = 自动。这里有「关」 —— thermostat 没有 active, 关机就是写 0。
current_temperature*-270 ~ 100℃, 步长 0.1必填当前温度, 摄氏度。只读。
target_temperature*10 ~ 38℃, 步长 0.1必填目标温度, 摄氏度。thermostat 用它, heater_cooler 不用 —— 后者靠两个阈值特征表达目标, 哪个生效由 target_heater_cooler_state 决定。
temperature_display_units*0 / 1必填设备面板上用什么温标显示。0 = 摄氏, 1 = 华氏。只影响设备自己的显示, HAP 上传的温度永远是摄氏度。设备没有这个概念就写死: { value = 0 }。
cooling_threshold_temperature10 ~ 35℃, 步长 0.1可省略制冷启动阈值, 摄氏度。高于它开始制冷。heater_cooler 用它当制冷模式下的目标温度; Auto 模式下与 heating_threshold_temperature 一起划出舒适区间。
current_relative_humidity0 ~ 100%, 步长 1可省略当前相对湿度, 百分比。只读。
heating_threshold_temperature0 ~ 25℃, 步长 0.1可省略制热启动阈值, 摄氏度。低于它开始制热。heater_cooler 用它当制热模式下的目标温度; Auto 模式下与 cooling_threshold_temperature 一起划出舒适区间。
name文本可省略这个服务在「家庭」里显示的名字。
target_relative_humidity0 ~ 100%, 步长 1可省略目标湿度百分比。

valve

阀门。active 是「已打开」的意图, in_use 是实际有水流过, 两个都必填 —— 别绑成同一个实体。

槽值必填说明
active*0 / 1必填风扇电源。0 = 停, 1 = 运转。
in_use*0 / 1必填阀门是否真的有水流过。0 = 未使用, 1 = 使用中。只读。与 active 的分工: active 是「已打开」的意图, 这里是实际出水, 两个都必填, 别绑成同一个实体。
valve_type*0 / 1 / 2 / 3必填阀门用途。0 = 通用阀, 1 = 灌溉, 2 = 花洒, 3 = 水龙头。只读 —— 固有属性, 通常写死。
is_configured0 / 1可省略这一路是否已配置好。0 = 未配置, 1 = 已配置。未配置的阀门/信号源在「家庭」里会被折叠起来。
name文本可省略这个服务在「家庭」里显示的名字。
remaining_duration0 ~ 3600, 步长 1可省略本次运行还剩多少秒。只读。阀门与灌溉用。
service_label_index1 ~ 255, 步长 1可省略这个服务在标签体系里排第几, 从 1 起。多按键设备靠它告诉「家庭」哪个是 1 号键, 要与 service_label 服务配合。只读, 且不推送变更。
set_duration0 ~ 3600, 步长 1可省略设定本次运行多少秒。写下去开始倒计时, 剩余时间读 remaining_duration。
status_fault0 / 1可省略是否有故障。0 = 正常, 1 = 故障。只读。

window

电动推窗。槽与 door / window_covering 完全相同, 区别只在「家庭」里的图标与措辞。

槽值必填说明
current_position*0 ~ 100%, 步长 1必填当前开合位置百分比。0 = 全关, 100 = 全开。只读。门/窗/窗帘共用。
target_position*0 ~ 100%, 步长 1必填希望开合到百分之几。0 = 全关, 100 = 全开。「家庭」里窗帘那根滑条写的就是它。
position_state*0 / 1 / 2必填开合正往哪个方向走。0 = 关闭中, 1 = 打开中, 2 = 已停。只读。门/窗/窗帘的必填槽 —— 设备不报方向的话写死 { value = 2 } 即可。
hold_positiontrue / false可省略只写。写 true 让门/窗/窗帘立刻停在当前位置。它是一次动作, 没有读值。
name文本可省略这个服务在「家庭」里显示的名字。
obstruction_detectedtrue / false可省略是否被异物挡住。只读。置 true 时「家庭」会提示, 车库门与窗帘用得上。

window_covering

窗帘、百叶。比 window 多四个倾角槽 —— 只有百叶用得上, 卷帘留空即可。

槽值必填说明
current_position*0 ~ 100%, 步长 1必填当前开合位置百分比。0 = 全关, 100 = 全开。只读。门/窗/窗帘共用。
target_position*0 ~ 100%, 步长 1必填希望开合到百分之几。0 = 全关, 100 = 全开。「家庭」里窗帘那根滑条写的就是它。
position_state*0 / 1 / 2必填开合正往哪个方向走。0 = 关闭中, 1 = 打开中, 2 = 已停。只读。门/窗/窗帘的必填槽 —— 设备不报方向的话写死 { value = 2 } 即可。
current_horizontal_tilt_angle-90 ~ 90arcdegrees, 步长 1可省略百叶当前的水平倾角, 度。-90 ~ 90, 0 是完全打开。只读。
current_vertical_tilt_angle-90 ~ 90arcdegrees, 步长 1可省略百叶当前的垂直倾角, 度。-90 ~ 90, 0 是完全打开。只读。
hold_positiontrue / false可省略只写。写 true 让门/窗/窗帘立刻停在当前位置。它是一次动作, 没有读值。
name文本可省略这个服务在「家庭」里显示的名字。
obstruction_detectedtrue / false可省略是否被异物挡住。只读。置 true 时「家庭」会提示, 车库门与窗帘用得上。
target_horizontal_tilt_angle-90 ~ 90arcdegrees, 步长 1可省略希望百叶的水平倾角是多少度。-90 ~ 90。
target_vertical_tilt_angle-90 ~ 90arcdegrees, 步长 1可省略希望百叶的垂直倾角是多少度。-90 ~ 90。