From d2d4701eb3c78a3ad9ae0575f0a1d67e80507115 Mon Sep 17 00:00:00 2001 From: Cliff Chung <116232729+cliffamzn@users.noreply.github.com> Date: Thu, 20 Jul 2023 12:02:01 -0700 Subject: [PATCH] Add ReplacementProductList to Resource Monitoring Cluster (#28095) * Add ReplacementProductList to Resource Monitoring Cluster This adds the implementation to fetch the replacement product list from the aliased resource-monitoring-cluster. It adds support for Hepa and Activated Carbon filter examples. Closes out issues #27802, #27801, #27577 ### Testing I tested this using the all-clusters-app and the resource-monitoring-example-app ``` >>>> hepafiltermonitoring read replacement-product-list 0x1 0x1 DataVersion = 0xd31d0b60, AttributePathIB = { Endpoint = 0x1, Cluster = 0x71, Attribute = 0x0000_0005, } Data = [ { 0x0 = 0, 0x1 = "upc12xhepaxx" (13 chars), }, { 0x0 = 1, 0x1 = "gtin8xhe" (9 chars), }, { 0x0 = 2, 0x1 = "ean13xhepaxxx" (14 chars), }, ], >>>> activatedcarbonfiltermonitoring read replacement-product-list 0x1 0x1 DataVersion = 0xfd145260, AttributePathIB = { Endpoint = 0x1, Cluster = 0x72, Attribute = 0x0000_0005, } Data = [ { 0x0 = 0, 0x1 = "upc12xcarbon" (13 chars), }, { 0x0 = 1, 0x1 = "gtin8xca" (9 chars), }, { 0x0 = 2, 0x1 = "ean13xacarbon" (14 chars), }, ], ``` * Addressing @tobiasgraf's comments * Addressing @tcarmelveilleux's comments and restyled * Simplifying example app and adding support for resource monitor list in the all clusters app * Addressing @tcarmelveilleux's suggestions * Restyled by whitespace * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../all-clusters-app.matter | 6 + .../all-clusters-common/all-clusters-app.zap | 38 +++- .../include/resource-monitoring-instances.h | 21 ++ .../src/resource-monitoring-instances.cpp | 41 +++- .../resource-monitoring-app/linux/BUILD.gn | 3 +- .../linux/src/main.cpp | 7 +- .../StaticReplacementProductListManager.h | 57 ++++++ .../resource-monitoring-app.matter | 6 + .../resource-monitoring-app.zap | 32 +++ .../StaticReplacementProductListManager.cpp | 38 ++++ .../ActivatedCarbonFilterMonitoring.cpp | 25 ++- .../src/instances/HepafilterMonitoring.cpp | 23 ++- src/app/chip_data_model.gni | 1 + .../fan-control-server/fan-control-server.cpp | 2 +- .../replacement-product-list-manager.h | 54 ++++++ .../resource-monitoring-cluster-objects.cpp | 16 ++ .../resource-monitoring-cluster-objects.h | 55 +++++- .../resource-monitoring-server.cpp | 40 ++++ .../resource-monitoring-server.h | 9 + src/app/tests/suites/certification/PICS.yaml | 18 ++ .../certification/Test_TC_ACFREMON_1_1.yaml | 15 +- .../certification/Test_TC_ACFREMON_2_1.yaml | 17 ++ .../certification/Test_TC_HEPAFREMON_1_1.yaml | 15 +- .../certification/Test_TC_HEPAFREMON_2_1.yaml | 17 ++ .../tests/suites/certification/ci-pics-values | 8 +- .../chip/resource-monitoring-cluster.xml | 1 + .../zcl/zcl-with-test-extensions.json | 2 + src/app/zap-templates/zcl/zcl.json | 2 + .../data_model/controller-clusters.matter | 2 + .../python/chip/clusters/Objects.py | 2 + .../app-common/zap-generated/cluster-enums.h | 10 +- .../chip-tool/zap-generated/test/Commands.h | 182 +++++++++++++----- 32 files changed, 691 insertions(+), 74 deletions(-) create mode 100644 examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h create mode 100644 examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp create mode 100644 src/app/clusters/resource-monitoring-server/replacement-product-list-manager.h diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 638d709919bb37..cf9ea43577a32d 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -2752,6 +2752,7 @@ server cluster HepaFilterMonitoring = 113 { bitmap Feature : BITMAP32 { kCondition = 0x1; kWarning = 0x2; + kReplacementProductList = 0x3; } struct ReplacementProductStruct { @@ -2764,6 +2765,7 @@ server cluster HepaFilterMonitoring = 113 { readonly attribute ChangeIndicationEnum changeIndication = 2; readonly attribute boolean inPlaceIndicator = 3; attribute nullable epoch_s lastChangedTime = 4; + readonly attribute ReplacementProductStruct replacementProductList[] = 5; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2798,6 +2800,7 @@ server cluster ActivatedCarbonFilterMonitoring = 114 { bitmap Feature : BITMAP32 { kCondition = 0x1; kWarning = 0x2; + kReplacementProductList = 0x3; } struct ReplacementProductStruct { @@ -2810,6 +2813,7 @@ server cluster ActivatedCarbonFilterMonitoring = 114 { readonly attribute ChangeIndicationEnum changeIndication = 2; readonly attribute boolean inPlaceIndicator = 3; attribute nullable epoch_s lastChangedTime = 4; + readonly attribute ReplacementProductStruct replacementProductList[] = 5; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -6318,6 +6322,7 @@ endpoint 1 { callback attribute changeIndication default = 0; callback attribute inPlaceIndicator; callback attribute lastChangedTime; + callback attribute replacementProductList; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; @@ -6332,6 +6337,7 @@ endpoint 1 { callback attribute changeIndication default = 0; callback attribute inPlaceIndicator; callback attribute lastChangedTime; + callback attribute replacementProductList; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index f3629559472674..1fb87b6b560309 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -15014,7 +15014,23 @@ "side": "server", "type": "epoch_s", "included": 1, - "storageOption": "RAM", + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ReplacementProductList", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, @@ -15252,7 +15268,23 @@ "side": "server", "type": "epoch_s", "included": 1, - "storageOption": "RAM", + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ReplacementProductList", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, @@ -31659,4 +31691,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/examples/all-clusters-app/all-clusters-common/include/resource-monitoring-instances.h b/examples/all-clusters-app/all-clusters-common/include/resource-monitoring-instances.h index ecc3603d105d21..c12a686735abba 100644 --- a/examples/all-clusters-app/all-clusters-common/include/resource-monitoring-instances.h +++ b/examples/all-clusters-app/all-clusters-common/include/resource-monitoring-instances.h @@ -54,3 +54,24 @@ class HepaFilterMonitoringInstance : public chip::app::Clusters::ResourceMonitor Instance(aEndpointId, chip::app::Clusters::HepaFilterMonitoring::Id, aFeature, aDegradationDirection, aResetConditionCommandSupported){}; }; + +class StaticReplacementProductListManager : public chip::app::Clusters::ResourceMonitoring::ReplacementProductListManager +{ +public: + uint8_t Size() override { return mReplacementProductListSize; }; + + CHIP_ERROR Next(chip::app::Clusters::ResourceMonitoring::Attributes::ReplacementProductStruct::Type & item) override; + + ~StaticReplacementProductListManager() {} + StaticReplacementProductListManager( + chip::app::Clusters::ResourceMonitoring::Attributes::ReplacementProductStruct::Type * aReplacementProductsList, + uint8_t aReplacementProductListSize) + { + mReplacementProductsList = aReplacementProductsList; + mReplacementProductListSize = aReplacementProductListSize; + } + +private: + chip::app::Clusters::ResourceMonitoring::Attributes::ReplacementProductStruct::Type * mReplacementProductsList; + uint8_t mReplacementProductListSize; +}; diff --git a/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-instances.cpp b/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-instances.cpp index 00f681a09e416e..891a7e85450b48 100644 --- a/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-instances.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-instances.cpp @@ -28,17 +28,34 @@ using namespace chip::app::Clusters::ResourceMonitoring; using chip::Protocols::InteractionModel::Status; constexpr std::bitset<4> gHepaFilterFeatureMap{ static_cast(Feature::kCondition) | - static_cast(Feature::kWarning) }; + static_cast(Feature::kWarning) | + static_cast(Feature::kReplacementProductList) }; constexpr std::bitset<4> gActivatedCarbonFeatureMap{ static_cast(Feature::kCondition) | - static_cast(Feature::kWarning) }; + static_cast(Feature::kWarning) | + static_cast(Feature::kReplacementProductList) }; -static HepaFilterMonitoringInstance * gHepafilterInstance = nullptr; +static HepaFilterMonitoringInstance * gHepaFilterInstance = nullptr; static ActivatedCarbonFilterMonitoringInstance * gActivatedCarbonFilterInstance = nullptr; +static ResourceMonitoring::Attributes::ReplacementProductStruct::Type sReplacementProductsList[] = { + { .productIdentifierType = ProductIdentifierTypeEnum::kUpc, + .productIdentifierValue = CharSpan::fromCharString("111112222233") }, + { .productIdentifierType = ProductIdentifierTypeEnum::kGtin8, .productIdentifierValue = CharSpan::fromCharString("gtin8xxx") }, + { .productIdentifierType = ProductIdentifierTypeEnum::kEan, + .productIdentifierValue = CharSpan::fromCharString("4444455555666") }, + { .productIdentifierType = ProductIdentifierTypeEnum::kGtin14, + .productIdentifierValue = CharSpan::fromCharString("gtin14xxxxxxxx") }, + { .productIdentifierType = ProductIdentifierTypeEnum::kOem, + .productIdentifierValue = CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx") }, +}; +StaticReplacementProductListManager sReplacementProductListManager(&sReplacementProductsList[0], + ArraySize(sReplacementProductsList)); + //-- Activated Carbon Filter Monitoring Instance methods CHIP_ERROR ActivatedCarbonFilterMonitoringInstance::AppInit() { ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::Init()"); + SetReplacementProductListManagerInstance(&sReplacementProductListManager); return CHIP_NO_ERROR; } @@ -58,6 +75,7 @@ Status ActivatedCarbonFilterMonitoringInstance::PostResetCondition() CHIP_ERROR HepaFilterMonitoringInstance::AppInit() { ChipLogDetail(Zcl, "HepaFilterMonitoringInstance::Init()"); + SetReplacementProductListManagerInstance(&sReplacementProductListManager); return CHIP_NO_ERROR; } @@ -82,8 +100,19 @@ void emberAfActivatedCarbonFilterMonitoringClusterInitCallback(chip::EndpointId } void emberAfHepaFilterMonitoringClusterInitCallback(chip::EndpointId endpoint) { - VerifyOrDie(gActivatedCarbonFilterInstance == nullptr); - gHepafilterInstance = new HepaFilterMonitoringInstance(endpoint, static_cast(gHepaFilterFeatureMap.to_ulong()), + gHepaFilterInstance = new HepaFilterMonitoringInstance(endpoint, static_cast(gHepaFilterFeatureMap.to_ulong()), DegradationDirectionEnum::kDown, true); - gHepafilterInstance->Init(); + gHepaFilterInstance->Init(); +} + +CHIP_ERROR StaticReplacementProductListManager::Next(Attributes::ReplacementProductStruct::Type & item) +{ + if (mIndex < mReplacementProductListSize) + { + item = mReplacementProductsList[mIndex]; + mIndex++; + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; } diff --git a/examples/resource-monitoring-app/linux/BUILD.gn b/examples/resource-monitoring-app/linux/BUILD.gn index 98301831b1b4a4..c5e769a39ce4f7 100644 --- a/examples/resource-monitoring-app/linux/BUILD.gn +++ b/examples/resource-monitoring-app/linux/BUILD.gn @@ -30,8 +30,9 @@ config("includes") { executable("chip-resource-monitoring-app") { sources = [ + "${chip_root}/examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp", "${chip_root}/examples/resource-monitoring-app/resource-monitoring-common/src/instances/ActivatedCarbonFilterMonitoring.cpp", - "${chip_root}/examples/resource-monitoring-app/resource-monitoring-common/src/instances/HepafilterMonitoring.cpp", + "${chip_root}/examples/resource-monitoring-app/resource-monitoring-common/src/instances/HepaFilterMonitoring.cpp", "include/CHIPProjectAppConfig.h", "src/main.cpp", ] diff --git a/examples/resource-monitoring-app/linux/src/main.cpp b/examples/resource-monitoring-app/linux/src/main.cpp index 04e05aa16c2497..6e515b7ea5845c 100644 --- a/examples/resource-monitoring-app/linux/src/main.cpp +++ b/examples/resource-monitoring-app/linux/src/main.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -29,9 +30,11 @@ using namespace chip::app::Clusters; using namespace chip::app::Clusters::ResourceMonitoring; constexpr std::bitset<4> gHepaFilterFeatureMap{ static_cast(Feature::kCondition) | - static_cast(Feature::kWarning) }; + static_cast(Feature::kWarning) | + static_cast(Feature::kReplacementProductList) }; constexpr std::bitset<4> gActivatedCarbonFeatureMap{ static_cast(Feature::kCondition) | - static_cast(Feature::kWarning) }; + static_cast(Feature::kWarning) | + static_cast(Feature::kReplacementProductList) }; static HepaFilterMonitoringInstance gHepaFilterInstance(0x1, static_cast(gHepaFilterFeatureMap.to_ulong()), Clusters::ResourceMonitoring::DegradationDirectionEnum::kDown, true); diff --git a/examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h b/examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h new file mode 100644 index 00000000000000..cb83148302f8b6 --- /dev/null +++ b/examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace ResourceMonitoring { + +/** + * This implementation statically defines the options. + */ + +class StaticReplacementProductListManager : public ReplacementProductListManager +{ +public: + uint8_t Size() override { return mReplacementProductListSize; }; + + CHIP_ERROR Next(Attributes::ReplacementProductStruct::Type & item) override; + + ~StaticReplacementProductListManager() {} + StaticReplacementProductListManager(Attributes::ReplacementProductStruct::Type * aReplacementProductsList, + uint8_t aReplacementProductListSize) + { + mReplacementProductsList = aReplacementProductsList; + mReplacementProductListSize = aReplacementProductListSize; + } + +private: + Attributes::ReplacementProductStruct::Type * mReplacementProductsList; + uint8_t mReplacementProductListSize; +}; + +} // namespace ResourceMonitoring +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.matter b/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.matter index 33710cbe1c87ed..70272ea93e4dbe 100644 --- a/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.matter +++ b/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.matter @@ -1519,6 +1519,7 @@ server cluster HepaFilterMonitoring = 113 { bitmap Feature : BITMAP32 { kCondition = 0x1; kWarning = 0x2; + kReplacementProductList = 0x3; } struct ReplacementProductStruct { @@ -1531,6 +1532,7 @@ server cluster HepaFilterMonitoring = 113 { readonly attribute ChangeIndicationEnum changeIndication = 2; readonly attribute boolean inPlaceIndicator = 3; attribute nullable epoch_s lastChangedTime = 4; + readonly attribute ReplacementProductStruct replacementProductList[] = 5; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1565,6 +1567,7 @@ server cluster ActivatedCarbonFilterMonitoring = 114 { bitmap Feature : BITMAP32 { kCondition = 0x1; kWarning = 0x2; + kReplacementProductList = 0x3; } struct ReplacementProductStruct { @@ -1577,6 +1580,7 @@ server cluster ActivatedCarbonFilterMonitoring = 114 { readonly attribute ChangeIndicationEnum changeIndication = 2; readonly attribute boolean inPlaceIndicator = 3; attribute nullable epoch_s lastChangedTime = 4; + readonly attribute ReplacementProductStruct replacementProductList[] = 5; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1984,6 +1988,7 @@ endpoint 1 { callback attribute changeIndication default = 0; callback attribute inPlaceIndicator; callback attribute lastChangedTime; + callback attribute replacementProductList; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; @@ -1998,6 +2003,7 @@ endpoint 1 { callback attribute changeIndication default = 0; callback attribute inPlaceIndicator; callback attribute lastChangedTime; + callback attribute replacementProductList; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.zap b/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.zap index 28fa23e068c377..fc6b03ba7dcd40 100644 --- a/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.zap +++ b/examples/resource-monitoring-app/resource-monitoring-common/resource-monitoring-app.zap @@ -6241,6 +6241,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "ReplacementProductList", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, @@ -6479,6 +6495,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "ReplacementProductList", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, diff --git a/examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp b/examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp new file mode 100644 index 00000000000000..4c657ff05cc488 --- /dev/null +++ b/examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp @@ -0,0 +1,38 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::ResourceMonitoring; + +CHIP_ERROR StaticReplacementProductListManager::Next(Attributes::ReplacementProductStruct::Type & item) +{ + if (mIndex < mReplacementProductListSize) + { + item = mReplacementProductsList[mIndex]; + mIndex++; + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; +} diff --git a/examples/resource-monitoring-app/resource-monitoring-common/src/instances/ActivatedCarbonFilterMonitoring.cpp b/examples/resource-monitoring-app/resource-monitoring-common/src/instances/ActivatedCarbonFilterMonitoring.cpp index f22c9590e1c8c3..778bb9d6e22dd0 100644 --- a/examples/resource-monitoring-app/resource-monitoring-common/src/instances/ActivatedCarbonFilterMonitoring.cpp +++ b/examples/resource-monitoring-app/resource-monitoring-common/src/instances/ActivatedCarbonFilterMonitoring.cpp @@ -16,26 +16,47 @@ * limitations under the License. */ +#include #include #include #include #include +#include #include #include #include #include #include -#include +using namespace chip; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ActivatedCarbonFilterMonitoring; using namespace chip::app::Clusters::ResourceMonitoring; using chip::Protocols::InteractionModel::Status; -//-- Hepa filter Monitoring Instance methods +static ResourceMonitoring::Attributes::ReplacementProductStruct::Type sActivatedCarbonFilterReplacementProductsList[] = { + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kUpc, + .productIdentifierValue = CharSpan::fromCharString("111112222233") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8, + .productIdentifierValue = CharSpan::fromCharString("gtin8xca") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kEan, + .productIdentifierValue = CharSpan::fromCharString("4444455555666") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14, + .productIdentifierValue = CharSpan::fromCharString("gtin14xcarbonx") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kOem, + .productIdentifierValue = CharSpan::fromCharString("oem20xcarbonxxxxxxxx") }, +}; +StaticReplacementProductListManager + sActivatedCarbonFilterReplacementProductListManager(&sActivatedCarbonFilterReplacementProductsList[0], + ArraySize(sActivatedCarbonFilterReplacementProductsList)); + +//-- Activated carbon filter Monitoring Instance methods CHIP_ERROR ActivatedCarbonFilterMonitoringInstance::AppInit() { ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::Init()"); + + SetReplacementProductListManagerInstance(&sActivatedCarbonFilterReplacementProductListManager); + return CHIP_NO_ERROR; } diff --git a/examples/resource-monitoring-app/resource-monitoring-common/src/instances/HepafilterMonitoring.cpp b/examples/resource-monitoring-app/resource-monitoring-common/src/instances/HepafilterMonitoring.cpp index ae93411a38b902..c0ee95ed7c02ff 100644 --- a/examples/resource-monitoring-app/resource-monitoring-common/src/instances/HepafilterMonitoring.cpp +++ b/examples/resource-monitoring-app/resource-monitoring-common/src/instances/HepafilterMonitoring.cpp @@ -16,26 +16,45 @@ * limitations under the License. */ +#include #include #include #include #include +#include #include #include #include #include #include -#include +using namespace chip; using namespace chip::app::Clusters; -using namespace chip::app::Clusters::HepaFilterMonitoring; using namespace chip::app::Clusters::ResourceMonitoring; using chip::Protocols::InteractionModel::Status; +static ResourceMonitoring::Attributes::ReplacementProductStruct::Type sHepaFilterReplacementProductsList[] = { + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kUpc, + .productIdentifierValue = CharSpan::fromCharString("111112222233") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8, + .productIdentifierValue = CharSpan::fromCharString("gtin8xhe") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kEan, + .productIdentifierValue = CharSpan::fromCharString("4444455555666") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14, + .productIdentifierValue = CharSpan::fromCharString("gtin14xhepaxxx") }, + { .productIdentifierType = ResourceMonitoring::ProductIdentifierTypeEnum::kOem, + .productIdentifierValue = CharSpan::fromCharString("oem20xhepaxxxxxxxxxx") }, +}; +StaticReplacementProductListManager sHepaFilterReplacementProductListManager(&sHepaFilterReplacementProductsList[0], + ArraySize(sHepaFilterReplacementProductsList)); + //-- Hepa filter Monitoring instance methods CHIP_ERROR HepaFilterMonitoringInstance::AppInit() { ChipLogDetail(Zcl, "HepaFilterMonitoringInstance::Init()"); + + SetReplacementProductListManagerInstance(&sHepaFilterReplacementProductListManager); + return CHIP_NO_ERROR; } diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 0f4dd4fe183d91..51bee460f09346 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -271,6 +271,7 @@ template("chip_data_model") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", "${_app_root}/clusters/${cluster}/${cluster}.h", + "${_app_root}/clusters/${cluster}/replacement-product-list-manager.h", "${_app_root}/clusters/${cluster}/resource-monitoring-cluster-objects.cpp", "${_app_root}/clusters/${cluster}/resource-monitoring-cluster-objects.h", ] diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index ca50fb06662283..9437d821c0631b 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -68,7 +68,7 @@ Delegate * GetDelegate(EndpointId endpoint) void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) { uint16_t ep = - emberAfGetClusterServerEndpointIndex(endpoint, FanControl::Id, EMBER_AF_APPLICATION_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT); + emberAfGetClusterServerEndpointIndex(endpoint, FanControl::Id, EMBER_AF_FAN_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); // if endpoint is found if (ep < kFanControlDelegateTableSize) { diff --git a/src/app/clusters/resource-monitoring-server/replacement-product-list-manager.h b/src/app/clusters/resource-monitoring-server/replacement-product-list-manager.h new file mode 100644 index 00000000000000..b252597306c21a --- /dev/null +++ b/src/app/clusters/resource-monitoring-server/replacement-product-list-manager.h @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace ResourceMonitoring { + +/** + * Interface to help manage the replacement product list in the Resource Monitoring Cluster. + */ +class ReplacementProductListManager +{ +public: + ReplacementProductListManager() {} + virtual ~ReplacementProductListManager() = default; + + void Reset() { mIndex = 0; } + + // Returns total size of Replacement Products List. + virtual uint8_t Size() = 0; + + virtual CHIP_ERROR Next(Attributes::ReplacementProductStruct::Type & item) = 0; + +protected: + uint8_t mIndex; +}; + +} // namespace ResourceMonitoring +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.cpp b/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.cpp index 34388cba90c4d9..932c95ce3a77ee 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.cpp +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.cpp @@ -44,6 +44,22 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } // namespace ResetCondition. } // namespace Commands +namespace Attributes { +namespace ReplacementProductStruct { + +CHIP_ERROR Type::Encode(TLV::TLVWriter & writer, TLV::Tag tag) const +{ + TLV::TLVType outer; + ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer)); + ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(Fields::kProductIdentifierType), productIdentifierType)); + ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(Fields::kProductIdentifierValue), productIdentifierValue)); + ReturnErrorOnFailure(writer.EndContainer(outer)); + return CHIP_NO_ERROR; +} + +} // namespace ReplacementProductStruct +} // namespace Attributes + } // namespace ResourceMonitoring } // namespace Clusters } // namespace app diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h b/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h index e6fdf35dfce6ba..995f42b6dc4d7c 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h @@ -29,7 +29,7 @@ namespace app { namespace Clusters { namespace ResourceMonitoring { -static constexpr std::array AliasedClusters = { 0x0071, 0x0072 }; +static constexpr std::array AliasedClusters = { HepaFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Id }; // Enum for ChangeIndicationEnum enum class ChangeIndicationEnum : uint8_t @@ -59,9 +59,19 @@ enum class DegradationDirectionEnum : uint8_t // Bitmap for Feature enum class Feature : uint32_t { - kCondition = 0x1, - kWarning = 0x2, - // TODO(#27577): add server support for REP feature (ReplacementProductList) + kCondition = 0x1, + kWarning = 0x2, + kReplacementProductList = 0x3 +}; + +// Enum for ProductIdentifierTypeEnum +enum class ProductIdentifierTypeEnum : uint8_t +{ + kUpc = 0x00, + kGtin8 = 0x01, + kEan = 0x02, + kGtin14 = 0x03, + kOem = 0x04 }; namespace Attributes { @@ -131,6 +141,43 @@ struct TypeInfo }; } // namespace LastChangedTime +namespace ReplacementProductStruct { +enum class Fields : uint8_t +{ + kProductIdentifierType = 0, + kProductIdentifierValue = 1, +}; + +struct Type +{ +public: + ProductIdentifierTypeEnum productIdentifierType = static_cast(0); + chip::CharSpan productIdentifierValue; + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = false; + + CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const; +}; + +using DecodableType = Type; + +} // namespace ReplacementProductStruct + +namespace ReplacementProductList { +static constexpr AttributeId Id = 0x00000005; +struct TypeInfo +{ + using Type = chip::app::DataModel::List; + using DecodableType = chip::app::DataModel::DecodableList; + using DecodableArgType = const chip::app::DataModel::DecodableList &; + + static constexpr AttributeId GetAttributeId() { return Attributes::ReplacementProductList::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace ReplacementProductList + namespace GeneratedCommandList { static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id; struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp index 17a19fa89f2e08..2cbcb433a23f42 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp @@ -123,6 +123,11 @@ chip::Protocols::InteractionModel::Status Instance::UpdateLastChangedTime(DataMo return Protocols::InteractionModel::Status::Success; } +void Instance::SetReplacementProductListManagerInstance(ReplacementProductListManager * aReplacementProductListManager) +{ + mReplacementProductListManager = aReplacementProductListManager; +} + uint8_t Instance::GetCondition() const { return mCondition; @@ -147,6 +152,11 @@ DataModel::Nullable Instance::GetLastChangedTime() const return mLastChangedTime; } +ReplacementProductListManager * Instance::GetReplacementProductListManagerInstance() +{ + return mReplacementProductListManager; +} + Status Instance::OnResetCondition() { ChipLogDetail(Zcl, "ResourceMonitoringServer::OnResetCondition()"); @@ -232,6 +242,32 @@ CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & clust return CHIP_NO_ERROR; } +CHIP_ERROR Instance::ReadReplacableProductList(AttributeValueEncoder & aEncoder) +{ + CHIP_ERROR err; + if (Instance::HasFeature(ResourceMonitoring::Feature::kReplacementProductList)) + { + ReplacementProductListManager * productListManagerInstance = Instance::GetReplacementProductListManagerInstance(); + if (nullptr == productListManagerInstance) + { + aEncoder.EncodeEmptyList(); + return CHIP_NO_ERROR; + } + + productListManagerInstance->Reset(); + + err = aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR { + Attributes::ReplacementProductStruct::Type replacementProductStruct; + while (productListManagerInstance->Next(replacementProductStruct) == CHIP_NO_ERROR) + { + ReturnErrorOnFailure(encoder.Encode(replacementProductStruct)); + } + return CHIP_NO_ERROR; + }); + } + return CHIP_NO_ERROR; +} + // Implements the read functionality for non-standard attributes. CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) { @@ -261,6 +297,10 @@ CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValu ReturnErrorOnFailure(aEncoder.Encode(mLastChangedTime)); break; } + case Attributes::ReplacementProductList::Id: { + return ReadReplacableProductList(aEncoder); + break; + } } return CHIP_NO_ERROR; } diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h index cc846bab94420d..f793b36c95cb32 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -68,12 +69,15 @@ class Instance : public CommandHandlerInterface, public AttributeAccessInterface chip::Protocols::InteractionModel::Status UpdateInPlaceIndicator(bool aNewInPlaceIndicator); chip::Protocols::InteractionModel::Status UpdateLastChangedTime(DataModel::Nullable aNewLastChangedTime); + void SetReplacementProductListManagerInstance(ReplacementProductListManager * instance); + // Attribute getters uint8_t GetCondition() const; ChangeIndicationEnum GetChangeIndication() const; DegradationDirectionEnum GetDegradationDirection() const; bool GetInPlaceIndicator() const; DataModel::Nullable GetLastChangedTime() const; + EndpointId GetEndpointId() const { return mEndpointId; } /** @@ -161,11 +165,16 @@ class Instance : public CommandHandlerInterface, public AttributeAccessInterface ChangeIndicationEnum mChangeIndication = ChangeIndicationEnum::kOk; bool mInPlaceIndicator = true; DataModel::Nullable mLastChangedTime; + ReplacementProductListManager * mReplacementProductListManager = nullptr; uint32_t mFeatureMap; bool mResetConditionCommandSupported = false; + ReplacementProductListManager * GetReplacementProductListManagerInstance(); + + CHIP_ERROR ReadReplacableProductList(AttributeValueEncoder & aEncoder); + // CommandHandlerInterface void InvokeCommand(HandlerContext & ctx) override; CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index 91ddf145fda4ca..7bc663fe5f54bd 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -3880,6 +3880,12 @@ PICS: - label: "Does the device implement the InPlaceIndicator attribute?" id: HEPAFREMON.S.A0003 + - label: "Does the device implement the LastChangedTime attribute?" + id: HEPAFREMON.S.A0004 + + - label: "Does the device implement the ReplacementProductList attribute?" + id: HEPAFREMON.S.A0005 + # # server / features # @@ -3889,6 +3895,9 @@ PICS: - label: "Does the device support the Warning feature?" id: HEPAFREMON.S.F01 + - label: "Does the device support the ReplacementProductList feature?" + id: HEPAFREMON.S.F02 + # # server / commandsReceived # @@ -3921,6 +3930,12 @@ PICS: - label: "Does the device implement the InPlaceIndicator attribute?" id: ACFREMON.S.A0003 + - label: "Does the device implement the LastChangedTime attribute?" + id: ACFREMON.S.A0004 + + - label: "Does the device implement the ReplacementProductList attribute?" + id: ACFREMON.S.A0005 + # # server / features # @@ -3930,6 +3945,9 @@ PICS: - label: "Does the device support the Warning feature?" id: ACFREMON.S.F01 + - label: "Does the device support the ReplacementProductList feature?" + id: ACFREMON.S.F02 + # # server / commandsReceived # diff --git a/src/app/tests/suites/certification/Test_TC_ACFREMON_1_1.yaml b/src/app/tests/suites/certification/Test_TC_ACFREMON_1_1.yaml index a52bec17438e32..183a3569dc265e 100644 --- a/src/app/tests/suites/certification/Test_TC_ACFREMON_1_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_ACFREMON_1_1.yaml @@ -42,7 +42,7 @@ tests: - label: "Step 3a: Read the global attribute: FeatureMap" command: "readAttribute" attribute: "FeatureMap" - PICS: "!ACFREMON.S.F00 && !ACFREMON.S.F01" + PICS: "!ACFREMON.S.F00 && !ACFREMON.S.F01 && !ACFREMON.S.F02" response: value: 0 constraints: @@ -70,6 +70,17 @@ tests: type: bitmap32 hasMasksSet: [0x2] + - label: + "Step 3d: Given ACFREMON.S.F01(ReplacementProductList) ensure + featuremap has the correct bit set" + command: "readAttribute" + attribute: "FeatureMap" + PICS: ACFREMON.S.F02 + response: + constraints: + type: bitmap32 + hasMasksSet: [0x3] + - label: "Step 4a: Read the global attribute: AttributeList" command: "readAttribute" attribute: "AttributeList" @@ -87,7 +98,7 @@ tests: response: constraints: type: list - contains: [0, 1] + contains: [0, 1, 2] - label: "Step 4c: Read the optional attribute InPlaceIndicator diff --git a/src/app/tests/suites/certification/Test_TC_ACFREMON_2_1.yaml b/src/app/tests/suites/certification/Test_TC_ACFREMON_2_1.yaml index b4b6cd2e6f91a5..797e87c5adfe18 100644 --- a/src/app/tests/suites/certification/Test_TC_ACFREMON_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_ACFREMON_2_1.yaml @@ -69,3 +69,20 @@ tests: response: constraints: type: boolean + + - label: "Step 6: TH reads from the DUT the LastChangedTime attribute" + PICS: ACFREMON.S.A0004 + command: "readAttribute" + attribute: "LastChangedTime" + response: + constraints: + type: epoch_s + + - label: + "Step 7: TH reads from the DUT the ReplacementProductList attribute" + PICS: ACFREMON.S.A0005 + command: "readAttribute" + attribute: "ReplacementProductList" + response: + constraints: + type: list diff --git a/src/app/tests/suites/certification/Test_TC_HEPAFREMON_1_1.yaml b/src/app/tests/suites/certification/Test_TC_HEPAFREMON_1_1.yaml index 5b35a2d2765108..e45f21f5278bfb 100644 --- a/src/app/tests/suites/certification/Test_TC_HEPAFREMON_1_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_HEPAFREMON_1_1.yaml @@ -42,7 +42,7 @@ tests: - label: "Step 3a: Read the global attribute: FeatureMap" command: "readAttribute" attribute: "FeatureMap" - PICS: "!HEPAFREMON.S.F00 && !HEPAFREMON.S.F01" + PICS: "!HEPAFREMON.S.F00 && !HEPAFREMON.S.F01 && !HEPAFREMON.S.F02" response: value: 0 constraints: @@ -70,6 +70,17 @@ tests: type: bitmap32 hasMasksSet: [0x2] + - label: + "Step 3d: Given HEPAFREMON.S.F02(ReplacementProductList) ensure + featuremap has the correct bit set" + command: "readAttribute" + attribute: "FeatureMap" + PICS: HEPAFREMON.S.F02 + response: + constraints: + type: bitmap32 + hasMasksSet: [0x3] + - label: "Step 4: Read the global attribute: AttributeList" command: "readAttribute" attribute: "AttributeList" @@ -87,7 +98,7 @@ tests: response: constraints: type: list - contains: [0, 1] + contains: [0, 1, 2] - label: "Step 4b: Read the optional attribute InPlaceIndicator diff --git a/src/app/tests/suites/certification/Test_TC_HEPAFREMON_2_1.yaml b/src/app/tests/suites/certification/Test_TC_HEPAFREMON_2_1.yaml index cb2f281eebdc48..d232c3af497b2c 100644 --- a/src/app/tests/suites/certification/Test_TC_HEPAFREMON_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_HEPAFREMON_2_1.yaml @@ -69,3 +69,20 @@ tests: response: constraints: type: boolean + + - label: "Step 6: TH reads from the DUT the LastChangedTime attribute" + PICS: HEPAFREMON.S.A0004 + command: "readAttribute" + attribute: "LastChangedTime" + response: + constraints: + type: epoch_s + + - label: + "Step 7: TH reads from the DUT the ReplacementProductList attribute" + PICS: HEPAFREMON.S.A0005 + command: "readAttribute" + attribute: "ReplacementProductList" + response: + constraints: + type: list diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index 665a89453add0f..b52820046477a7 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -2172,10 +2172,13 @@ HEPAFREMON.S=1 HEPAFREMON.C=0 HEPAFREMON.S.F00=1 HEPAFREMON.S.F01=1 +HEPAFREMON.S.F02=1 HEPAFREMON.S.A0000=1 HEPAFREMON.S.A0001=1 HEPAFREMON.S.A0002=1 HEPAFREMON.S.A0003=1 +HEPAFREMON.S.A0004=1 +HEPAFREMON.S.A0005=1 HEPAFREMON.S.C00.Rsp=0 # Activated Carbon Filter Monitoring Cluster @@ -2183,10 +2186,13 @@ ACFREMON.S=1 ACFREMON.C=0 ACFREMON.S.F00=1 ACFREMON.S.F01=1 +ACFREMON.S.F02=1 ACFREMON.S.A0000=1 ACFREMON.S.A0001=1 ACFREMON.S.A0002=1 ACFREMON.S.A0003=1 +ACFREMON.S.A0004=1 +ACFREMON.S.A0005=1 ACFREMON.S.C00.Rsp=0 # Air Quality @@ -2516,4 +2522,4 @@ RVCCLEANMS.S.A0005=1 #Commands: RVCCLEANMS.S.C00.Rsp=1 RVCCLEANMS.S.C01.Rsp=1 -RVCCLEANMS.S.C03.Tx=1 \ No newline at end of file +RVCCLEANMS.S.C03.Tx=1 diff --git a/src/app/zap-templates/zcl/data-model/chip/resource-monitoring-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/resource-monitoring-cluster.xml index add05a191d4a75..a6be42b1a32e60 100644 --- a/src/app/zap-templates/zcl/data-model/chip/resource-monitoring-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/resource-monitoring-cluster.xml @@ -68,6 +68,7 @@ limitations under the License. + diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index d958e671819f20..59d5ba3e1a03f1 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -332,6 +332,7 @@ "ChangeIndication", "InPlaceIndicator", "LastChangedTime", + "ReplacementProductList", "FeatureMap" ], "HEPA Filter Monitoring": [ @@ -340,6 +341,7 @@ "ChangeIndication", "InPlaceIndicator", "LastChangedTime", + "ReplacementProductList", "FeatureMap" ] }, diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 3187abd98c7aaf..7d4d89ec6b4107 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -330,6 +330,7 @@ "ChangeIndication", "InPlaceIndicator", "LastChangedTime", + "ReplacementProductList", "FeatureMap" ], "HEPA Filter Monitoring": [ @@ -338,6 +339,7 @@ "ChangeIndication", "InPlaceIndicator", "LastChangedTime", + "ReplacementProductList", "FeatureMap" ] }, diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 543c6fe139a91a..43004df7702d9e 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -3470,6 +3470,7 @@ client cluster HepaFilterMonitoring = 113 { bitmap Feature : BITMAP32 { kCondition = 0x1; kWarning = 0x2; + kReplacementProductList = 0x3; } struct ReplacementProductStruct { @@ -3518,6 +3519,7 @@ client cluster ActivatedCarbonFilterMonitoring = 114 { bitmap Feature : BITMAP32 { kCondition = 0x1; kWarning = 0x2; + kReplacementProductList = 0x3; } struct ReplacementProductStruct { diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 4a987bb5da8683..1c843b6c1e53aa 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -19123,6 +19123,7 @@ class Bitmaps: class Feature(IntFlag): kCondition = 0x1 kWarning = 0x2 + kReplacementProductList = 0x3 class Structs: @dataclass @@ -19417,6 +19418,7 @@ class Bitmaps: class Feature(IntFlag): kCondition = 0x1 kWarning = 0x2 + kReplacementProductList = 0x3 class Structs: @dataclass diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h index 611acbb6043ce3..6cef8dce3faef4 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h @@ -1904,8 +1904,9 @@ enum class ProductIdentifierTypeEnum : uint8_t // Bitmap for Feature enum class Feature : uint32_t { - kCondition = 0x1, - kWarning = 0x2, + kCondition = 0x1, + kWarning = 0x2, + kReplacementProductList = 0x3, }; } // namespace HepaFilterMonitoring @@ -1954,8 +1955,9 @@ enum class ProductIdentifierTypeEnum : uint8_t // Bitmap for Feature enum class Feature : uint32_t { - kCondition = 0x1, - kWarning = 0x2, + kCondition = 0x1, + kWarning = 0x2, + kReplacementProductList = 0x3, }; } // namespace ActivatedCarbonFilterMonitoring diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 4a209ef3d3c52d..5a4912e5a59c70 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -107998,7 +107998,7 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand { public: Test_TC_ACFREMON_1_1Suite(CredentialIssuerCommands * credsIssuerConfig) : - TestCommand("Test_TC_ACFREMON_1_1", 12, credsIssuerConfig) + TestCommand("Test_TC_ACFREMON_1_1", 13, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); @@ -108072,6 +108072,15 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand } break; case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + VerifyOrReturn(CheckConstraintHasMasksSet("value", value, 3UL)); + } + break; + case 6: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108086,7 +108095,7 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintContains("value", value, 65533UL)); } break; - case 6: + case 7: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108094,9 +108103,10 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "list", "list")); VerifyOrReturn(CheckConstraintContains("value", value, 0UL)); VerifyOrReturn(CheckConstraintContains("value", value, 1UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 2UL)); } break; - case 7: + case 8: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108105,7 +108115,7 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintContains("value", value, 3UL)); } break; - case 8: + case 9: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108117,7 +108127,7 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "list", "list")); } break; - case 9: + case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108125,7 +108135,7 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "list", "list")); } break; - case 10: + case 11: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108134,7 +108144,7 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintContains("value", value, 0UL)); } break; - case 11: + case 12: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108175,7 +108185,8 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand } case 2: { LogStep(2, "Step 3a: Read the global attribute: FeatureMap"); - VerifyOrDo(!ShouldSkip("!ACFREMON.S.F00 && !ACFREMON.S.F01"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + VerifyOrDo(!ShouldSkip("!ACFREMON.S.F00 && !ACFREMON.S.F01 && !ACFREMON.S.F02"), + return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Attributes::FeatureMap::Id, true, chip::NullOptional); } @@ -108192,40 +108203,46 @@ class Test_TC_ACFREMON_1_1Suite : public TestCommand ActivatedCarbonFilterMonitoring::Attributes::FeatureMap::Id, true, chip::NullOptional); } case 5: { - LogStep(5, "Step 4a: Read the global attribute: AttributeList"); + LogStep(5, "Step 3d: Given ACFREMON.S.F01(ReplacementProductList) ensure featuremap has the correct bit set"); + VerifyOrDo(!ShouldSkip("ACFREMON.S.F02"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, - ActivatedCarbonFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); + ActivatedCarbonFilterMonitoring::Attributes::FeatureMap::Id, true, chip::NullOptional); } case 6: { - LogStep(6, "Step 4b: Read the feature dependent(ACFREMON.S.F00) attribute in AttributeList"); - VerifyOrDo(!ShouldSkip("ACFREMON.S.F00"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + LogStep(6, "Step 4a: Read the global attribute: AttributeList"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); } case 7: { - LogStep(7, "Step 4c: Read the optional attribute InPlaceIndicator (ACFREMON.S.A0002) in AttributeList"); - VerifyOrDo(!ShouldSkip("ACFREMON.S.A0002"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + LogStep(7, "Step 4b: Read the feature dependent(ACFREMON.S.F00) attribute in AttributeList"); + VerifyOrDo(!ShouldSkip("ACFREMON.S.F00"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); } case 8: { - LogStep(8, "Step 5: TH reads EventList attribute from DUT"); + LogStep(8, "Step 4c: Read the optional attribute InPlaceIndicator (ACFREMON.S.A0002) in AttributeList"); + VerifyOrDo(!ShouldSkip("ACFREMON.S.A0002"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, - ActivatedCarbonFilterMonitoring::Attributes::EventList::Id, true, chip::NullOptional); + ActivatedCarbonFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); } case 9: { - LogStep(9, "Step 6a: Read the global attribute: AcceptedCommandList"); + LogStep(9, "Step 5: TH reads EventList attribute from DUT"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, - ActivatedCarbonFilterMonitoring::Attributes::AcceptedCommandList::Id, true, chip::NullOptional); + ActivatedCarbonFilterMonitoring::Attributes::EventList::Id, true, chip::NullOptional); } case 10: { - LogStep(10, "Step 6b: Read the optional command (ResetCondition) in AcceptedCommandList"); - VerifyOrDo(!ShouldSkip("ACFREMON.S.C00.Rsp"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + LogStep(10, "Step 6a: Read the global attribute: AcceptedCommandList"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Attributes::AcceptedCommandList::Id, true, chip::NullOptional); } case 11: { - LogStep(11, "Step 7: Read the global attribute: GeneratedCommandList"); + LogStep(11, "Step 6b: Read the optional command (ResetCondition) in AcceptedCommandList"); + VerifyOrDo(!ShouldSkip("ACFREMON.S.C00.Rsp"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, + ActivatedCarbonFilterMonitoring::Attributes::AcceptedCommandList::Id, true, chip::NullOptional); + } + case 12: { + LogStep(12, "Step 7: Read the global attribute: GeneratedCommandList"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Attributes::GeneratedCommandList::Id, true, chip::NullOptional); } @@ -108238,7 +108255,7 @@ class Test_TC_ACFREMON_2_1Suite : public TestCommand { public: Test_TC_ACFREMON_2_1Suite(CredentialIssuerCommands * credsIssuerConfig) : - TestCommand("Test_TC_ACFREMON_2_1", 5, credsIssuerConfig) + TestCommand("Test_TC_ACFREMON_2_1", 7, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); @@ -108313,6 +108330,24 @@ class Test_TC_ACFREMON_2_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "boolean", "boolean")); } break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::Nullable value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "epoch_s", "epoch_s")); + } + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::DecodableList< + chip::app::Clusters::ActivatedCarbonFilterMonitoring::Structs::ReplacementProductStruct::DecodableType> + value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "list", "list")); + } + break; default: LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT)); } @@ -108359,6 +108394,18 @@ class Test_TC_ACFREMON_2_1Suite : public TestCommand return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Attributes::InPlaceIndicator::Id, true, chip::NullOptional); } + case 5: { + LogStep(5, "Step 6: TH reads from the DUT the LastChangedTime attribute"); + VerifyOrDo(!ShouldSkip("ACFREMON.S.A0004"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, + ActivatedCarbonFilterMonitoring::Attributes::LastChangedTime::Id, true, chip::NullOptional); + } + case 6: { + LogStep(6, "Step 7: TH reads from the DUT the ReplacementProductList attribute"); + VerifyOrDo(!ShouldSkip("ACFREMON.S.A0005"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id, + ActivatedCarbonFilterMonitoring::Attributes::ReplacementProductList::Id, true, chip::NullOptional); + } } return CHIP_NO_ERROR; } @@ -108368,7 +108415,7 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand { public: Test_TC_HEPAFREMON_1_1Suite(CredentialIssuerCommands * credsIssuerConfig) : - TestCommand("Test_TC_HEPAFREMON_1_1", 12, credsIssuerConfig) + TestCommand("Test_TC_HEPAFREMON_1_1", 13, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); @@ -108442,6 +108489,15 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand } break; case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + VerifyOrReturn(CheckConstraintHasMasksSet("value", value, 3UL)); + } + break; + case 6: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108456,7 +108512,7 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintContains("value", value, 65533UL)); } break; - case 6: + case 7: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108464,9 +108520,10 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "list", "list")); VerifyOrReturn(CheckConstraintContains("value", value, 0UL)); VerifyOrReturn(CheckConstraintContains("value", value, 1UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 2UL)); } break; - case 7: + case 8: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108475,7 +108532,7 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintContains("value", value, 3UL)); } break; - case 8: + case 9: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108487,7 +108544,7 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "list", "list")); } break; - case 9: + case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108495,7 +108552,7 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "list", "list")); } break; - case 10: + case 11: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108504,7 +108561,7 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand VerifyOrReturn(CheckConstraintContains("value", value, 0UL)); } break; - case 11: + case 12: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::DecodableList value; @@ -108545,7 +108602,8 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand } case 2: { LogStep(2, "Step 3a: Read the global attribute: FeatureMap"); - VerifyOrDo(!ShouldSkip("!HEPAFREMON.S.F00 && !HEPAFREMON.S.F01"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + VerifyOrDo(!ShouldSkip("!HEPAFREMON.S.F00 && !HEPAFREMON.S.F01 && !HEPAFREMON.S.F02"), + return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, HepaFilterMonitoring::Attributes::FeatureMap::Id, true, chip::NullOptional); } @@ -108562,40 +108620,46 @@ class Test_TC_HEPAFREMON_1_1Suite : public TestCommand HepaFilterMonitoring::Attributes::FeatureMap::Id, true, chip::NullOptional); } case 5: { - LogStep(5, "Step 4: Read the global attribute: AttributeList"); + LogStep(5, "Step 3d: Given HEPAFREMON.S.F02(ReplacementProductList) ensure featuremap has the correct bit set"); + VerifyOrDo(!ShouldSkip("HEPAFREMON.S.F02"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, - HepaFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); + HepaFilterMonitoring::Attributes::FeatureMap::Id, true, chip::NullOptional); } case 6: { - LogStep(6, "Step 4a: Read the feature dependent(HEPAFREMON.S.F00) attribute in AttributeList"); - VerifyOrDo(!ShouldSkip("HEPAFREMON.S.F00"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + LogStep(6, "Step 4: Read the global attribute: AttributeList"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, HepaFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); } case 7: { - LogStep(7, "Step 4b: Read the optional attribute InPlaceIndicator (HEPAFREMON.S.A0002) in AttributeList"); - VerifyOrDo(!ShouldSkip("HEPAFREMON.S.A0002"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + LogStep(7, "Step 4a: Read the feature dependent(HEPAFREMON.S.F00) attribute in AttributeList"); + VerifyOrDo(!ShouldSkip("HEPAFREMON.S.F00"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, HepaFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); } case 8: { - LogStep(8, "Step 5: TH reads EventList attribute from DUT"); + LogStep(8, "Step 4b: Read the optional attribute InPlaceIndicator (HEPAFREMON.S.A0002) in AttributeList"); + VerifyOrDo(!ShouldSkip("HEPAFREMON.S.A0002"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, - HepaFilterMonitoring::Attributes::EventList::Id, true, chip::NullOptional); + HepaFilterMonitoring::Attributes::AttributeList::Id, true, chip::NullOptional); } case 9: { - LogStep(9, "Step 6a: Read the global attribute: AcceptedCommandList"); + LogStep(9, "Step 5: TH reads EventList attribute from DUT"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, - HepaFilterMonitoring::Attributes::AcceptedCommandList::Id, true, chip::NullOptional); + HepaFilterMonitoring::Attributes::EventList::Id, true, chip::NullOptional); } case 10: { - LogStep(10, "Step 6b: Read the optional command (ResetCondition) in AcceptedCommandList"); - VerifyOrDo(!ShouldSkip("HEPAFREMON.S.C00.Rsp"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + LogStep(10, "Step 6a: Read the global attribute: AcceptedCommandList"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, HepaFilterMonitoring::Attributes::AcceptedCommandList::Id, true, chip::NullOptional); } case 11: { - LogStep(11, "Step 7: Read the global attribute: GeneratedCommandList"); + LogStep(11, "Step 6b: Read the optional command (ResetCondition) in AcceptedCommandList"); + VerifyOrDo(!ShouldSkip("HEPAFREMON.S.C00.Rsp"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, + HepaFilterMonitoring::Attributes::AcceptedCommandList::Id, true, chip::NullOptional); + } + case 12: { + LogStep(12, "Step 7: Read the global attribute: GeneratedCommandList"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, HepaFilterMonitoring::Attributes::GeneratedCommandList::Id, true, chip::NullOptional); } @@ -108608,7 +108672,7 @@ class Test_TC_HEPAFREMON_2_1Suite : public TestCommand { public: Test_TC_HEPAFREMON_2_1Suite(CredentialIssuerCommands * credsIssuerConfig) : - TestCommand("Test_TC_HEPAFREMON_2_1", 5, credsIssuerConfig) + TestCommand("Test_TC_HEPAFREMON_2_1", 7, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); @@ -108683,6 +108747,24 @@ class Test_TC_HEPAFREMON_2_1Suite : public TestCommand VerifyOrReturn(CheckConstraintType("value", "boolean", "boolean")); } break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::Nullable value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "epoch_s", "epoch_s")); + } + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::DecodableList< + chip::app::Clusters::HepaFilterMonitoring::Structs::ReplacementProductStruct::DecodableType> + value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "list", "list")); + } + break; default: LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT)); } @@ -108729,6 +108811,18 @@ class Test_TC_HEPAFREMON_2_1Suite : public TestCommand return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, HepaFilterMonitoring::Attributes::InPlaceIndicator::Id, true, chip::NullOptional); } + case 5: { + LogStep(5, "Step 6: TH reads from the DUT the LastChangedTime attribute"); + VerifyOrDo(!ShouldSkip("HEPAFREMON.S.A0004"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, + HepaFilterMonitoring::Attributes::LastChangedTime::Id, true, chip::NullOptional); + } + case 6: { + LogStep(6, "Step 7: TH reads from the DUT the ReplacementProductList attribute"); + VerifyOrDo(!ShouldSkip("HEPAFREMON.S.A0005"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id, + HepaFilterMonitoring::Attributes::ReplacementProductList::Id, true, chip::NullOptional); + } } return CHIP_NO_ERROR; }