Matter
Matter 驱动参考:设备加入的 Wi-Fi 和 Thread 网络、通过蓝牙把设备调试进本地 Fabric、配对设备的流程、节点身份,以及来自设备的点位和写入每个点位会做什么。
Matter 驱动读的是 Matter 仪器:通过 Matter 标准认证的智能传感器、插座、灯具之类的设备,不管它们是通过 Wi-Fi 还是通过 Thread 加入网络。两种都由同一个驱动负责。网络只是进门的路:设备一旦进了网络,Ganter Lab 就用同样的方式、通过局域网去读它。
Ganter Lab 扮演的是一个带着自己本地 Fabric 的 Matter 控制器:它在本机上通过蓝牙低功耗把每一台设备调试入网一次,把登记在驱动网络卡片上的某个网络的凭据交给它,从那以后就通过局域网和它对话:Wi-Fi 设备经过你的路由器,Thread 设备经过你的 Thread 边界路由器。
你从来不用告诉 Ganter Lab 一台设备是 Wi-Fi 还是 Thread:设备自己会说。蓝牙会话一打开,Ganter Lab 在往设备上写任何东西之前,先从设备读出它加入哪一种网络;如果选中的网络是另一种,它就停下来,并给出一条专门说明这件事的消息。
这把通常的配置顺序颠倒了过来。Matter 设备不是从一个主机和端口开始的:它是从一次配对仪式开始的,事后存下来的只有那个已调试节点稳定的身份。
配对之前你需要:
- 本机上一块蓝牙低功耗适配器,处于打开状态,并且 Windows 允许 Ganter Lab 使用它。
- 设备要加入的网络,已经登记在网络卡片上:Wi-Fi 设备需要 Wi-Fi 名称和它的密码;Thread 设备需要一个已有的、带边界路由器的 Thread 网络,以及它完整的活动运行数据集。Ganter Lab 把设备加入你的网络;它编不出这个网络的凭据。
- 设备的配网码,印在设备上或者它的包装上,并且设备处于配对模式。
网络
Matter 驱动的面板上有一张标题为网络的卡片:设备要加入的 Wi-Fi 和 Thread 网络,一行一个。一个网络在第一台设备之前登记一次,之后配对进这个网络的每一台设备都用它,所以在同一个 Wi-Fi 上配对第二盏灯时,什么都不用再填。这张卡片只对可以配置 Connector 的角色绘制,因为它保存着网络的秘密,而且除了配对别无用处。
卡片的头部按这个顺序放着它的命令:
| 命令 | 做什么 | 不做什么 |
|---|---|---|
| 添加 Wi-Fi 网络 | 添加一个 Wi-Fi 网络并选中它。本机连着的 Wi-Fi 的名称还没登记过时,新网络就用这个名称;否则它先不带名称,由你来填写。Windows 只交出名称,而且只在它允许应用知道本机位置的时候才交出(Windows 11 会就此请求权限);密码永远由你自己输入。 | 它不从 Windows 读取密码,也不检查这个网络是否存在。 |
| 添加 Thread 网络 | 添加一个 Thread 网络并选中它;在你给它起名之前,它用一个临时名称(已被占用时加上编号),并等着你填上数据集。 | 它不和边界路由器对话:Ganter Lab 只使用边界路由器所建网络的数据集。 |
| 移除网络 | 移除选中的网络,之前会弹出一次确认,点出这个网络的名字,并说明已经配对的设备不受影响。没有选中任何网络时,它仍然画着、呈灰色,它的提示会说明原因。 | 它不碰已经配对进这个网络的设备:这些设备照常工作,并在自己的网络字段里保留这个名称。 |
表格列出每个网络的名称、网络类型(Wi-Fi 网络或Thread 网络)和状态:可以配对,或者这个网络还缺什么。还没写名称的网络显示为未命名的网络。
选中网络的字段就在表格下方原地编辑,并且自动保存。下面的规则拒绝的值不会写入,字段会说明原因。
| 类型 | 字段 | 它是什么 | 格式 |
|---|---|---|---|
| Wi-Fi | Wi-Fi 名称 | 交给设备的名称(SSID),必须和路由器广播的一模一样:区分大小写。每个 Wi-Fi 名称只登记一次。 | 1 到 32 字节的文本(UTF-8)。 |
| Wi-Fi | 密码 | 交给设备的 Wi-Fi 密码。 | 开放网络留空;否则是 8 到 63 个可打印的 ASCII 字符(WPA 口令),或者正好 64 位十六进制数(原始密钥)。 |
| Thread | 名称 | 你给这个网络起的名字,用来在配对时和每台设备上认出它。每个 Thread 网络名称只登记一次。 | 自由文本。 |
| Thread | Thread 操作数据集 | 你那个 Thread 网络完整的活动数据集,来自网络管理员或者它的边界路由器。Home Assistant 会显示它;Alexa 和 Apple 不会。 | 十六进制文本(空白字符和一个 hex: 前缀都能容忍),解码之后最多 254 字节。它必须是完整的数据集:Active Timestamp、Channel、Channel Mask、Extended PAN ID、Mesh-Local Prefix、Network Key、Network Name、PAN ID、PSKc 和 Security Policy 必须一个不缺,残缺或畸形的数据集会被拒绝,并点名缺的是哪一项。 |
一台 Wi-Fi 设备到底能不能配对,取决于两件事,卡片在字段旁边把两件都写着:
- 大多数设备只加入 2.4 GHz 网络。在 2.4 GHz 和 5 GHz 上广播同一个名称的路由器可以用;只存在于 5 GHz 的网络不行。
- 本机和这些设备必须在同一个局域网里。访客网络,或者路由器上打开的客户端隔离,会让本机在设备入网之后找不到它们。
一个网络只有在它的秘密符合这些规则时才能用于配对:Wi-Fi 网络要有合法的名称和合法的密码(空也算),Thread 网络要有合法的数据集。
编辑一个网络,改变的是下一次配对交出去的东西,从不改变设备已经收到的东西。需要换到另一个网络的设备,或者路由器换了新密码的设备,要复位后重新配对。
配对设备的流程
在 Matter 驱动上,其他驱动提供“添加设备”的位置,这里的命令栏提供的是配对设备,这一栏“新建…”菜单里的 Matter 那一项也提供它。还没有任何网络能用于配对时,它仍然画着、呈灰色,提示是“请先添加设备要加入的网络。”有可用的网络时,它会打开一个表单:
| 字段 | 它是什么 | 格式 | 默认值 |
|---|---|---|---|
| 设备名称 | 这台设备将来在 Connector 里带着的名字,可编辑。 | 自由文本 | Matter device |
| Matter 配网码 | 那串官方的手工配对码,或者完整的 QR 载荷。输入时打码,旁边有一个显示控件。 | 一串 11 位或 21 位的手工输入码(短横线和空格会被忽略;校验位会被核对),或者以 MT: 开头的完整 QR 载荷。不声明支持蓝牙调试入网的 QR 载荷会被拒绝,保留的或超出范围的配网码也一样。 |
空 |
| 网络 | 设备要加入的已登记网络。只有一个可用网络时,表单用一行字说明是哪个网络、什么类型,没有什么可选的;有多个时,它是一个选择列表。 | 网络卡片上可用网络中的一个 | 只有一个时就是它 |
| 目标文件夹 | 只在某个文件夹的“新建设备”打开表单时出现:配对的设备要归入的文件夹。用“配对设备”打开时没有这一行,设备落在驱动自己的层级。 | 只读 | 打开表单的文件夹 |
Matter 驱动的文件夹提供新建设备(在它的“设备”表、它的右键菜单,以及新建… > Matter > <Folder> 下面)。它打开同一个表单,没有可用网络时同样置灰,配对的设备归入那个文件夹。
名称和配网码都填好、并且有可用的网络之前,表单里的配对设备一直不可用。配对进行时,表单会报告它走到哪一步:校验(检查配网码和网络的秘密)、查找(通过蓝牙搜索设备)、配对(用配网码做认证,并读出设备加入哪一种网络)、加入网络(把网络发给设备,然后在局域网上反复询问它,直到它应答;状态行会说明这个网络是 Wi-Fi 还是 Thread)、保存(和局域网上的设备建立安全会话,完成它的调试入网,并把节点记进本地 Fabric)。
在物理设备还没被改动之前,取消是可用的;一旦调试入网已经改动了设备,这个按钮就写着 Ganter Lab 正在安全收尾,流程会把这条记录做完,而不是丢下一个调试到一半的节点。一次只跑一次配对;一次配对进行期间的第二次尝试会被拒绝。
新设备会记下它加入的网络的名称,显示在它的网络字段里。在同一个网络上配对下一台设备时,只需要填它的名称和配网码。
配对失败时
配对失败时,消息会说明原因和该怎么做:
| 原因 | 含义 | 仪器 | 怎么做 |
|---|---|---|---|
| 配网码无效 | 这串码既不是官方的 11 位或 21 位手工输入码,也不是完整的 MT: QR 载荷。 |
没被动过 | 把印着的码再看一遍。 |
| Thread 数据集无效 | 选中的 Thread 网络的数据集不完整或格式不对。 | 没被动过 | 在网络卡片上,把完整的活动数据集重新复制进这个网络。 |
| Wi-Fi 名称或密码无效 | 选中的 Wi-Fi 网络的名称或密码违反了网络卡片的规则。 | 没被动过 | 在卡片上改正。 |
| 蓝牙缺失、被关掉或被拒绝 | 本机没有可用的蓝牙低功耗适配器、蓝牙被关掉了,或者 Windows 拒绝了 Ganter Lab 访问它。 | 没被动过 | 打开蓝牙,或者在 Windows 里允许 Ganter Lab 使用它,然后再试一次。 |
| 没有找到匹配的设备 | 没有处于配对模式的设备回应这个配网码。 | 没被动过 | 让设备进入配对模式,放在本机附近,再试一次。 |
| 配网码被驳回 | 设备驳回了这个码。 | 没被动过 | 把印着的码再看一遍,并让设备重新进入配对模式。 |
| 设备通过 Wi-Fi 加入 | 选中的网络是 Thread。 | 没被动过:只读了它,什么都没写进去 | 登记设备要加入的 Wi-Fi 网络,选中它重新配对。 |
| 设备通过 Thread 加入 | 选中的网络是 Wi-Fi。 | 没被动过:只读了它,什么都没写进去 | 登记这个 Thread 网络,选中它重新配对。 |
| 设备是有线的(以太网) | 通过蓝牙配对不适用于有线设备。 | 没被动过:只读了它,什么都没写进去 | Ganter Lab 无法配对这台设备。 |
| 设备不说自己的网络 | 设备既没报 Wi-Fi,也没报 Thread 或以太网。 | 没被动过:只读了它,什么都没写进去 | Ganter Lab 无法配对这台设备。 |
| 找不到 Wi-Fi 网络 | 设备回答说找不到叫这个名字的 Wi-Fi:拼写或大小写写错了、网络只在 5 GHz 上,或者设备超出了信号范围。 | 什么都不保留:它丢掉收到的东西,回到配对模式。没有节点 ID。 | 在网络卡片上改正名称,确认路由器在 2.4 GHz 上广播它,然后重新配对。 |
| Wi-Fi 密码被拒绝 | 设备回答说 Wi-Fi 拒绝了这个密码。 | 什么都不保留:它丢掉收到的东西,回到配对模式。没有节点 ID。 | 在网络卡片上改正密码,然后重新配对。 |
| 设备无法加入网络 | 设备回答说它加入不了网络,原因不是上面两种(Thread 的话,任何拒绝都算,包括找不到网络)。 | 什么都不保留:它丢掉收到的东西,回到配对模式。没有节点 ID。 | 在网络卡片上检查这个网络(Thread 的话,重新复制当前的活动数据集,并确认边界路由器开着),然后重新配对。 |
| 设备没有出现在网络上 | 设备对网络没有给出任何回答,或者之后始终没有出现在局域网上。有些设备要离开蓝牙才能入网,根本没法回答。 | 已调试入网:消息会显示节点 ID | Wi-Fi 的话,确认本机和设备在同一个局域网里,中间没有访客网络或客户端隔离;Thread 的话,确认边界路由器开着并且连得上。然后用设备发现把节点找回来。 |
| 安全会话没有建立 | 设备已加入网络,也在网络上找到了,但与它的安全会话,或通过该会话完成配对的步骤失败了。诊断日志会记下停在哪一步以及设备的回答。 | 已调试入网:消息会显示节点 ID | 用设备发现把节点找回来。如果设备开着,设备发现却找到它而没有任何值,就让设备重新进入配对模式,然后重新配对。 |
| 另一次配对正在进行 | 一次只跑一次配对。 | 没被动过 | 等它结束后再试一次。 |
| 本地 Fabric 无法保存 | Ganter Lab 没能安全地保存 Fabric。 | 发生在配对开始之前时没被动过;发生在之后时已调试入网,并附带节点 ID | 先解决存储问题,再复位任何东西。 |
只要失败发生在仪器已经被调试入网之后,消息就会说出来并显示节点 ID:这个节点留在 Fabric 里,等它上了网,日后可以用“发现设备”把它加进来。这种情况下不要复位设备;只有一条说“什么都没有保存”的消息,才表示仪器完全没被动过。
回答说自己加入不了网络的设备是例外:它身上没有值得留下的东西。Ganter Lab 在设备上结束这次配对,设备丢掉收到的东西并立刻回到配对模式,同时把它的节点从 Fabric 里移除;所以消息里没有节点 ID,“发现设备”也永远不会列出一个无法应答的节点。改正网络,然后重新配对。只有完全没有回答的设备才保留节点,因为它有没有入网,要等它出现在局域网上才知道。
保存了什么
| 什么 | 存在哪里 | 怎么存 |
|---|---|---|
| 网络的名称和类型 | 工作站的配置 | 按写下的样子。 |
| Wi-Fi 密码和 Thread 操作数据集 | 工作站的配置 | 和设备密码一样,为输入它们的那个 Windows 用户加密保护:换一个 Windows 账户,它们读出来是空的,必须重新输入。备份不带上它们;导出到另一台计算机会带上它们,用导出自己的密码封好。 |
| 配网码 | 哪里都不存 | 它只在配对进行时存在于表单里,配对结束、失败或被取消时就被清掉。 |
| 设备加入的网络 | 设备的配置 | 它的名称,显示在设备的网络字段里。 |
| 设备的身份 | 设备的配置和本地 Fabric | 节点 ID。 |
Wi-Fi 密码和数据集从不出现在诊断日志里、设备的地址里,也不出现在它的 Thing Description 里。网络和配对不通过 MCP 服务器提供给智能体:配对需要有人在设备旁边,而网络保存着秘密。
节点身份
配对好的设备绑定在仪器那个稳定的 64 位节点 ID 上,它在设备的“连接”卡片里以 16 位十六进制数只读显示,旁边就是设备状态。可编辑的显示名称归你改;节点 ID 不归。存下来的身份已经读不出来的设备,会在那个位置显示需要重新配对。
设备的面板上还有一个只读的网络字段:设备配对时加入的那个网络的名称。由一个还不记录它的版本配对的设备,会说明没有记录任何东西。这个字段是一条记录,不是一项设置:在网络卡片上编辑或删除那个网络,不会改变设备上的任何东西。
因为身份就是节点 ID,所以各台 Matter 设备的连接状态彼此独立:禁用、删除或者丢掉一个节点,不会让另一个变得不可用;而删掉一台设备,只是放开它对那条安全会话的占用,并不会把仪器从本地 Fabric 里移除。
设备发现
Matter 驱动上的发现设备列出已经调试进本应用本地 Fabric 的那些节点,并从每个节点读取它公开的值。为了读这些值,它要和每个节点打开一个安全会话,所以不在网络上的节点在会话打开失败之后仍然列出来,只是没有值。设备发现的候选项带的是节点身份,不带任何配网秘密。一般的设备发现流程见设备发现。
| 节点 | 它的卡片 | 它的命令 |
|---|---|---|
| 这里没有它的设备:设备被删掉了,或者配对结束时没有留下设备 | 它公开的值,每个都已勾选 | 添加设备创建这台设备,勾选的值成为它的点位,不必再做一次仪式。 |
| 是一台已配置的设备,有些值还没有点位 | 标为已经配置过,写明它公开的值里有几个还不是点位,并列出这些值,默认勾选 | 添加所选点位把勾选的值添加到这台设备上;打开打开这台设备。 |
| 是一台已配置的设备,每个值都有点位 | “已经配置过,设备公开的每个值都已有点位。” | 打开打开这台设备。 |
| 是一台已配置的设备,没有报告任何值 | “已经配置过。设备没有报告任何值:等设备在线后,再运行一次‘发现设备’。” | 打开打开这台设备。 |
已配置设备的值按输出、簇和属性与它的点位比对,从不按名称:你改过名字的点位照样算数,同一个值也绝不会添加两次。
设备自己的页面上也能做到同样的事,不用离开:“点位”卡片标题栏里的发现点位只读这一个节点,列出它还没有点位的值,并且已勾选,旁边是添加所选点位(见发现一台设备的点位)。
点位
Matter 设备的点位来自设备本身:没有人需要为它们输入簇或属性编号。配对顺利结束后会直接走到这一步。记录条写“已配对 Matter 设备‘厨房灯’。”,页面在 Matter 驱动上打开,新设备在它的“设备”表格里突出显示,并立刻只扫描这一台设备。配对创建的设备出现在发现的设备里,它公开的值全部勾选,扫描结束时写“勾选‘厨房灯’中要创建为点位的值,然后点‘添加所选点位’。”取消勾选你不要的值,再点添加所选点位;记录条随后写“已向‘厨房灯’添加 5 个点位。”还没有应答的设备什么也不报告:“‘厨房灯’还没有报告任何值。等设备在线后,再运行一次‘发现设备’。”以后每次发现设备,同一张卡片都会回来,带着设备还没有点位的那些值。
添加所选点位只为拥有“配置 Connector”权限的角色画出来。扫描或配对进行中、工作站拒绝更改时,以及什么都没勾选时(“请至少勾选一个要添加的值。”),它保持灰色,并把原因写在提示里。设备已经在读其输出、簇和属性的值绝不会再添加一次;勾选的值全都已经在了时,什么都不保存:“勾选的每个值在‘厨房灯’上都已有点位,所以没有添加任何内容。”设备上另一个点位已经用了的名称,后面会加上编号,比如亮度 (2)。
扫描按 Matter 规范的组织方式读取设备公开的内容:
| 读什么 | 设备在哪里说明 |
|---|---|
| 它的输出(endpoint) | endpoint 0 上的 Descriptor 簇(0x001D),属性 PartsList |
| 每个输出的簇 | 该输出上的 Descriptor,属性 ServerList |
| 每个簇的值 | 该簇的属性 AttributeList(0xFFFB) |
| 每个簇接受的命令 | 该簇的属性 AcceptedCommandList(0xFFF9) |
| 每个簇实现的可选功能 | 该簇的属性 FeatureMap(0xFFFC) |
| 每个值的当前读数 | 值本身,读一次 |
扫描提供什么,用什么名称:
| 一个值 | 提供方式 |
|---|---|
| 驱动认识的值(下一节) | 用工作站语言的清楚名称和规范给它的类型提供;只有设备接受规范改变它的方式时才可写,否则只读 |
| 驱动认识、但属于簇没有实现的功能的值:没有 Hue and Saturation 功能时的色调和饱和度,没有 Color Temperature 功能时的色温 | 不提供 |
| 驱动不认识的值 | 只读,用它在 Matter 规范里的名称(Level Control OnLevel),驱动也不认识这个属性时用簇和属性编号(On/Off attribute 0x131B0001);类型取设备返回的读数的类型 |
| 在不止一个输出上的同一个值 | 名称写明是哪个输出,比如亮度(输出 2) |
| 全局属性(0xFFF8 到 0xFFFD),或者节点本身(endpoint 0)的值 | 不提供 |
| 列表或结构、驱动不支持的类型的值、设备没有返回读数的值 | 不列出,并在扫描收尾的那一行里计数 |
作为可写提供的点位到达时访问是读写;其余的一律只读。
驱动认识的值
驱动带着一张取自 Matter 规范的表,列出它按名称认识的值,以及每个值怎么改变。一个值有三种改变方式之一:由驱动发送的命令改变,设备必须把这条命令列在它接受的命令里;由写入属性本身改变,前提是规范规定它可写而且设备列出了它;或者根本不改变,那是设备只报告的值。
| 值 | 簇和属性 | 类型 | 写入它会让设备做什么 | 规范规定的范围 |
|---|---|---|---|---|
| 开启 | On/Off(0x0006),OnOff(0x0000) |
Boolean | true 发送命令 On(0x01),false 发送 Off(0x00);只有设备两条都接受时才可写 |
true 或 false |
| 亮度 | Level Control(0x0008),CurrentLevel(0x0000) |
UInt32 | 发送 MoveToLevelWithOnOff(0x04),带上亮度级别、过渡时间 0,不覆盖任何选项:输出以该级别点亮,到最小值时熄灭 |
0 到 254 |
| 色调 | Color Control(0x0300),CurrentHue(0x0000) |
UInt32 | 按最短方向发送 MoveToHue(0x00),过渡时间 0;仅在有 Hue and Saturation 功能时 |
0 到 254 |
| 饱和度 | Color Control(0x0300),CurrentSaturation(0x0001) |
UInt32 | 发送 MoveToSaturation(0x03),过渡时间 0;仅在有 Hue and Saturation 功能时 |
0 到 254 |
| 色温 | Color Control(0x0300),ColorTemperatureMireds(0x0007) |
UInt32 | 发送 MoveToColorTemperature(0x0A),过渡时间 0;仅在有 Color Temperature 功能时。设备把值保持在它自己的限值之内 |
0 到 65279,单位是迈尔德 |
| 窗帘位置 | Window Covering(0x0102),CurrentPositionLiftPercent100ths(0x000E) |
UInt32 | 发送 GoToLiftPercentage(0x05) |
0(打开)到 10000(关闭),单位是百分之一个百分点 |
| 室内温度 | Thermostat(0x0201),LocalTemperature(0x0000) |
Float(°C) | 什么也不做:只读 | -27315 到 32767,单位是百分之一摄氏度;读数为 -273.15 到 327.67 °C |
| 制冷设定值 | Thermostat(0x0201),OccupiedCoolingSetpoint(0x0011) |
Float(°C) | 写入该属性。设备拒绝超出它自己限值的设定值 | -27315 到 32767,单位是百分之一摄氏度;读数为 -273.15 到 327.67 °C |
| 制热设定值 | Thermostat(0x0201),OccupiedHeatingSetpoint(0x0012) |
Float(°C) | 写入该属性。设备拒绝超出它自己限值的设定值 | -27315 到 32767,单位是百分之一摄氏度;读数为 -273.15 到 327.67 °C |
| 风扇模式 | Fan Control(0x0202),FanMode(0x0000) |
UInt32 | 写入该属性 | 0 关,1 低,2 中,3 高,4 开,5 自动,6 智能 |
| 风扇速度设定 | Fan Control(0x0202),PercentSetting(0x0002) |
UInt32 | 写入该属性 | 0 到 100 百分比 |
| 风扇速度 | Fan Control(0x0202),PercentCurrent(0x0003) |
UInt32 | 什么也不做:只读 | 0 到 100 百分比 |
| 温度 | Temperature Measurement(0x0402),MeasuredValue(0x0000) |
Float(°C) | 什么也不做:只读 | -27315 到 32767,单位是百分之一摄氏度;读数为 -273.15 到 327.67 °C |
| 湿度 | Relative Humidity Measurement(0x0405),MeasuredValue(0x0000) |
Float(%) | 什么也不做:只读 | 0 到 10000,单位是百分之一个百分点;读数为 0 到 100 % |
| 照度 | Illuminance Measurement(0x0400),MeasuredValue(0x0000) |
UInt32 | 什么也不做:只读 | 0 到 65534,即 10000 × log10(勒克斯) + 1 |
| 压力 | Pressure Measurement(0x0403),MeasuredValue(0x0000) |
Float(kPa) | 什么也不做:只读 | -32767 到 32767,单位是十分之一千帕;读数为 -3276.7 到 3276.7 kPa |
| 占用 | Occupancy Sensing(0x0406),Occupancy(0x0000) |
Boolean | 什么也不做:只读 | 有人时为 true |
| 状态 | Boolean State(0x0045),StateValue(0x0000) |
Boolean | 什么也不做:只读 | true 或 false |
规范以固定单位发送温度、湿度和压力:百分之一摄氏度、百分之一个百分点和十分之一千帕。设备发现一开始就以 °C、% 和 kPa 提供这些值:点位到达时,量程换算环节里已经带着系数(温度和湿度为 0.01,压力为 0.1)和单位,所以设备发送 2150 时读作 21.5 °C。写入会在值发出之前把这个环节反过来算,所以写成 21.5 的设定值以 2150 到达设备。照度是对数值(10000 × log10(lux) + 1),没有哪个系数能换算它:它按设备发送的数字来读。其他所有值也都按设备发送的样子来读。
门锁、按 X 和 Y 坐标定的颜色、场景、组以及 Toggle 命令都不在表里。Matter 设备也没有自己的命令:每一次改动都是写它的某个点位。
写入一个值
访问为读写的 Matter 点位在被写入时会改变设备:无论写入来自它的“实时数值”卡片、仪表盘控件、Logic 还是代理。写入和任何驱动一样进入设备的队列,与设备的读取轮流进行,得到的回答是设备自己的回答。驱动根据这张表选择 Matter 命令或属性写入;没有人去选命令。只有设备回答 SUCCESS 才算写入成功。其余一律拒绝,并给出原因:
| 发生了什么 | 在哪里判定 | 给出的原因 |
|---|---|---|
| 这个点不是驱动表里的值 | 发送任何东西之前 | 驱动不知道设备怎么改变这个值,所以这个点位只读它。 |
| 这个点是表里标为只读的值 | 发送任何东西之前 | 设备报告这个值,外面没有东西去设它。 |
| 写入的值既不是 true 也不是 false(对 Boolean 值),或者不是整数 | 发送任何东西之前 | 这个值接受什么,以及写进来的是什么。 |
| 值超出规范规定的范围 | 发送任何东西之前 | 上表给出的范围。 |
| 点位没有指定簇 | 发送任何东西之前 | Matter 的值要靠输出、簇和属性来找。 |
| 设备用 SUCCESS 以外的任何状态回答 | 设备 | 设备给出的原样状态:它在规范里的名称和编号,例如 CONSTRAINT_ERROR, 0x87(值超出了设备接受的范围)或 UNSUPPORTED_COMMAND, 0x81(设备不接受改变这个值的命令)。簇附加的状态跟在后面(FAILURE, 0x01, cluster 0x02),规范没有命名的状态只读作它的编号。 |
| 设备没有及时回答 | 设备 | 无应答。 |
被拒绝的写入绝不会报成已写入,也不会报成连不上现场设备。在点位页面上,设备拒绝时状态行写“现场设备拒绝了写入:CONSTRAINT_ERROR, 0x87。”;在发送任何东西之前就断定的拒绝,状态的位置换成原因;没有收到答复时写“写入未得到确认:现场设备没有及时应答。”;“写入失败:无法连上现场设备。”留给没有连上的设备。原因也随写入一起传递:这次写入的日志行连同状态的含义写明原因,代理的 tag_write 也会把原因返回。
手工创建的点位
对于设备没有以扫描能提供的形式公开的少见的值,在 Matter 设备上点添加点位会创建一个要手工填写的点位。它的“信号源”卡片把三个字段排在一行,下面的地址预览把它们按十进制拼成 <endpoint>/<cluster>/<attribute>(1/8/0 是第一个输出的亮度)。选好簇之前,这个点位不会保存,面板会说:“请选择这个点位读取的簇。没有簇,就不会向设备请求任何东西。”
| 字段 | 作用 | 取值 | 默认值 |
|---|---|---|---|
| 输出(endpoint) | 点位读设备的哪一个输出。 | 0 到 65535;1 是第一个可控的输出,0 是节点本身 | 1 |
| Matter 簇 | 点位读这个输出上的哪一个簇。 | Matter 目录里的簇,按规范名称加编号列出,比如 Level Control (0x0008);目录里没有名称、由扫描找到的簇按编号排在最前面 |
无 |
| 属性 | 点位读这个簇的哪一个属性。 | 0 及以上;0 是这个簇自己的值 | 0 |
点位名称随意:它只给点位取名,不在设备上选择任何东西。数据类型从 Boolean、Int32、UInt32、Float、Double 和 String 中选;声明的类型表示不了的读数读作报错,而不是给一个凑数的数字。值按设备发送的样子到达:手工创建的温度、湿度或压力点位读作百分之一或十分之一的单位,直到你在它的量程换算环节里填上上表的系数和单位。
访问字段只在驱动的表会改变这个值的地方提供写入;否则只提供只读,并在下面说明原因:
| 点 | 访问字段提供 | 说明的话 |
|---|---|---|
| 表里由命令或属性写入改变的值 | 只读、只写和读写 | 无 |
| 还没有选簇 | 只读 | “在点位指向设备的某个值之前是只读的:请选择它的簇。” |
| 表不认识的值 | 只读 | “只读:驱动不知道设备如何改变这个值。” |
| 表标为只读的值 | 只读 | “只读:这个值由设备报告,外部不能设定它。” |
对输出、簇或属性的编辑让点位指向驱动无法写入的值时,它的访问回到只读。设备发现提供的点位保留设备发现给它的访问,因为只有设备发现会询问设备接受哪些命令:设备没有列出的值保持只读,而字段仍然提供写入。
早期版本保存的点位
早期版本只用点位名称来指定 Matter 点位的簇,地址是 <endpoint>/<attribute>。本版本第一次启动时,凡是名称是 Matter 目录里某个簇的 Matter 设备点位(看最后一个冒号后面的部分,去掉两边的空格,不区分大小写),都会得到这个簇,于是它继续读和以前完全一样的值。它的名称保持原样,地址预览随后显示 <endpoint>/<cluster>/<attribute>。名称对不上任何簇的点位从来没读到过东西:它保持没有簇,读取会被拒绝并说明原因,它的页面会要求选择簇。转换后的点位保留原来的访问,即只读,那也是那些版本唯一提供的访问;要写它,就选读写,这对上表里的值有效。