OTA 更新提供者 Cluster(OtaSoftwareUpdateProvider)
Cluster ID: 0x0029 |
所在 Endpoint: 固定在 Endpoint 0(Root Endpoint) |
角色: Client Cluster(由 Provider 节点实现)
OtaSoftwareUpdateProvider 是 Matter OTA(Over-The-Air)固件更新机制的服务端 Cluster —— 它运行在提供固件镜像的节点上(通常是 Hub、网关或云端代理),负责响应其他设备的固件查询请求、 管控更新节奏、以及接收更新完成通知。
在 Matter 的 OTA 架构中,需要更新的设备叫做 Requestor(请求者), 提供固件的节点叫做 Provider(提供者)。Requestor 主动向 Provider 发起查询, Provider 告诉它有没有新版本、从哪里下载、是否需要用户同意。整个流程是「拉取」模式,不是推送。
OtaSoftwareUpdateProvider 是一个 Client Cluster —— 它定义的是 Provider 端接收的命令, 而不是暴露的属性。因此这个 Cluster 没有属性可读取,所有交互都通过命令完成。 与之配对的 OtaSoftwareUpdateRequestor(0x002A) 是 Server Cluster, 运行在需要更新的设备上,负责发起查询和执行下载。
命令(Commands)
OtaSoftwareUpdateProvider Cluster 共有 3 个请求命令,其中 2 个有对应的响应命令,1 个是单向通知。 这三个命令构成了完整的 OTA 更新生命周期:查询 → 确认安装 → 通知完成。 点击下方表格中的命令 ID 可跳转到对应的详细说明。
Requestor → Provider(请求命令)
| ID | 名称 | 说明 | 响应 |
|---|---|---|---|
0x00 |
QueryImage | 查询是否有可用的固件更新 | QueryImageResponse |
0x02 |
ApplyUpdateRequest | 下载完成,请求确认是否安装 | ApplyUpdateResponse |
0x04 |
NotifyUpdateApplied | 通知 Provider 更新已成功安装 | 无响应 |
Provider → Requestor(响应命令)
| ID | 名称 | 说明 | 对应请求 |
|---|---|---|---|
0x01 |
QueryImageResponse | 返回固件查询结果(有无更新、下载地址等) | QueryImage |
0x03 |
ApplyUpdateResponse | 返回是否允许安装更新 | ApplyUpdateRequest |
QueryImage —— 查询固件更新(0x00)
Requestor 发送此命令询问 Provider:「我是这个型号、这个版本的设备,你那有没有更新给我?」 这是整个 OTA 流程的第一步。Provider 根据 Requestor 提供的厂商 ID、产品 ID、 当前版本号等信息,判断是否有适用的固件镜像。
| 参数 | 类型 | 必选 | 说明 |
|---|---|---|---|
| VendorID | vendor-id | 是 | Requestor 的厂商 ID(与 BasicInformation Cluster 中的一致) |
| ProductID | uint16 | 是 | Requestor 的产品 ID |
| SoftwareVersion | uint32 | 是 | Requestor 当前运行的固件版本号 |
| ProtocolsSupported | list<DownloadProtocolEnum> | 是 | Requestor 支持的下载协议列表(如 BDX、HTTPS) |
| HardwareVersion | uint16 | 否 | Requestor 的硬件版本号(某些固件仅适用于特定硬件版本) |
| Location | String (2 字符) | 否 | ISO 3166-1 alpha-2 国家代码(如 "CN"),用于区域限定的固件分发 |
| RequestorCanConsent | bool | 否 | Requestor 是否有能力向用户展示更新同意对话框(如带屏幕的设备) |
| MetadataForProvider | octstr | 否 | 厂商自定义的元数据(Provider 可据此做额外判断) |
QueryImageResponse 响应字段
| 字段 | 类型 | 条件 | 说明 |
|---|---|---|---|
| Status | StatusEnum | 始终 | 查询结果状态 |
| DelayedActionTime | uint32(秒) | 可选 | 当 Status 为 Busy 时,建议 Requestor 等待这么多秒后重试 |
| ImageURI | String (max 256) | UpdateAvailable | 固件镜像的下载地址(BDX URI 或 HTTPS URL) |
| SoftwareVersion | uint32 | UpdateAvailable | 新固件的版本号 |
| SoftwareVersionString | String (max 64) | UpdateAvailable | 新固件的版本字符串(人类可读,如 "2.0.0") |
| UpdateToken | octstr (max 32) | UpdateAvailable | 更新令牌 —— 后续 ApplyUpdateRequest 和 NotifyUpdateApplied 必须携带此令牌 |
| UserConsentNeeded | bool | 可选 | 是否需要用户在 Requestor 侧手动确认更新(默认 false) |
| MetadataForRequestor | octstr | 可选 | Provider 返回给 Requestor 的厂商自定义数据 |
UpdateToken 是贯穿整个 OTA 流程的凭据。Requestor 在后续的 ApplyUpdateRequest
和 NotifyUpdateApplied 中必须携带同一个 Token,Provider 借此追踪更新会话。
Token 最长 32 字节,由 Provider 生成,内容和格式由厂商自定义。
使用场景与注意事项
Requestor 通常在以下时机调用 QueryImage:周期性检查(如每 24 小时)、设备重启后、或收到管理员的检查指令。
Provider 可能返回 Busy 并附带 DelayedActionTime,让 Requestor 稍后重试
—— 这在大规模设备场群中很常见,Provider 通过错峰控制避免同时下载导致的网络拥塞。
ApplyUpdateRequest —— 请求安装更新(0x02)
Requestor 下载完固件镜像并校验通过后,发送此命令询问 Provider:「我准备好安装了,可以继续吗?」 Provider 可以在此刻做最后的决策 —— 批准安装、要求等待、或者取消更新。 这一步的存在让 Provider 对整个更新流程拥有最终控制权。
| 参数 | 类型 | 说明 |
|---|---|---|
| UpdateToken | octstr | QueryImageResponse 中返回的更新令牌 |
| NewVersion | uint32 | 即将安装的新固件版本号(应与 QueryImageResponse 中的 SoftwareVersion 一致) |
ApplyUpdateResponse 响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| Action | ApplyUpdateActionEnum | Provider 对安装请求的决策 |
| DelayedActionTime | uint32(秒) | 当 Action 为 AwaitNextAction 时,Requestor 应等待这么多秒后再次请求 |
即使 Requestor 已经下载好了固件,Provider 仍然可以通过 AwaitNextAction 延迟安装时间
(比如等到凌晨低峰期),或通过 Discontinue 直接取消更新(比如发现这个版本有严重 bug)。
这种设计让 Provider 在整个 OTA 流程中始终保持控制力。
使用场景与注意事项
典型流程:Requestor 下载完固件 → 校验 OTA Image 签名 → 发送 ApplyUpdateRequest → 收到 Proceed → 执行安装并重启。 如果 Provider 返回 AwaitNextAction,Requestor 应等待 DelayedActionTime 秒后重新发送 ApplyUpdateRequest。 如果收到 Discontinue,Requestor 应放弃安装并丢弃已下载的镜像。
NotifyUpdateApplied —— 通知更新已完成(0x04)
Requestor 成功安装固件并重启后,发送此命令告知 Provider 更新已完成。 这是整个 OTA 流程的最后一步 —— 一个单向通知,没有响应命令。 Provider 收到后可以更新自己的记录(如标记该设备已更新到新版本)。
| 参数 | 类型 | 说明 |
|---|---|---|
| UpdateToken | octstr | 本次更新会话的令牌(与 QueryImageResponse 中的一致) |
| SoftwareVersion | uint32 | 更新后的当前固件版本号 |
NotifyUpdateApplied 是纯通知性质的 —— Requestor 不需要 Provider 的确认。 设备已经成功重启运行在新版本上,即使 Provider 没收到这个通知,也不影响设备正常工作。 Provider 端通常用这个通知来更新统计数据(如「已有多少设备升级到新版本」)。
使用场景与注意事项
设备重启后应尽快发送此通知。如果 Requestor 在重启后无法立即连接到 Provider(如网络恢复需要时间), 它应该在恢复连接后补发。规范建议 Requestor 在重启后的首次 Idle 状态下发送 NotifyUpdateApplied。
枚举定义
StatusEnum(查询结果状态)
QueryImageResponse 的 Status 字段使用此枚举,表示 Provider 对固件查询的回答。
UpdateAvailable → 开始下载 ImageURI 指向的固件; Busy → 等待 DelayedActionTime 秒后重新 QueryImage; NotAvailable → 无事可做,按正常周期下次再查; DownloadProtocolNotSupported → 检查 Requestor 的 ProtocolsSupported 列表,确认是否遗漏了 Provider 支持的协议。
ApplyUpdateActionEnum(安装决策)
ApplyUpdateResponse 的 Action 字段使用此枚举,表示 Provider 对安装请求的决策。
DownloadProtocolEnum(下载协议)
QueryImage 的 ProtocolsSupported 参数使用此枚举,声明 Requestor 支持哪些固件下载方式。
大多数 Matter 设备使用 BDX(Bulk Data Exchange) 协议下载固件, 因为它走 Matter 消息通道,不需要设备有独立的互联网连接能力。 HTTPS 适合有 Wi-Fi 的设备直接从云端下载,速度更快但需要设备能访问外网。 Thread 设备(如门锁、传感器)通常只支持 BDX,因为它们通过 Border Router 联网,不一定能直接发起 HTTPS 请求。
示例数据
QueryImage 交互示例
Requestor 向 Provider 查询可用更新 —— Provider 回复「有新版本可用」:
// Requestor → Provider:查询是否有可用固件
{
"invokeRequests": [{
"commandPath": {
"endpointId": 0,
"clusterId": "0x0029",
"commandId": "0x00" // QueryImage
},
"commandFields": {
"vendorID": 65521, // 厂商 ID(0xFFF1 = 测试厂商)
"productID": 32769, // 产品 ID
"softwareVersion": 1, // 当前固件版本号
"protocolsSupported": [0], // 支持的下载协议:BDXSynchronous
"hardwareVersion": 0, // 可选:硬件版本
"location": "CN", // 可选:ISO 3166-1 国家代码
"requestorCanConsent": true, // 可选:Requestor 能否向用户展示同意确认
"metadataForProvider": null // 可选:厂商自定义数据
}
}]
}
// Provider → Requestor:有可用更新
{
"status": 0, // UpdateAvailable
"delayedActionTime": 0, // 无需等待,立即可下载
"imageURI": "bdx://provider-node-id/firmware-v2.ota",
"softwareVersion": 2, // 新固件版本号
"softwareVersionString": "2.0.0",
"updateToken": "dXBkYXRlLXRva2VuLXYy", // Base64 编码的更新令牌
"userConsentNeeded": false, // 无需用户额外确认
"metadataForRequestor": null // 无厂商自定义数据
}
ApplyUpdateRequest 交互示例
Requestor 下载完成,向 Provider 确认是否可以安装:
// Requestor → Provider:下载完成,请求应用更新
{
"invokeRequests": [{
"commandPath": {
"endpointId": 0,
"clusterId": "0x0029",
"commandId": "0x02" // ApplyUpdateRequest
},
"commandFields": {
"updateToken": "dXBkYXRlLXRva2VuLXYy", // QueryImageResponse 中的令牌
"newVersion": 2 // 即将安装的版本号
}
}]
}
// Provider → Requestor:确认继续安装
{
"action": 0, // Proceed(允许安装)
"delayedActionTime": 0 // 无需等待
}
NotifyUpdateApplied 示例
Requestor 安装成功并重启后,通知 Provider 更新已完成:
// Requestor → Provider:已成功安装并重启
{
"invokeRequests": [{
"commandPath": {
"endpointId": 0,
"clusterId": "0x0029",
"commandId": "0x04" // NotifyUpdateApplied
},
"commandFields": {
"updateToken": "dXBkYXRlLXRva2VuLXYy", // 原始更新令牌
"softwareVersion": 2 // 更新后的当前版本号
}
}]
}
// 此命令无响应(单向通知)
在开发 OTA Provider 时,最核心的逻辑在 QueryImage 的处理 —— 你需要根据 VendorID + ProductID + SoftwareVersion
匹配正确的固件,并通过 ProtocolsSupported 选择合适的下载方式。
如果你的设备群规模较大,善用 Busy 状态和 DelayedActionTime 做错峰分发。
常见场景
场景 1:标准固件更新流程
- Requestor 向 Provider 发送
QueryImage (0x00),携带自身的厂商 ID、产品 ID、当前版本号和支持的下载协议 - Provider 回复
QueryImageResponse,Status =UpdateAvailable,包含 ImageURI、新版本号和 UpdateToken - Requestor 通过 ImageURI 下载固件镜像(BDX 或 HTTPS)
- 下载完成后,Requestor 校验镜像签名(OTA Image 头部包含厂商签名)
- 校验通过,Requestor 发送
ApplyUpdateRequest (0x02),携带 UpdateToken 和 NewVersion - Provider 回复
ApplyUpdateResponse,Action =Proceed - Requestor 执行固件安装并重启
- 重启后,Requestor 发送
NotifyUpdateApplied (0x04),告知 Provider 更新成功
整个流程从查询到安装完成,通常需要数分钟到数十分钟,取决于固件大小和网络条件。
场景 2:固件回滚(紧急撤回有问题的版本)
- 厂商发现新版本 v2.0.0 有严重 bug,需要紧急撤回
- Provider 端下架 v2.0.0 的固件,改为提供 v1.0.1(修复版或回退版)
- 已更新到 v2.0.0 的设备下次 QueryImage 时,Provider 回复 UpdateAvailable,指向 v1.0.1
- 尚未更新的设备 QueryImage 时,Provider 回复
NotAvailable(跳过 v2.0.0) - 如果有设备已下载 v2.0.0 但还没安装(在 ApplyUpdateRequest 阶段),Provider 回复
Discontinue取消安装
关键点:Matter OTA 规范允许「降级」更新 —— SoftwareVersion 可以比当前版本低。 但实际能否降级取决于设备端的实现:部分设备的 bootloader 可能会拒绝安装低于当前版本的固件。
场景 3:多设备批量更新(错峰分发)
- 厂商发布新固件,设备群中有 10,000 台设备需要更新
- Provider 不希望所有设备同时下载,避免网络拥塞
- 前 100 台设备 QueryImage 时,Provider 回复
UpdateAvailable,立即允许下载 - 第 101 台开始,Provider 回复
Busy,DelayedActionTime = 3600(1 小时后重试) - 每批完成后,Provider 逐步放开下一批的配额
- 如果某设备下载完成后 Provider 希望它等到凌晨再安装,ApplyUpdateRequest 回复
AwaitNextAction,DelayedActionTime 设为到凌晨的秒数
实现建议:Provider 可以维护一个更新队列和并发计数器。
通过灵活使用 Busy(控制下载并发)和 AwaitNextAction(控制安装时机),
实现从容的灰度发布和错峰分发。
场景 4:需要用户同意的更新
- Requestor 在 QueryImage 中声明
RequestorCanConsent = true(设备有屏幕,可以展示确认对话框) - Provider 回复 UpdateAvailable,
UserConsentNeeded = true - Requestor 收到响应后,在设备屏幕上弹出确认对话框:「有新版本 v2.0.0 可用,是否更新?」
- 用户点击「确认」后,Requestor 才开始下载固件
- 如果用户拒绝,Requestor 暂不下载,下次检查周期再次询问
无屏设备:如果 Requestor 没有屏幕(RequestorCanConsent = false),
Provider 通常不会设置 UserConsentNeeded = true。对于这类设备,用户同意可以通过手机 App 中的
OTA 管理界面来实现(App 作为中间人传达用户意图)。