Matter OTA Provider Linux 参考应用完全指南:构建、命令行参数与源码原理
2026/9/18 7:26:10 网站建设 项目流程

Matter OTA Provider Linux 参考应用完全指南:构建、命令行参数与源码原理

【免费下载链接】connectedhomeipMatter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers and increasing compatibility for consumers, guided by the Connectivity Standards Alliance.项目地址: https://gitcode.com/GitHub_Trending/co/connectedhomeip

本篇指南围绕 connectedhomeip(Matter 参考实现)中的 Linux OTA Provider 参考应用展开,它以examples/ota-provider-app/linux为骨架,完整实现了一个 OTA Software Update Provider Cluster Server(OTA 软件升级提供方集群服务器),用于向同 Fabric 内的 OTA Requestor 设备提供固件升级镜像。读完本文,你将掌握该应用的构建方法、全部命令行参数的含义与默认值、--otaImageListJSON 配置文件的编写规范、OTA 镜像头(Software Image Header)的生成方式,以及通过 ACL 授权让 Requestor 正常调用 QueryImage 的完整配置流程,并深入理解其底层源码实现。

应用定位与整体结构

OTA Provider 是 Matter OTA 升级链路中的"服务端"角色:OTA Requestor(请求方,通常是终端设备)向 Provider 发送QueryImage命令询问是否有可用更新,Provider 依据自身策略返回QueryImageResponse;随后双方通过 BDX(Bulk Data Exchange)协议传输固件镜像,Requestor 下载完成后调用ApplyUpdateRequestNotifyUpdateApplied完成升级闭环。

Linux 版本的 OTA Provider 是一个完整可运行的参考实现,其核心源码分布如下:

  • 入口与参数解析:命令行选项定义、JSON 镜像列表解析、ApplicationInit初始化;
  • OTA Provider 核心逻辑:OTAProviderDelegate接口的三个命令处理函数HandleQueryImageHandleApplyUpdateRequestHandleNotifyUpdateApplied,以及镜像选择、用户同意、BDX 会话初始化等;
  • BDX 发送器:继承chip::bdx::Responder,负责以发送方角色执行 BDX 传输(头文件见 BdxOtaSender.h);
  • 构建配置 与 args.gni。

应用将 OTA Provider 集群部署在endpoint 0(见 main.cpp 中的kOtaProviderEndpoint = 0),并通过chip::app::Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, &GetOtaProviderExample())将委托实例注册到集群服务器上。启动阶段还会把BdxOtaSender注册为 BDX 协议的无请求消息处理器,从而能够接收 Requestor 发起的 BDX 传输请求(见 main.cpp)。

构建 OTA Provider 应用

推荐使用仓库自带的 GN 构建脚本,命令如下:

scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug chip_config_network_layer_ble=false
  • examples/ota-provider-app/linux:待构建的 example 目标;
  • out/debug:构建输出目录;
  • chip_config_network_layer_ble=false:禁用 BLE 网络层(Linux 平台通常使用 IP 网络完成发现与配对)。

构建产物为可执行文件chip-ota-provider-app,默认输出到out/debug目录。从 BUILD.gn 可以看到,该目标依赖ota-provider-commonapp-main(Linux 平台应用框架)、ota-provider集群实现、user-consent(用户同意模块)、bdx协议栈以及jsoncpp(用于解析镜像列表 JSON)。

命令行参数完全解析

应用通过ChipLinuxAppInit(argc, argv, &cmdLineOptions)解析参数,完整选项定义见 main.cpp。下表整理了所有选项及其在源码中的行为,标注了默认值与"首次响应后回退"策略。

选项说明
-a, --applyUpdateAction <proceed \| awaitNextAction \| discontinue>首次ApplyUpdateResponseAction字段的值;后续所有响应固定使用proceed。源码中发送响应后会把mUpdateAction重置为kProceed(见 OTAProviderExample.cpp)
-c, --userConsentNeeded若提供,QueryImageResponseUserConsentNeeded字段置为true仅当 QueryImage 命令中RequestorCanConsent为 true 时生效,否则该字段为false(见 SendQueryImageResponse)
-f, --filepath <file path>包含 OTA 镜像的文件路径,应用将自动把该文件提供给 OTA Requestor
-i, --imageUri <uri>QueryImageResponseImageURI字段的值;若未提供,应用会基于节点 ID 与文件设计符自动生成一个合法的 BDX URI
-m, --maxBDXBlockSize <size>BDX 传输最大块大小;若未提供,使用默认值 1024 字节(源码常量kMaxBdxBlockSize,见 OTAProviderExample.cpp)。注意:该选项未出现在 README 表格中,但已由源码支持
-o, --otaImageList <file path>包含 OTA 镜像列表的 JSON 文件路径
-p, --delayedApplyActionTimeSec <秒>首次ApplyUpdateResponseDelayedActionTime字段的值;后续响应固定为 0
-q, --queryImageStatus <updateAvailable \| busy \| updateNotAvailable>首次QueryImageResponseStatus字段的值;后续响应固定回退为updateAvailable
-t, --delayedQueryActionTimeSec <秒>首次QueryImageResponseDelayedActionTime字段的值;后续响应固定为 0
-u, --userConsentState <granted \| denied \| deferred>首次QueryImageResponse的用户同意状态;后续固定为granted。注意--queryImageStatus优先级更高(覆盖本选项),三者映射关系为:grantedupdateAvailabledeniedupdateNotAvailabledeferredbusy
-x, --ignoreQueryImage <次数>忽略(不响应)QueryImage 命令的次数,用于测试超时/无响应场景
-y, --ignoreApplyUpdate <次数>忽略 ApplyUpdate 请求的次数
-P, --pollInterval <毫秒>BDX 传输的轮询间隔;默认 50ms(源码常量kBdxServerPollIntervalMillis
--persistQueryImageStatus长选项(无短形式)。提供后,--queryImageStatus及其DelayedActionTime将用于每一次QueryImageResponse,而不是首次响应后回退到updateAvailable,便于持续模拟busy/updateNotAvailable状态(见 main.cpp)

其中若干选项与源码实现存在深层关联:

  • 状态回退机制:默认情况下,busyupdateNotAvailable等状态被设计为"一次性"条件——服务完一次后,ApplyQueryImageStatusAfterResponse()会将状态重置回updateAvailable、延时归零,避免测试套件因 Provider 卡死在异常状态而反复重启(见 OTAProviderExample.cpp)。如需持续保持特定状态,请使用--persistQueryImageStatus
  • 用户同意状态deferred在内部映射为UserConsentState::kObtaining(获取中),此时 Provider 返回busy状态;granted映射为kGranteddenied映射为kDenied(见 main.cpp)。
  • 忽略计数--ignoreQueryImage N会让前 N 次 QueryImage 请求"石沉大海"(不发送任何响应也不发送错误状态),对应HandleQueryImage开头的计数判断(见 OTAProviderExample.cpp)。

除上述选项外,应用还继承 Linux 平台通用参数,例如--discriminator(长鉴别码,默认 3840)、--secured-device-port(安全端口,默认 5540)、--KVS(KVS 存储位置,默认/tmp/chip_kvs)、--autoApplyImage等,具体可参考 OTA Requestor Linux README 中的运行示例。

一个典型启动命令如下(参考 ota-requestor-app/linux/README.md):

out/chip-ota-provider-app --discriminator 22 --secured-device-port 5565 --KVS /tmp/chip_kvs_provider --filepath /tmp/ota-image.bin

使用--filepath--otaImageList

两种提供镜像的方式存在严格的约束,参数解析逻辑见 main.cpp:

  1. 二者不能同时提供HandleOptions通过静态标志位检测,若先出现-f再出现-o(或反之),会直接报错退出;
  2. 至少必须提供其一:若两者都为nullptrApplicationInit会记录错误日志 "Either an OTA file or image list file must be specified" 并调用chipDie()终止进程(见 main.cpp);
  3. 提供--filepath时,应用直接将该文件作为唯一可提供的镜像;
  4. 提供--otaImageList时,应用解析 JSON 文件,从中选取"最新且有效"的软件版本,并把对应 OTA 文件发送给 Requestor。

镜像列表 JSON 格式

--otaImageList指向的 JSON 文件以deviceSoftwareVersionModel数组为核心(解析逻辑见 main.cpp)。注意:文件顶部允许出现 C/C++ 风格注释builder["collectComments"] = true),README 示例中的{ "foo": 1, // ignored by parser正是利用了这一特性——解析器会忽略该无效字段。

{ "foo": 1, // ignored by parser "deviceSoftwareVersionModel": [ { "vendorId": 1, "productId": 1, "softwareVersion": 10, "softwareVersionString": "1.0.0", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v10.bin" }, { "vendorId": 1, "productId": 1, "softwareVersion": 20, "softwareVersionString": "1.0.1", "cDVersionNumber": 18, "softwareVersionValid": false, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v20.bin" }, { "vendorId": 1, "productId": 1, "softwareVersion": 30, "softwareVersionString": "1.0.2", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v30.bin" }, { "vendorId": 1, "productId": 1, "softwareVersion": 40, "softwareVersionString": "1.1.0", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v40.bin" }, { "vendorId": 1, "productId": 1, "softwareVersion": 50, "softwareVersionString": "1.1.1", "cDVersionNumber": 18, "softwareVersionValid": false, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "/tmp/ota_v50.bin" } ] }

各字段含义与源码默认值(解析时缺省即采用,见 main.cpp):

字段说明解析默认值
vendorId厂商 ID1
productId产品 ID1
softwareVersion软件版本号(uint32)10
softwareVersionString软件版本字符串"1.0.0"
cDVersionNumber认证声明(CD)版本号0
softwareVersionValid该版本是否有效(可选)true
minApplicableSoftwareVersion适用的最低请求方版本0
maxApplicableSoftwareVersion适用的最高请求方版本1000
otaURLOTA 镜像文件路径"https://test.com"

版本校验与镜像选择

从源码可以确认两条关键行为:

  1. 版本一致性校验SetOTACandidates()会逐个打开候选镜像并解析其头部,通过VerifyOrDie强制校验 JSON 中的vendorIdproductIdsoftwareVersionsoftwareVersionStringmin/maxApplicableSoftwareVersion与镜像头完全一致;只要有一项不一致,进程即终止(见 OTAProviderExample.cpp)。因此务必保证otaURL指向的文件确实带有与 JSON 条目匹配的镜像头。

  2. 候选选择算法SelectOTACandidate()首先按softwareVersion升序排序所有候选,然后依次遍历,选出满足以下全部条件的候选:

    • softwareVersionValid == true
    • 候选版本号>请求方当前版本号(requestorSoftwareVersion < candidate.softwareVersion);
    • 请求方当前版本号落在[minApplicableSoftwareVersion, maxApplicableSoftwareVersion]区间内。

    由于候选已升序排列,最终命中的将是满足条件中版本最高的一个(见 OTAProviderExample.cpp)。若没有任何候选命中,QueryImageResponse的状态会置为updateNotAvailable

    对照上述示例 JSON:v10 对应"有效",请求方版本为 0 时会命中 v10;而softwareVersionValid=false的 v20、v50 永远不会被选中。同时注意,Provider 端版本判定逻辑与 OTA Requestor 侧的行为(仅当响应版本高于当前运行版本时才继续下载)相互配合,共同构成完整的升级前提校验。

软件镜像头(Software Image Header)

Matter 规范(第 11.21.1 节)要求所有 Matter 软件镜像必须携带一个软件镜像头。仓库提供了 ota_image_tool.py 用于在固件上生成所需头部。凡是通过--filepath--otaImageList提供给 OTA Provider 的镜像,都必须包含该头部——Provider 会从头部解析SoftwareVersion字段并填入QueryImageResponse

例如,为一个软件版本号为 2 的固件生成带头镜像:

src/app/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 2 -vs "2.0" -da sha256 firmware.bin firmware.ota

参数含义:-v指定厂商 ID(0xDEAD)、-p指定产品 ID(0xBEEF)、-vn指定版本号(2)、-vs指定版本字符串("2.0")、-da指定摘要算法(sha256),输出为firmware.ota

在 Provider 端,镜像头的解析路径为:ParseOTAHeader()以二进制方式读取文件前 1024 字节(常量kOtaHeaderMaxSize),交给OTAImageHeaderParserAccumulateAndDecode解码(见 OTAProviderExample.cpp)。当使用--filepath直接提供单个镜像时,每次HandleQueryImage都会重新解析镜像头来取得mSoftwareVersionmSoftwareVersionString(见 OTAProviderExample.cpp)。

如需构建一个携带指定软件版本的 OTA Requestor 应用进行端到端验证,请参考 OTA Requestor Linux README 中 "Generate Images" 一节:其流程是先修改CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION为更大版本号,再重新构建 Requestor 并用ota_image_tool.py为生成的可执行文件打上匹配版本号的镜像头,最后用带--autoApplyImage的旧版本 Requestor 应用发起升级。

访问控制要求(ACL)

OTA Provider 集群的可用性依赖 ACL(Access Control List,访问控制列表)授权。Commissioner 或 Administrator应当在配网时或之后安装必要的 ACL 条目,允许同 Fabric 内的 OTA Requestor 处理QueryImage命令,否则该 Provider 对 Requestor 不可用。

由于ACL属性本身是一个列表,写入时不能只包含新条目,而必须先读取现有条目再连同新条目一并写入。下面是一个写入两条 ACL 条目的完整示例:

out/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": [{"cluster": 41, "endpoint": null, "deviceType": null}]}]' 0xDEADBEEF 0
  • 条目 1:配网时自动创建的原始条目,向节点 ID 112233(默认控制器节点 ID)授予privilege: 5(Administer,管理)权限,覆盖所有 endpoint 上的所有集群;
  • 条目 2:新增条目,向所有节点(subjects: null)授予privilege: 3(Operate,操作)权限,目标为cluster: 41——即 OTA Provider 集群(0x0029 的十进制值)——覆盖所有 endpoint。

该示例的适用前提:Provider 位于 fabric index 1,节点 ID 为0xDEADBEEF,endpoint 为 0。authMode: 2表示使用 Case(证书认证会话模式)。注意:endpoint: nulldeviceType: null表示不限制 endpoint 与设备类型,targets: null表示不限制目标。

当前限制(Current Limitations)

README 明确了该参考实现目前的已知限制,对应源码也可找到佐证:

  1. 仅支持同步 BDX 传输BdxOtaSender使用轮询式事件处理(默认每 50ms 轮询一次,可经--pollInterval调整),不支持异步/多会话并行;
  2. 不校验 VID/PIDSelectOTACandidate()的注释明确说明当前以 vendorId/productId 作为查询主键的校验尚未启用("VendorID and ProductID will be the primary key when querying the DCL servers. If not we can add the vendor/product ID checks here.",见 OTAProviderExample.cpp);
  3. 同一时刻仅支持一个传输SendQueryImageResponse()中若InitializeTransfer失败(说明已有 BDX 传输正在进行),会将状态临时切换为kBusy(见 OTAProviderExample.cpp);同时HandleApplyUpdateRequest中也留有 TODO 注释,说明尚未通过追踪updateToken来支持多传输(见 OTAProviderExample.cpp)。

测试与验证

该示例附带单元测试,可用于验证镜像列表版本校验与 BDX 会话逻辑:

  • TestOTAProviderExample.cpp:覆盖 OTA Provider 示例核心逻辑;
  • TestBdxOtaSenderPeerBinding.cpp:覆盖 BDX 发送器的对端绑定与会话行为。

实际验证 OTA 升级链路时,推荐组合使用 OTA Provider 与 OTA Requestor Linux 应用:分别以不同的--discriminator--secured-device-port--KVS启动两者并完成配网后,即可观察 QueryImage → BDX 传输 → ApplyUpdate 的完整流程。Requestor 侧的日志(如 "Available update version X is <= current version Y, update ignored")可帮助诊断版本校验失败,而 "Image does not contain a valid header" 则提示镜像缺少头部。

【免费下载链接】connectedhomeipMatter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers and increasing compatibility for consumers, guided by the Connectivity Standards Alliance.项目地址: https://gitcode.com/GitHub_Trending/co/connectedhomeip

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询