OTA 更新请求者 Cluster(OtaSoftwareUpdateRequestor)
Cluster ID: 0x002A |
所在 Endpoint: Endpoint 0(Root Endpoint) |
角色: Server(设备作为 OTA 客户端)
OtaSoftwareUpdateRequestor 是 Matter OTA 升级体系中的客户端侧 —— 即需要被升级的设备。 它负责向 OTA Provider(升级提供者,对应 Cluster 0x0029)查询是否有新版本、下载固件、应用更新。 所有支持 OTA 的 Matter 设备都必须实现这个 Cluster。
Matter 的 OTA 升级由两个 Cluster 配合完成: OtaSoftwareUpdateProvider(0x0029) 是「服务端」,负责托管固件并响应查询; OtaSoftwareUpdateRequestor(0x002A) 是「客户端」,负责发起查询、下载并应用更新。 本页描述的是后者 —— 设备侧的行为。
命令(Commands)
OtaSoftwareUpdateRequestor 只有 1 个命令。它不是由设备自己发起的,而是由外部节点 (通常是 OTA Provider 或管理节点)发送给设备,告知设备可以去某个 Provider 查询更新。
| ID | 名称 | 说明 | 方向 |
|---|---|---|---|
0x00 |
AnnounceOTAProvider | 通知设备有可用的 OTA Provider | Client → Server |
AnnounceOTAProvider —— 通告 OTA 提供者(0x00)
外部节点通过此命令告知设备:「有一个 OTA Provider 可以为你提供更新」。 收到此命令后,设备应尽快向指定的 Provider 发起更新查询(调用 Provider 的 QueryImage 命令)。 这是推送式 OTA 的核心触发机制 —— 让设备不必一直轮询,而是被动通知后再查询。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| ProviderNodeID | node-id | 是 | OTA Provider 节点的 Node ID |
| VendorID | vendor-id | 是 | Provider 的 Vendor ID,设备可据此判断是否信任该 Provider |
| AnnouncementReason | AnnouncementReasonEnum | 是 | 通告原因(见枚举说明) |
| MetadataForNode | octstr | 否 | Provider 传给设备的自定义元数据(最长 512 字节,可选) |
| Endpoint | endpoint-no | 是 | Provider 节点上 OTA Provider Cluster 所在的 Endpoint |
使用场景
管理后台发布了新固件,通过 Hub 或管理节点向所有目标设备发送 AnnounceOTAProvider 命令。 设备收到后,会向指定的 Provider 查询可用更新。如果 AnnouncementReason 是 UrgentUpdateAvailable, 设备应优先处理,可能跳过用户确认直接开始下载。
属性详解
OtaSoftwareUpdateRequestor 有 4 个应用属性,分为「Provider 配置」和「更新状态」两组。
| ID | 名称 | 类型 | 分组 | 说明 |
|---|---|---|---|---|
0x0000 |
DefaultOTAProviders | list<ProviderLocation> | Provider 配置 | 默认 OTA Provider 列表 |
0x0001 |
UpdatePossible | bool | 更新状态 | 设备是否可以接受更新 |
0x0002 |
UpdateState | UpdateStateEnum | 更新状态 | 当前 OTA 更新状态机的状态 |
0x0003 |
UpdateStateProgress | uint8 / null | 更新状态 | 更新进度百分比(0-100) |
Provider 配置(0x0000)
配置设备应该向哪些 OTA Provider 查询更新。每个 Fabric 最多配置一个 Provider。
| ID | 名称 | 类型 | 说明 |
|---|---|---|---|
0x0000 |
DefaultOTAProviders(默认 OTA 提供者) | list<ProviderLocation> |
设备默认查询的 OTA Provider 列表。每个条目是一个 ProviderLocation 结构体。
写入需要 manage 权限(Administrator 角色)。
每个 Fabric 最多包含一个条目 —— 同一 Fabric 写入新的会覆盖旧的
|
ProviderLocation 结构体
| 字段 | 类型 | 说明 |
|---|---|---|
| ProviderNodeID | node-id | OTA Provider 的 Node ID |
| Endpoint | endpoint-no | Provider 上 OTA Provider Cluster 所在的 Endpoint |
| FabricIndex | fabric-idx | 此条目所属的 Fabric 索引(由系统自动填入) |
DefaultOTAProviders 是按 Fabric 隔离的 —— 每个 Fabric(管理域)只能看到和修改自己的条目。 这意味着设备同时加入多个 Fabric 时,各个 Fabric 的管理者可以各自指定自己的 OTA Provider,互不影响。
更新状态(0x0001 - 0x0003)
反映设备当前的 OTA 更新状态。这些属性均为只读,App 端通过订阅这些属性来跟踪更新进度。
| ID | 名称 | 类型 | 说明 |
|---|---|---|---|
0x0001 |
UpdatePossible(可否更新) | bool |
设备当前是否能够接受 OTA 更新。true 表示可以,false 表示设备当前不允许更新
(例如正在执行关键操作、电量过低等)。默认值为 true
|
0x0002 |
UpdateState(更新状态) | UpdateStateEnum | 设备 OTA 状态机的当前状态(见枚举说明)。 从这个属性可以知道设备正在查询、下载、应用还是空闲 |
0x0003 |
UpdateStateProgress(更新进度) | uint8 / null |
当前更新操作的进度百分比,取值 0-100。Nullable —— null 表示进度不可用
(例如设备处于 Idle 状态,或所处阶段无法计算进度时为 null)
|
UpdateStateProgress 的含义取决于 UpdateState 的当前值。
在 Downloading 状态下表示下载进度,在 Applying 状态下表示安装/写入进度。
状态切换时进度可能重置为 0 或 null。不要假设它是一个线性增长的全局进度值。
枚举速查
UpdateStateEnum —— 更新状态
描述设备 OTA 状态机的完整生命周期,共 9 个状态:
AnnouncementReasonEnum —— 通告原因
AnnounceOTAProvider 命令中使用,告知设备此次通告的原因:
ChangeReasonEnum —— 状态变更原因
在 StateTransition 事件中使用,说明状态机发生状态转移的原因:
事件(Events)
OtaSoftwareUpdateRequestor 定义了 3 个事件,覆盖了 OTA 生命周期的关键节点。 订阅这些事件可以实时跟踪设备的更新流程,比轮询属性更及时。
| ID | 名称 | 优先级 | 说明 |
|---|---|---|---|
0x00 |
StateTransition | Info | OTA 状态机发生状态转移时触发 |
0x01 |
VersionApplied | Critical | 新固件版本成功应用后触发 |
0x02 |
DownloadError | Info | 固件下载过程中发生错误时触发 |
StateTransition —— 状态转移事件(0x00)
每当 OTA 状态机从一个状态转移到另一个状态时触发。这是追踪更新流程最核心的事件 —— 通过监听它可以知道设备从空闲到查询、从下载到应用的每一步。
| 字段 | ID | 类型 | 说明 |
|---|---|---|---|
| PreviousState | 0x00 |
UpdateStateEnum | 转移前的状态 |
| NewState | 0x01 |
UpdateStateEnum | 转移后的新状态 |
| Reason | 0x02 |
ChangeReasonEnum | 触发此次转移的原因 |
| TargetSoftwareVersion | 0x03 |
uint32 / null | 目标固件版本号。null 表示尚未确定(例如从 Idle 到 Querying 时还不知道目标版本) |
事件上报示例 —— 从 Idle 转入 Downloading:
{
"eventReports": [{
"eventData": {
"path": {
"endpointId": 0,
"clusterId": "0x002A",
"eventId": "0x00" // StateTransition
},
"eventNumber": 15,
"priority": "INFO",
"data": {
"0": 1, // PreviousState = Idle
"1": 4, // NewState = Downloading
"2": 1, // Reason = Success(查询成功,开始下载)
"3": 5 // TargetSoftwareVersion = 5
}
}
}]
}
VersionApplied —— 版本已应用事件(0x01)
新固件版本成功应用后触发(通常在设备重启后上报)。这个事件是确认「更新真正完成」的标志。 优先级为 Critical,确保即使在事件队列满时也不会被丢弃。
| 字段 | ID | 类型 | 说明 |
|---|---|---|---|
| SoftwareVersion | 0x00 |
uint32 | 刚刚应用的新固件版本号 |
| ProductID | 0x01 |
uint16 | 设备的产品 ID |
事件上报示例:
{
"eventReports": [{
"eventData": {
"path": {
"endpointId": 0,
"clusterId": "0x002A",
"eventId": "0x01" // VersionApplied
},
"eventNumber": 18,
"priority": "CRITICAL",
"data": {
"0": 5, // SoftwareVersion = 5(刚刚应用的版本号)
"1": 4 // ProductID = 4(产品 ID)
}
}
}]
}
DownloadError —— 下载错误事件(0x02)
固件下载过程中遇到错误时触发。此事件提供了出错时的上下文信息(已下载量、进度等), 有助于诊断网络问题或 Provider 端故障。
| 字段 | ID | 类型 | 说明 |
|---|---|---|---|
| SoftwareVersion | 0x00 |
uint32 | 正在下载的目标固件版本号 |
| BytesDownloaded | 0x01 |
uint64 | 出错前已成功下载的字节数 |
| ProgressPercent | 0x02 |
uint8 / null | 出错时的下载进度百分比(0-100),null 表示无法计算 |
| PlatformCode | 0x03 |
int64 / null | 平台特定的错误码,null 表示无额外信息。具体含义由设备厂商定义 |
事件上报示例 —— 下载到 75% 时出错:
{
"eventReports": [{
"eventData": {
"path": {
"endpointId": 0,
"clusterId": "0x002A",
"eventId": "0x02" // DownloadError
},
"eventNumber": 16,
"priority": "INFO",
"data": {
"0": 5, // SoftwareVersion = 5
"1": 512, // BytesDownloaded = 512
"2": 75, // ProgressPercent = 75(下载到 75% 时出错)
"3": -1 // PlatformCode = -1(平台错误码,nullable)
}
}
}]
}
示例数据
一个处于空闲状态的设备的 OtaSoftwareUpdateRequestor Cluster 属性读取结果:
{
// --- 默认 OTA 提供者 ---
"0x0000": [ // DefaultOTAProviders(可配置多个)
{
"providerNodeID": 12345, // Provider 的 Node ID
"endpoint": 0, // Provider 上 OTA Provider Cluster 所在的 Endpoint
"fabricIndex": 1 // 所属 Fabric 索引
}
],
// --- 更新能力 ---
"0x0001": true, // UpdatePossible = true(设备当前可以接受更新)
// --- 更新状态 ---
"0x0002": 0, // UpdateState = Idle(当前空闲,未在更新流程中)
"0x0003": null // UpdateStateProgress = null(无进度信息)
}
OTA Requestor Cluster 位于 Endpoint 0(Root Endpoint),不在功能端点上。
读取属性时注意指定正确的 Endpoint。此外,DefaultOTAProviders 是 Fabric-scoped 列表,
你只能看到当前 Fabric 的条目。
常见场景
场景 1:正常 OTA 更新流程
一次完整的 OTA 更新从通告到应用的典型流程:
- 管理节点向设备发送
AnnounceOTAProvider (0x00),告知有可用的 Provider - 设备向 Provider 发起 QueryImage 请求 —— UpdateState 从 Idle 变为 Querying
- Provider 返回可用更新 —— 设备开始下载,UpdateState 变为 Downloading
- 下载过程中,UpdateStateProgress 从 0 逐渐增长到 100
- 下载完成,设备验证固件并开始写入 —— UpdateState 变为 Applying
- 写入完成,设备重启应用新固件 —— 重启后触发 VersionApplied 事件
- UpdateState 回到 Idle,整个流程结束
场景 2:Provider 通告触发更新
通过 AnnounceOTAProvider 命令的不同原因触发不同的设备行为:
- SimpleAnnouncement (0):设备可以在方便时查询,不急迫。适合常规固件发布场景
- UpdateAvailable (1):明确告知有新版本,设备应尽快查询。适合功能更新
- UrgentUpdateAvailable (2):紧急安全补丁,设备应立即查询并优先下载。 此时设备可能跳过 DelayedOnUserConsent 直接进入下载,确保安全漏洞尽快修补
App 端在收到 StateTransition 事件时,可根据 Reason 字段判断是否需要向用户展示通知。 UrgentUpdateAvailable 触发的更新建议弹出醒目提示。
场景 3:更新进度跟踪
App 端实时展示 OTA 更新进度的实现方式:
- 订阅
UpdateState (0x0002)和UpdateStateProgress (0x0003)属性 - 同时订阅
StateTransition、VersionApplied、DownloadError三个事件 - 根据 UpdateState 的值显示不同的 UI 状态:
- Idle → 显示「固件已是最新」或「检查更新」按钮
- Querying → 显示「正在检查更新...」
- Downloading → 显示下载进度条,数值来自 UpdateStateProgress
- Applying → 显示「正在安装更新,请勿断电...」
- DelayedOnUserConsent → 显示确认对话框,等待用户同意
- RollingBack → 显示「更新失败,正在恢复...」
- 收到 VersionApplied 事件 → 显示「更新成功!已升级到版本 X」
- 收到 DownloadError 事件 → 显示「下载失败」并展示已下载进度,提供重试按钮
注意:UpdateStateProgress 在状态切换时可能变为 null 或重置为 0, UI 应处理好 null 的情况(例如隐藏进度条或显示不确定进度指示器)。