集群与设备类型开发完全指南:从 XML 定义、ZAP/Ember 集成到单元测试)
connectedhomeipMatter SDK集群与设备类型开发完全指南从 XML 定义、ZAP/Ember 集成到单元测试【免费下载链接】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导读本文是 Matter 开源 SDKconnectedhomeip中开发新 Cluster集群与 Device Type设备类型的端到端技术指南内容源自仓库 docs/cluster_and_device_type_dev 目录下的系列文档并辅以当前仓库源码验证。读完本文你将掌握如何在src/app/zap-templates/zcl/data-model/chip/下编写集群/设备类型的 XML 定义并接入 ZAP 代码生成链路如何选择 Ember 层回调与AttributeAccessInterface/CommandHandlerInterface覆盖Override两种实现机制以及如何使用ClusterTester辅助类对 code-driven 集群进行可维护、可认证的单元测试。集群与设备类型开发的三大目标开发一个新的 Cluster 或 Device Type最终要交付三类产出物集群实现Cluster implementation——真正运行在设备上的 C 逻辑。支撑 ZAP 代码生成的素材ZAP glue——让 ZAP 工具能识别新集群、为 Ember 层生成函数签名与默认实现。测试与认证材料Tests certification——单元测试、YAML/Python 测试计划与自动化脚本用于证明代码正确性并支撑认证。单元测试、测试计划与认证测试在 docs/testing 相关章节展开本文聚焦第 1、2 点即如何在 SDK 中实现集群与设备类型。Cluster 定义XML集群定义的载体是 XML 文件它是对 Matter 规范中集群的直接翻译描述结构体struct、枚举enum、属性attribute、命令command、事件event等存放位置src/app/zap-templates/zcl/data-model/chip该目录下现存 100 余个集群定义文件如access-control-cluster.xml、air-quality-cluster.xml、audio-control-cluster.xml等可直接作为新集群的参考模板。Cluster 实现实现分客户端与服务器两端客户端侧主要依赖代码生成codegen开发者只需编写“胶水层”调用代码。服务器侧通过 Ember 层生成代码和/或实现两个覆盖接口AttributeAccessInterface——拦截属性读写的接口CommandHandlerInterface——拦截命令处理的接口。实现文件位于src/app/clusters/your_cluster_name构建配置通过 src/app/chip_data_model.gni 接入——该构建文件利用 codegen 产出的数据自动填充集群列表在 ZAP 中勾选新集群后即可把对应代码编入固件。Device Type 定义设备类型同样以 XML 定义其一致性conformance要求主文件为 src/app/zap-templates/zcl/data-model/chip/matter-devices.xml。从源码可见matter-devices.xml每个deviceType元素包含设备名称、domain、typeName、profileId、deviceId、revision、class/scope以及强制/可选集群的include cluster... client... server.../列表ZAP 据此决定端点配置中该设备类型可挂载的集群。注意定义完成后还应使用 .matter 解析工具详见 docs/guides/matter_idl_tooling.md对照规范验证产出。ZAP、Ember 与 Overrides三层协作模型ZAPZigbee Cluster Configurator 的演进版的核心目标是让工具链理解新集群从而在任意设备上被 ZAP 配置所引用XML 定义 胶水代码。集群定义与 ZAP 的关系关于 ZAP 的入门介绍见 docs/zap_and_codegen/zap_intro.md。完成 XML 定义与注册步骤后可以用 zaptool 打开任意.zap文件来验证集群是否出现在工具中./scripts/tools/zap/run_zaptool.sh filename验证要点依次在 ZAP GUI 中检查设备类型列表打开端点Endpoint配置确认新设备类型出现在设备类型列表中。集群完整性XML 中的domain参数决定集群归属的分组确认集群包含全部预期属性、命令与事件。属性存储选项确认每个属性的存储方式RAM / External设置符合实现预期。集群实现Ember 层与 Overrides 的区别Ember 层是用于在设备上建立/访问端点、属性、命令等的底层机制构建时自动生成 Ember 函数签名与默认实现集群服务器代码实现初始化、命令、属性访问、事件生成等回调当 Interaction Model交互模型收到针对该集群的入站交互时会调用对应的 Ember 函数。**Overrides覆盖**与 Ember 层最大的差异在于生命周期Ember 层在编译时生成而 Overrides 在运行时安装对属性访问或命令处理而言Overrides 会先于Ember 层被调用通过 AttributeAccessInterface 与 CommandHandlerInterface 实现提供远高于 Ember 层的控制粒度但复杂度也更高关键优势可单元测试UNIT TESTABLE若 ZAP 中保留了相应配置两种机制都允许“回落fall through”到 Ember 层。集群服务器初始化流程入站消息从 Matter 核心流入集群初始化代码的完整流程如下EmberAfInitializeAttributes——针对 ZAP 中标记为RAM存储的全部属性在 Ember 属性存储中写入默认值MatterClusterPluginServerCallback——.h是生成文件.cpp实现在集群服务器代码中编写。利用它完成集群初始化并通过chip::app::AttributeAccessInterfaceRegistry::Instance().Register注册覆盖实例以在外部处理属性读写。集群服务器属性两种机制的选择存储方式ZAP 中设置Ember 层行为Override 要求RAM自动分配存储Ember 处理读写生成文件 Accessors.h 为每个属性生成 Get/Set 函数可选。若覆盖函数中不对该属性编码则回落至存储层。若总在覆盖函数里编码则纯属浪费 RAMExternal不分配任何存储不回落 Ember 存储必须注册访问覆盖access override否则属性无法工作通过 Override 读属性属性读取在 AttributeAccessInterface::Read() 中实现。源码注释明确了三种处理方式返回失败转换为 StatusIB 返回给客户端成功并编码数据数据返回客户端成功但不编码回落 Ember 属性存储/外部回调。典型实现CHIP_ERROR Read(const ConcreteReadAttributePath aPath, AttributeValueEncoder aEncoder) { // 解析 aPath 确定被请求的属性 switch (aPath.mAttributeId) { case SomeAttribute::Id: // 直接编码值 aEncoder.Encode(mSomeValue); break; } // 小心 List 属性 —— 必须使用 EncodeList 才能正确处理分块(chunking) return CHIP_NO_ERROR; }通过 Override 写属性写入与读取走同一条路径但落在 AttributeAccessInterface::Write() 中。源码注释同样给出三种行为返回失败转换为 StatusIB成功并解码视为成功写入成功但不解码回落 Ember 存储。属性处理器attribute handler需要自行负责约束检查constraint checking与属性持久化attribute persistence。属性持久化使用AttributeAccessInterface时需要自行管理需要持久化的属性可通过AttributePersistence基于AttributePersistenceProvider完成它为读写任意类型的值到默认 PersistenceProvider 提供了统一 API见 src/app/AttributePersistence.h单元测试时可将TestPersistentStorageDelegate与DefaultAttributePersistenceProvider组合使用。Ember 层读写在 Ember 层函数中编解码由 Ember 层自己处理。这对简单属性可行但复杂属性交互会很有挑战且Ember 层极难单元测试。Ember 层提供属性变更回调供应用处理void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath attributePath, uint8_t type, uint16_t size, uint8_t * value)注意使用该回调时要确保实现方式能够跨多个示例examples复用。集群服务器命令命令处理与属性一样存在 Ember 与 Override 两条路Override运行时注册InteractionModelEngine::RegisterCommandHandler实现CommandHandlerInterfaceEmber静态的emberAfClusterNameCommandNameCallback。命令分发流程如下图所示命令处理器编写要点CommandHandlerInterface见 CommandHandlerInterface.h可使用HandleCommand便捷函数自动标记为已处理否则需显式设置命令是否已处理——若未处理默认回落 Ember 层若命令完全由该接口处理在 src/app/common/templates/config-data.yaml 的CommandHandlerInterfaceOnlyClusters列表中登记关闭 Ember 命令回调生成。Ember 接口返回true表示命令已处理返回false会收到无效命令响应。两者通用必须在命令处理器中通过AddResponse或AddStatus处理对调用方的返回必须按规范进行约束检查并返回正确的状态码或响应体。事件与属性订阅属性变更上报Attribute change reporting走 Ember 存储层生成的属性 Get/Set 函数时自动处理使用AttributeAccessInterface时需要主动通知上报引擎属性已变更——调用MatterReportingAttributeChangeCallback。事件EventsEmber 层没有直接支持调用 EventLogging.h 中的LogEvent函数。调用方需持有 Matter 栈锁lock或将事件排入 Matter 事件队列queue后再调用LogEvent。动态端点的补充说明ZAP 配置在编译期是静态的也可以在运行时注册动态端点常见于桥接设备 bridge使用emberAfSetDynamicEndpoint如果为属性等数据自建了存储必须同时考虑动态端点与静态端点两种情况。向 SDK 添加新集群与设备类型完整操作清单以下步骤均建立在 Matter 规范已评审通过的前提下。第一步添加集群定义到 SDK在目录 src/app/zap-templates/zcl/data-model/chip 中以恰当的命名新建集群定义 XML 文件。将新集群定义引用登记到以下文件中.github/workflows/tests.yamlscripts/rules.matterlintsrc/app/zap-templates/zcl/zcl-with-test-extensions.jsonsrc/app/zap-templates/zcl/zcl.json若新集群是派生集群derived cluster需在基类集群定义中加入引用例如在mode-base-cluster.xml中加入集群代码否则运行regen_all.py时会抛出难以理解的异常struct nameModeOptionStruct cluster code0x0051/ !-- Laundry Washer Mode -- cluster codeYOUR NEW CLUSTER ID/ /structsrc/controller/python/matter/clusters/init.py在 src/controller/data_model/controller-clusters.zap 中启用新集群作用于 Python 与 Android 客户端需要借助 ZAP 工具编辑若本机未安装 ZAP可运行 zaptool 直接打开目标文件./scripts/tools/zap/run_zaptool.sh src/controller/data_model/controller-clusters.zapGUI 操作步骤在左侧面板选择Endpoint-1打开集群分组例如Appliances找到要启用的集群例如Dishwasher Control在 Enable 列的下拉框中为该集群选择ClientFile - Save保存配置然后关闭 GUI。在 src/app/zap_cluster_list.json 的ClientDirectories一节添加条目。更新 chip-tool重新生成全部 ZAP 生成代码./scripts/tools/zap_regen_all.py该脚本位于 scripts/tools/zap_regen_all.py重新构建 chip-tool即可获得新集群支持./scripts/examples/gn_build_example.sh examples/chip-tool SOME-PATH/第二步添加设备类型定义到 SDK将设备 XML 定义加入 matter-devices.xml实现所有应用通用的入站命令行为TLV 载荷到 C 结构体的解析由 XML 自动生成的代码完成生成产物见 zzz_generated/app-common/app-common/zap-generated其余功能需手动实现。重新生成自动代码的方法全部重新生成./scripts/tools/zap_regen_all.py仅重新生成 app-common 部分./scripts/tools/zap/generate.py -t src/app/common/templates/templates.json -o zzz_generated/app-common/app-common/zap-generated src/controller/data_model/controller-clusters.zap为所有非全局属性如CommandList、AttributeList等全局属性无需实现实现读写与存储操作。非 list/struct 类型属性的处理代码是通用生成的通常无需额外工作实现所有应用通用的属性规范要求例如特定范围range的强制约束、属性间交互的处理等。第三步实现代码与测试新集群实现放在 src/app/clusters编写规范见 docs/guides/writing_clusters.md测试放在 src/app/tests/suites实现示例集群服务器应用YAML 测试会针对该服务器运行两个可选方案在all-clusters-app中启用新集群并作为示例服务器可另附一个仅含相关集群的精简示例应用属锦上添花若集群有复杂的全局应用需求考虑独立示例应用可参考 door lock、bridge、TV、OTA 集群的做法。mode-base 派生集群接入 all-clusters-app 的完整清单假设新集群名为XYZMode派生自mode-base在 src/app/zap-templates/zcl/data-model/chip 中创建精简的xyz-mode-cluster.xml派生集群定义远小于普通集群参考 dishwasher-mode-cluster.xml。依据规范审视是否需要StartUpMode、OnMode属性确认已在 mode-base-cluster.xml 中登记集群代码struct nameModeTagStruct cluster code0xXXXXstruct nameModeOptionStruct cluster code0xXXXXbitmap nameFeature typebitmap32 cluster code0xXXXX在xyz-mode.h中定义模式/标签/tag参考 dishwasher-mode.h添加实例化模式的 stub参考 dishwasher-mode.cpp修改 examples/all-clusters-app/linux/main-common.cpp添加#include xyz-mode.h在ApplicationShutdown()中调用Clusters::XYZMode::Shutdown();在 examples/all-clusters-app/linux/BUILD.gn 的sources中加入xyz-mode.cpp修改 src/app/common/templates/config-data.yaml在EnumsNotUsedAsTypeInXML一节添加XYZMode::ModeTag该节的作用是避免代码误以为可安全使用kUnknownEnumValue派生集群尤其关键在CommandHandlerInterfaceOnlyClusters一节添加XYZ Mode条目该节用于声明完全由CommandHandlerInterface实现、无需生成命令分发的集群在 src/app/util/util.cpp 的// Cluster Init Functions...区域添加空实现void MatterXYZModePluginServerInitCallback() {}修改 src/app/zap-templates/zcl/zcl-with-test-extensions.json将xyz-mode-cluster.xml加入xmlFile列表在attributeAccessInterfaceAttributes中添加XYZ Mode: [ SupportedModes, CurrentMode, FeatureMap ]——这样 ZAP 就不会为这些属性生成处理代码修改 src/app/zap_cluster_list.json在ClientDirectories对象中添加XYZ_MODE_CLUSTER: []在ServerDirectories对象中添加XYZ_MODE_CLUSTER: [mode-base-server]。第四步测试计划与 CI 集成添加测试计划使用模板cluster_test_plan_template.adoc 所述流程对应的官方测试计划模板位于 CHIP-Specifications/chip-test-plans 仓库注意CHIP-Tool 参考客户端是从 XML 生成的无需手写客户端代码按需添加测试相对简单的测试在 src/app/tests/suites/certification 添加 YAML 测试并更新 src/app/tests/suites/certification/PICS.yaml较复杂的测试在 src/python_testing 添加 Python 测试接入 CIPython 测试加入 .github/workflows/tests.yaml需提供每个 Python 脚本的全部参数如端点 PIXITYAML 测试编辑 src/app/tests/suites/ciTests.json创建MyDevice章节列出该设备的所有 YAML 测试并将章节名加入collection列表然后执行./scripts/tools/zap_regen_all.py重新生成 ZAP 代码将设备类型规范加入测试计划工具device_type_requirements供 src/app/tests/suites/certification/Test_TC_DESC_2_1.yaml 使用将设备类型加入 Chefexamples/chef/devices。常见问题QAQ1测试活动可以用什么设备一种实现可以是测试框架 all-clusters 示例应用 Raspberry Pi两个独立实现需运行在目标硬件上可以是 mock-up、原型机等。Q2Chef 工具如何用于上述交付物官方答复为 TBD待定。Q3如何使用 ZAP 自动生成代码并提交结果搜索本文提到的zap_regen运行后把变更文件全部加入 git 提交。Q4旧的集群定义在哪里src/app/zap-templates/zcl/data-model/silabs/general.xml。Q5ZAP 文档在哪ZAP 官方仓库的 README外部链接按需访问。面向可测试性与可移植性的集群设计推荐的组合式实现Combined Implementation新集群设计推荐组合式实现模式以在保持完全可单元测试的同时优化 flash 与 RAM 占用组合式实现推荐集群的逻辑、数据存储与ServerClusterInterface实现集中在一个类中通常继承DefaultServerCluster。最小化样板代码与虚函数开销。模块化实现 /ClusterLogic不推荐把逻辑拆到独立的ClusterLogic类会带来明显的 flash 与 RAM 开销新集群不建议采用。平台相关代码分离按需若集群需要触发平台/硬件特定动作通过构造函数注入Delegate或 Driver接口。这既保证集群可移植也便于在测试中 mock delegate。简单的上报型集群如传感器读数往往完全不需要 delegate——应用直接调用 setter 即可。整体架构Interaction Model --(Read/Write/Invoke)-- MyCluster --(可选 Hardware/Platform actions)-- DelegateMyCluster实现ServerClusterInterfaceDelegate为可选虚线连接仅当需要平台动作时存在组合式实现中DefaultServerCluster提供数据版本Data version管理路径管理单端点/集群对未处理属性/命令的默认状态响应与ServerClusterContext的集成。组合式集群实现示例DataModel::ActionReturnStatus DiscoBallCluster::ReadAttribute(const DataModel::ReadAttributeRequest request, AttributeValueEncoder encoder) { switch (request.path.mAttributeId) { case Attributes::ClusterRevision::Id: return encoder.Encode(kRevision); case Attributes::Run::Id: return encoder.Encode(mRun); // ... } return Protocols::InteractionModel::Status::UnsupportedAttribute; }Delegate / Driver 接口Delegate 是可选组件仅在集群需要触发平台/硬件特定动作时使用例如驱动电机旋转、调节真实设备的亮度。简单的上报集群如传感器测量值可完全跳过 delegate由应用通过 setter 直接推送状态。使用 delegate 时通过构造函数注入以便在单元测试中 mock。集群在调用 delegate 之前仍需完成所有规范定义的校验如范围检查。class DiscoBallDelegate { public: virtual ~DiscoBallDelegate() default; virtual void OnRunChanged(bool run) 0; };用 ClusterTester 为 Code-Driven 集群编写单元测试单元测试应聚焦行为正确性与规范一致性。对于 code-driven 集群ClusterTester辅助类是强制要求mandatory的测试组件。ClusterTester 是什么ClusterTester是位于 src/app/server-cluster/testing/ClusterTester.h 的 C 辅助类为实现了ServerClusterInterface的 Matter 集群简化单元测试。其价值体现在自动 TLV 处理写入/命令时自动把 C 结构编码为 TLV读取/响应时自动把 TLV 解码为 C 结构内存安全对于返回视图view的属性如CharSpan、ListClusterTester持有底层 TLV 数据的所有权测试作用域内可安全检视数据而无悬垂指针之忧类型安全利用生成的数据模型类型如Attributes::MyAttr::TypeInfo确保参数与规范一致。从源码看ClusterTester.h其核心 API 包括ReadAttribute、WriteAttribute含 list 专用重载支持指定写入模式与Invoke。基础用法无 Fabric 上下文的集群对于不需要 fabric 上下文fabric context的简单集群如Boolean State直接包装集群实例即可。#include app/server-cluster/testing/ClusterTester.h #include app/clusters/boolean-state-server/BooleanStateCluster.h class TestBooleanStateCluster : public ::testing::Test { // ... (Setup memory and context) ... BooleanStateCluster booleanState{kRootEndpointId}; // 用集群实例初始化 tester chip::Testing::ClusterTester tester{booleanState}; void SetUp() override { booleanState.Startup(testContext.Get()); } };读取属性TEST_F(TestBooleanStateCluster, ReadAttributeTest) { // 1. 读取简单整型属性 uint16_t revision{}; ASSERT_EQ(tester.ReadAttribute(Globals::Attributes::ClusterRevision::Id, revision), CHIP_NO_ERROR); // 2. 读取 bitmap uint32_t features{}; ASSERT_EQ(tester.ReadAttribute(FeatureMap::Id, features), CHIP_NO_ERROR); // 3. 读取布尔值 bool stateValue{}; ASSERT_EQ(tester.ReadAttribute(StateValue::Id, stateValue), CHIP_NO_ERROR); }高级用法Fabric 作用域集群涉及访问控制Access Control或 fabric 作用域的复杂集群如Group Key ManagementClusterTester与FabricTestFixture集成。不必把 fixture 传入 tester 构造器但在执行操作前必须在 tester 上设置 active fabric index。class TestGroupKeyManagementCluster : public ::testing::Test { TestServerClusterContext mTestContext; FabricTestFixture fabricHelper{ mTestContext.StorageDelegate() }; GroupKeyManagementCluster mCluster{ fabricHelper.GetFabricTable() }; // 仅用集群初始化 tester ClusterTester tester{ mCluster}; void SetUp() override { // ... (Startup cluster) ... // 初始化测试 fabric fabricHelper.SetUpTestFabric(kTestFabricIndex); // 重要为 tester 设置 fabric index。 // 之后所有的写入/命令都会被当作来自该 fabric。 tester.SetFabricIndex(kTestFabricIndex); } };写入复杂类型属性StructTester 自动处理 Struct 等复杂类型List 除外TEST_F(TestCameraAVStreamManagementCluster, TestReadWriteViewport) { ... // 写入一个合法的新值 Attributes::Viewport::TypeInfo::Type newViewport { 0, 0, 1280, 720 }; EXPECT_EQ(mClusterTester.WriteAttribute(Attributes::Viewport::Id, newViewport), CHIP_NO_ERROR); }写入 List 属性list 属性存在两种主流写入模式集群服务器通常都支持因此测试应通过ListWritingPattern遍历两种模式以面向未来兼容TEST_F(TestUserLabelCluster, WriteValidLabelListTest) { // 每种 List 写入模式各跑一遍 for (ListWritingPattern listWritingPattern : { ListWritingPattern::ReplaceAll, ListWritingPattern::ClearAllThenAppendItems }) { ClusterTester tester(userLabel); Structs::LabelStruct::Type labels[] { { .label room_span, .value bedroom 2_span }, { .label orientation_span, .value North_span }, }; // 包进 DataModel::List auto listToWrite DataModel::List(labels); // 写入属性。 // 对 fabric 作用域属性tester 自动处理 EncodeForWrite ASSERT_EQ(tester.WriteAttribute(LabelList::Id, listToWrite, listWritingPattern), CHIP_NO_ERROR); } }调用命令使用Invoke方法与生成的 Command Request 结构体交互TEST_F(TestGroupKeyManagementCluster, TestKeySetWriteCommand) { // 1. 构造 Request 结构体 GroupKeyManagement::Commands::KeySetWrite::Type requestData; requestData.groupKeySet.groupKeySetID kTestKeySetId; requestData.groupKeySet.groupKeySecurityPolicy GroupKeyManagement::GroupKeySecurityPolicyEnum::kTrustFirst; requestData.groupKeySet.epochStartTime0 kStartTime; // ... 填充其余字段 ... // 2. 调用命令 // CommandId 由请求类型自动推导 // 也可以显式传入: tester.Invoke(CommandId, request) auto result tester.Invoke(requestData); // 3. 校验结果 EXPECT_TRUE(result.IsSuccess()); }关键行为与测试场景完整类定义见 ClusterTester.h 头文件以下为简化测试的若干内部行为读操作的内存管理ReadAttribute自动管理底层 TLV 数据。含视图/列表的类型CharSpan、ByteSpan、DecodableList会被 tester 在内部缓冲该数据在ClusterTester实例生命周期内持续有效可安全迭代列表或检视 span。写入的 Fabric 作用域处理WriteAttribute通过 C 内省introspection检测结构体是否为 fabric 作用域——若是则自动使用EncodeForWrite否则使用标准Encode同时自动应用与SetFabricIndex()对应 fabric 索引的访问控制主体描述符subject descriptor。Invoke 的结果统一返回InvokeResultResponseType同时携带状态与解码后的响应载荷若命令返回数据。IsSuccess()在状态为成功且对返回数据的命令响应存在时返回 trueGetStatusCode()返回std::optionalClusterStatusCode可省去ASSERT_TRUE(status.has_value())直接以单个EXPECT_EQ()校验状态码该 helper 面向同步执行的单元测试设计。验证副作用事件与上报验证事件生成// 1. 执行动作如写属性 tester.WriteAttribute(MyAttribute::Id, newValue); // 2. 从队列弹出下一个事件 auto event tester.GetNextGeneratedEvent(); ASSERT_TRUE(event.has_value()); // 3. 用规范生成的 decodable 类型解码事件载荷 MyCluster::Events::MyEvent::DecodableType eventData; ASSERT_EQ(event-GetEventData(eventData), CHIP_NO_ERROR); // ... 校验 eventData 字段 ...验证脏属性Dirty Attributes// 1. 执行动作 tester.Invoke(myCommand); // 2. 检查特定属性是否被标记为 dirty EXPECT_TRUE(tester.IsAttributeDirty(MyAttribute::Id)); // 或者按需检视完整 dirty path 列表 auto dirtyList tester.GetDirtyList();推荐测试清单针对 code-driven 集群至少覆盖以下测试类别初始化Startup后初始属性值正确范围检查setter 与命令处理器对越界值返回错误如ConstraintError边界情况最小值、最大值、可空nullable属性的 null 值行为规范一致性所有规范定义的错误条件均正确处理副作用状态变更时的事件生成与脏属性标记Delegate 交互正确调用 delegate、正确处理 delegate 上报的错误Fabric 隔离fabric 作用域属性与命令的正确行为。测试既有集群的两个选项选项 1重构Refactor推荐将集群重构为使用DefaultServerCluster与ClusterTester长期可维护性最佳选项 2接口边界测试Test at Interface Boundary实例化集群通过ServerClusterInterface边界用ClusterTester交互。适合暂时无法完整重构的既有实现。结语至此一条完整的新集群/设备类型开发流水线已经打通从src/app/zap-templates/zcl/data-model/chip/下的 XML 规范翻译到 ZAP/Ember/codegen 三层的注册与接线再到AttributeAccessInterface/CommandHandlerInterface覆盖机制的精细控制最后以DefaultServerClusterClusterTester的组合交付可单元测试、可移植、可认证的服务器实现。开发者可按 docs/cluster_and_device_type_dev/how_to_add_new_dts_and_clusters.md 的清单逐项落地并以 docs/cluster_and_device_type_dev/unit_testing_clusters.md 与 docs/cluster_and_device_type_dev/cluster_tester.md 作为测试环节的规范依据最终将新功能安全地带入 Matter 生态。【免费下载链接】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),仅供参考