用户标签 Cluster(UserLabel)
Cluster ID: 0x0041 |
所在 Endpoint: 通常在 Endpoint 0(Root)或功能端点 |
角色: Server(可读写,无命令)
UserLabel 允许用户或 App 为设备打上自定义的键值对标签,用于分类、分组、备注等用途。
这是一个极其简单的 Cluster —— 0 个命令、0 个事件,
只有 1 个可写属性 LabelList,通过直接写属性来管理标签。
Matter 有两个标签 Cluster,区别在于谁能改:
- FixedLabel(0x0040) —— 厂商在出厂时写入的标签,只读,App 无法修改。例如
"room"/"factory-default"、"model"/"v2" - UserLabel(0x0041) —— 用户自定义的标签,可读写,App 可以随时增删改。例如
"zone"/"living-room"、"owner"/"alice"
两者数据结构完全相同(都是 LabelStruct 列表),只是读写权限不同。
读取设备标签时,应该合并两个 Cluster 的结果,FixedLabel 提供厂商默认值,UserLabel 提供用户自定义值。
UserLabel 的标签是 per-fabric(按 Fabric 隔离)的。
每个 Fabric 只能看到和修改自己写入的标签,无法访问其他 Fabric 的标签。
例如,用户通过 Apple Home 写入的 "zone"/"kitchen",在 Google Home 上是看不到的。
属性
UserLabel 只有一个属性,且是必须支持的。
| ID | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
0x00 |
LabelList | list<LabelStruct> | 读写 | 用户自定义的标签列表 |
LabelList(标签列表)
一个 LabelStruct 的列表,每个元素是一对 Label(键)+ Value(值)字符串。
App 通过 Write Attribute 操作来增删改标签 —— 每次写入都是整体替换,
不是追加。如果想新增一个标签,需要先读取现有列表,追加后再整体写回。
UserLabel 没有定义任何命令。所有操作(新增、修改、删除标签)都通过写 LabelList 属性完成。
这是 Matter 中少数「纯属性驱动」的 Cluster 之一。写入时要注意整体替换的语义 —— 漏掉已有标签相当于删除它。
LabelStruct 结构体
LabelStruct 是 UserLabel 和 FixedLabel 共用的数据结构,表示一个键值对标签。
| 字段 ID | 名称 | 类型 | 约束 | 说明 |
|---|---|---|---|---|
0x00 |
Label | string | 最长 16 字符 | 标签的键名,如 "zone"、"owner" |
0x01 |
Value | string | 最长 16 字符 | 标签的值,如 "living-room"、"alice" |
Label 和 Value 都有 最长 16 字符的硬限制。
App 端在写入前应做校验,超出长度的写入会被设备拒绝(返回 CONSTRAINT_ERROR)。
建议使用短小精悍的英文缩写作为键名,值可以适当使用中文但要注意字符长度(中文字符按 UTF-8 编码计算可能占 3 字节,但 Matter 按字符数计算,16 个中文字符是允许的)。
示例数据
读取一台智能灯的 UserLabel Cluster 属性:
{
// --- 属性 ---
"0x0": [ // LabelList(标签列表)
{
"0": "zone", // Label = "zone"
"1": "living-room" // Value = "living-room"
},
{
"0": "owner", // Label = "owner"
"1": "alice" // Value = "alice"
},
{
"0": "floor", // Label = "floor"
"1": "2F" // Value = "2F"
}
]
}
写入标签(Write Attribute 请求):
{
"writeRequests": [{
"attributePath": {
"endpointId": 1,
"clusterId": "0x0041",
"attributeId": "0x00" // LabelList
},
"data": [
{ "0": "zone", "1": "living-room" },
{ "0": "owner", "1": "alice" },
{ "0": "floor", "1": "2F" }
]
}]
}
写属性的流程是读 → 改 → 写三步:
- 先 Read Attribute 获取当前
LabelList - 在本地修改列表(增 / 删 / 改某个标签)
- 将完整列表通过 Write Attribute 写回设备
直接写入新列表而不先读取,会丢失其他 App 之前写入的标签。 如果多个 App 可能同时操作标签,建议加上乐观锁逻辑(读取时记录版本,写入前再次确认)。
常见场景
场景 1:按区域分组管理设备
用户家中有多台同类设备(例如 5 个智能灯泡),需要按房间、楼层等维度组织管理。 通过 UserLabel 为每台设备打上位置标签,App 就可以按标签分组展示。
- 配网完成后,引导用户为设备设置区域标签
- 写入标签:
{'{"zone": "living-room", "floor": "1F"}'} - App 首页按
zone值分组显示设备 - 用户搬动设备后,可在 App 中修改
zone值 - 支持自定义区域名,不限于预置列表
与 Matter 的 Groups Cluster 不同,UserLabel 是纯元数据标记,不影响设备的群组控制行为。 适合做 App 层面的 UI 分组,而非设备层面的联动控制。
场景 2:多用户家庭的设备归属标记
一个家庭中有多个成员,某些设备归属于特定成员(如儿童房的灯、书房的台灯)。 通过 UserLabel 记录归属信息,App 可以为不同成员展示不同的设备视图。
- 为设备写入归属标签:
{'{"owner": "alice", "usage": "reading"}'} - App 根据当前登录用户的名字过滤
owner标签 - 「我的设备」页面只展示 owner 匹配的设备
- 管理员视图仍可看到全部设备
注意:UserLabel 是 per-fabric 的,如果家庭成员使用不同的 Fabric(不同品牌的 App), 各自的标签互相不可见。同一 Fabric 下的所有 App 共享同一套标签。