Modifying ReplacementProductListManager to be generic (#28185)
* Modifying ReplacementProductListManager to be generic
Addressing feedback from PR #28095 and also addressing #28148
This change simplifies the implementation of the ReplacementProductList and also introduces a DynamicReplacementProductList example which better represents devices fetching this product list from flash.
It includes some simplifications to the structure of the code and a few additional unit tests to exercise the behavior.
Tested to ensure functionality still works as expected using the all-clusters-app as well as the resource-monitoring-app
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 c12a686..276e423 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
@@ -55,23 +55,9 @@
aResetConditionCommandSupported){};
};
-class StaticReplacementProductListManager : public chip::app::Clusters::ResourceMonitoring::ReplacementProductListManager
+class ImmutableReplacementProductListManager : 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;
+ CHIP_ERROR
+ Next(chip::app::Clusters::ResourceMonitoring::ReplacementProductStruct & item) override;
};
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 de7b46d..dc42835 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
@@ -36,20 +36,7 @@
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));
+static ImmutableReplacementProductListManager sReplacementProductListManager;
//-- Activated Carbon Filter Monitoring Instance methods
CHIP_ERROR ActivatedCarbonFilterMonitoringInstance::AppInit()
@@ -106,14 +93,40 @@
gHepaFilterInstance->Init();
}
-CHIP_ERROR StaticReplacementProductListManager::Next(Attributes::ReplacementProductStruct::Type & item)
+CHIP_ERROR ImmutableReplacementProductListManager::Next(ReplacementProductStruct & item)
{
- if (mIndex < mReplacementProductListSize)
+ if (mIndex >= kReplacementProductListMaxSize)
{
- item = mReplacementProductsList[mIndex];
- mIndex++;
- return CHIP_NO_ERROR;
+ return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
}
- return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+ switch (mIndex)
+ {
+ case 0: {
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kUpc);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233"));
+ break;
+ case 1:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx"));
+ break;
+ case 2:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kEan);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666"));
+ break;
+ case 3:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx"));
+ break;
+ case 4:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kOem);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx"));
+ break;
+ default:
+ return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+ break;
+ }
+ }
+ mIndex++;
+ return CHIP_NO_ERROR;
}
diff --git a/examples/placeholder/linux/apps/app1/BUILD.gn b/examples/placeholder/linux/apps/app1/BUILD.gn
index 595a0b7..99b3547 100644
--- a/examples/placeholder/linux/apps/app1/BUILD.gn
+++ b/examples/placeholder/linux/apps/app1/BUILD.gn
@@ -30,6 +30,7 @@
]
sources = [
+ "../../resource-monitoring-instances.cpp",
"../../src/bridged-actions-stub.cpp",
"../../static-supported-modes-manager.cpp",
]
diff --git a/examples/placeholder/linux/apps/app2/BUILD.gn b/examples/placeholder/linux/apps/app2/BUILD.gn
index 7d8f30a..9177797 100644
--- a/examples/placeholder/linux/apps/app2/BUILD.gn
+++ b/examples/placeholder/linux/apps/app2/BUILD.gn
@@ -30,6 +30,7 @@
]
sources = [
+ "../../resource-monitoring-instances.cpp",
"../../src/bridged-actions-stub.cpp",
"../../static-supported-modes-manager.cpp",
]
diff --git a/examples/placeholder/linux/include/resource-monitoring-instances.h b/examples/placeholder/linux/include/resource-monitoring-instances.h
new file mode 100644
index 0000000..276e423
--- /dev/null
+++ b/examples/placeholder/linux/include/resource-monitoring-instances.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright (c) 2023 Project CHIP Authors
+ *
+ * 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 <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h>
+#include <app/clusters/resource-monitoring-server/resource-monitoring-server.h>
+
+/// This is an application level Instance to handle ActivatedCarbonfilterMonitoringInstance commands according to the specific
+/// business logic.
+class ActivatedCarbonFilterMonitoringInstance : public chip::app::Clusters::ResourceMonitoring::Instance
+{
+private:
+ CHIP_ERROR AppInit() override;
+ chip::Protocols::InteractionModel::Status PreResetCondition() override;
+ chip::Protocols::InteractionModel::Status PostResetCondition() override;
+
+public:
+ ActivatedCarbonFilterMonitoringInstance(
+ chip::EndpointId aEndpointId, uint32_t aFeature,
+ chip::app::Clusters::ResourceMonitoring::Attributes::DegradationDirection::TypeInfo::Type aDegradationDirection,
+ bool aResetConditionCommandSupported) :
+ Instance(aEndpointId, chip::app::Clusters::ActivatedCarbonFilterMonitoring::Id, aFeature, aDegradationDirection,
+ aResetConditionCommandSupported){};
+};
+
+/// This is an application level instance to handle HepaFilterMonitoringInstance commands according to the specific business logic.
+class HepaFilterMonitoringInstance : public chip::app::Clusters::ResourceMonitoring::Instance
+{
+private:
+ CHIP_ERROR AppInit() override;
+ chip::Protocols::InteractionModel::Status PreResetCondition() override;
+ chip::Protocols::InteractionModel::Status PostResetCondition() override;
+
+public:
+ HepaFilterMonitoringInstance(
+ chip::EndpointId aEndpointId, uint32_t aFeature,
+ chip::app::Clusters::ResourceMonitoring::Attributes::DegradationDirection::TypeInfo::Type aDegradationDirection,
+ bool aResetConditionCommandSupported) :
+ Instance(aEndpointId, chip::app::Clusters::HepaFilterMonitoring::Id, aFeature, aDegradationDirection,
+ aResetConditionCommandSupported){};
+};
+
+class ImmutableReplacementProductListManager : public chip::app::Clusters::ResourceMonitoring::ReplacementProductListManager
+{
+public:
+ CHIP_ERROR
+ Next(chip::app::Clusters::ResourceMonitoring::ReplacementProductStruct & item) override;
+};
diff --git a/examples/placeholder/linux/resource-monitoring-instances.cpp b/examples/placeholder/linux/resource-monitoring-instances.cpp
new file mode 100644
index 0000000..a030bee
--- /dev/null
+++ b/examples/placeholder/linux/resource-monitoring-instances.cpp
@@ -0,0 +1,133 @@
+/*
+ *
+ * Copyright (c) 2023 Project CHIP Authors
+ *
+ * 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 <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h>
+#include <app/clusters/resource-monitoring-server/resource-monitoring-server.h>
+#include <resource-monitoring-instances.h>
+
+using namespace chip;
+using namespace chip::app;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::ResourceMonitoring;
+using chip::Protocols::InteractionModel::Status;
+
+constexpr std::bitset<4> gHepaFilterFeatureMap{ static_cast<uint32_t>(Feature::kCondition) |
+ static_cast<uint32_t>(Feature::kWarning) |
+ static_cast<uint32_t>(Feature::kReplacementProductList) };
+constexpr std::bitset<4> gActivatedCarbonFeatureMap{ static_cast<uint32_t>(Feature::kCondition) |
+ static_cast<uint32_t>(Feature::kWarning) |
+ static_cast<uint32_t>(Feature::kReplacementProductList) };
+
+static HepaFilterMonitoringInstance * gHepaFilterInstance = nullptr;
+static ActivatedCarbonFilterMonitoringInstance * gActivatedCarbonFilterInstance = nullptr;
+
+static ImmutableReplacementProductListManager sReplacementProductListManager;
+
+//-- Activated Carbon Filter Monitoring Instance methods
+CHIP_ERROR ActivatedCarbonFilterMonitoringInstance::AppInit()
+{
+ ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::Init()");
+ SetReplacementProductListManagerInstance(&sReplacementProductListManager);
+ return CHIP_NO_ERROR;
+}
+
+Status ActivatedCarbonFilterMonitoringInstance::PreResetCondition()
+{
+ ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringInstance::PreResetCondition()");
+ return Status::Success;
+}
+
+Status ActivatedCarbonFilterMonitoringInstance::PostResetCondition()
+{
+ ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringInstance::PostResetCondition()");
+ return Status::Success;
+}
+
+//-- Hepa Filter Monitoring instance methods
+CHIP_ERROR HepaFilterMonitoringInstance::AppInit()
+{
+ ChipLogDetail(Zcl, "HepaFilterMonitoringInstance::Init()");
+ SetReplacementProductListManagerInstance(&sReplacementProductListManager);
+ return CHIP_NO_ERROR;
+}
+
+Status HepaFilterMonitoringInstance::PreResetCondition()
+{
+ ChipLogDetail(Zcl, "HepaFilterMonitoringInstance::PreResetCondition()");
+ return Status::Success;
+}
+
+Status HepaFilterMonitoringInstance::PostResetCondition()
+{
+ ChipLogDetail(Zcl, "HepaFilterMonitoringInstance::PostResetCondition()");
+ return Status::Success;
+}
+
+void emberAfActivatedCarbonFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
+{
+ VerifyOrDie(gActivatedCarbonFilterInstance == nullptr);
+ gActivatedCarbonFilterInstance = new ActivatedCarbonFilterMonitoringInstance(
+ endpoint, static_cast<uint32_t>(gActivatedCarbonFeatureMap.to_ulong()), DegradationDirectionEnum::kDown, true);
+ gActivatedCarbonFilterInstance->Init();
+}
+void emberAfHepaFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
+{
+ VerifyOrDie(gHepaFilterInstance == nullptr);
+ gHepaFilterInstance = new HepaFilterMonitoringInstance(endpoint, static_cast<uint32_t>(gHepaFilterFeatureMap.to_ulong()),
+ DegradationDirectionEnum::kDown, true);
+ gHepaFilterInstance->Init();
+}
+
+CHIP_ERROR ImmutableReplacementProductListManager::Next(ReplacementProductStruct & item)
+{
+ if (mIndex >= kReplacementProductListMaxSize)
+ {
+ return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+ }
+
+ switch (mIndex)
+ {
+ case 0: {
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kUpc);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233"));
+ break;
+ case 1:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx"));
+ break;
+ case 2:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kEan);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666"));
+ break;
+ case 3:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx"));
+ break;
+ case 4:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kOem);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx"));
+ break;
+ default:
+ return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+ break;
+ }
+ }
+ mIndex++;
+ return CHIP_NO_ERROR;
+}
diff --git a/examples/resource-monitoring-app/linux/BUILD.gn b/examples/resource-monitoring-app/linux/BUILD.gn
index c5e769a..e9d5e39 100644
--- a/examples/resource-monitoring-app/linux/BUILD.gn
+++ b/examples/resource-monitoring-app/linux/BUILD.gn
@@ -30,7 +30,7 @@
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/ReplacementProductListManager.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",
"include/CHIPProjectAppConfig.h",
diff --git a/examples/resource-monitoring-app/resource-monitoring-common/include/ImmutableReplacementProductListManager.h b/examples/resource-monitoring-app/resource-monitoring-common/include/ImmutableReplacementProductListManager.h
new file mode 100644
index 0000000..2dcbff4
--- /dev/null
+++ b/examples/resource-monitoring-app/resource-monitoring-common/include/ImmutableReplacementProductListManager.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 <app/clusters/resource-monitoring-server/replacement-product-list-manager.h>
+#include <app/util/af.h>
+#include <app/util/config.h>
+
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace ResourceMonitoring {
+
+/**
+ * This implementation returns an immutable list of replacement products.
+ * It holds ReplacementProductListManager::kReplacementProductListMaxSize products in the list.
+ */
+
+class ImmutableReplacementProductListManager : public ReplacementProductListManager
+{
+public:
+ CHIP_ERROR Next(ReplacementProductStruct & item) override;
+};
+
+} // namespace ResourceMonitoring
+} // namespace Clusters
+} // namespace app
+} // namespace chip
diff --git a/examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h b/examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h
index cb83148..26601a2 100644
--- a/examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h
+++ b/examples/resource-monitoring-app/resource-monitoring-common/include/StaticReplacementProductListManager.h
@@ -34,20 +34,17 @@
class StaticReplacementProductListManager : public ReplacementProductListManager
{
public:
- uint8_t Size() override { return mReplacementProductListSize; };
-
- CHIP_ERROR Next(Attributes::ReplacementProductStruct::Type & item) override;
+ CHIP_ERROR Next(ReplacementProductStruct & item) override;
~StaticReplacementProductListManager() {}
- StaticReplacementProductListManager(Attributes::ReplacementProductStruct::Type * aReplacementProductsList,
- uint8_t aReplacementProductListSize)
+ StaticReplacementProductListManager(ReplacementProductStruct * aReplacementProductsList, uint8_t aReplacementProductListSize)
{
mReplacementProductsList = aReplacementProductsList;
mReplacementProductListSize = aReplacementProductListSize;
}
private:
- Attributes::ReplacementProductStruct::Type * mReplacementProductsList;
+ ReplacementProductStruct * mReplacementProductsList;
uint8_t mReplacementProductListSize;
};
diff --git a/examples/resource-monitoring-app/resource-monitoring-common/src/ReplacementProductListManager.cpp b/examples/resource-monitoring-app/resource-monitoring-common/src/ReplacementProductListManager.cpp
new file mode 100644
index 0000000..f450df6
--- /dev/null
+++ b/examples/resource-monitoring-app/resource-monitoring-common/src/ReplacementProductListManager.cpp
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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 <ImmutableReplacementProductListManager.h>
+#include <StaticReplacementProductListManager.h>
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h>
+#include <lib/core/CHIPError.h>
+
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::ResourceMonitoring;
+
+CHIP_ERROR StaticReplacementProductListManager::Next(ReplacementProductStruct & item)
+{
+ if (mIndex < mReplacementProductListSize)
+ {
+ item = mReplacementProductsList[mIndex];
+ mIndex++;
+ return CHIP_NO_ERROR;
+ }
+
+ return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+}
+
+CHIP_ERROR ImmutableReplacementProductListManager::Next(ReplacementProductStruct & item)
+{
+ if (mIndex >= kReplacementProductListMaxSize)
+ {
+ return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+ }
+
+ switch (mIndex)
+ {
+ case 0: {
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kUpc);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("111112222233"));
+ break;
+ case 1:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("gtin8xxx"));
+ break;
+ case 2:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kEan);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("4444455555666"));
+ break;
+ case 3:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("gtin14xxxxxxxx"));
+ break;
+ case 4:
+ item.SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum::kOem);
+ item.SetProductIdentifierValue(CharSpan::fromCharString("oem20xxxxxxxxxxxxxxx"));
+ break;
+ default:
+ return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+ break;
+ }
+ }
+ mIndex++;
+ return CHIP_NO_ERROR;
+}
diff --git a/examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp b/examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp
deleted file mode 100644
index 4c657ff..0000000
--- a/examples/resource-monitoring-app/resource-monitoring-common/src/StaticReplacementProductListManager.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * 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 <StaticReplacementProductListManager.h>
-#include <app-common/zap-generated/ids/Attributes.h>
-#include <app-common/zap-generated/ids/Clusters.h>
-#include <app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h>
-#include <lib/core/CHIPError.h>
-
-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 778bb9d..3ab33e6 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
@@ -32,19 +32,15 @@
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::ActivatedCarbonFilterMonitoring;
using namespace chip::app::Clusters::ResourceMonitoring;
+using namespace chip::app::Clusters::ResourceMonitoring::Attributes;
using chip::Protocols::InteractionModel::Status;
-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") },
+static ReplacementProductStruct sActivatedCarbonFilterReplacementProductsList[] = {
+ { ResourceMonitoring::ProductIdentifierTypeEnum::kUpc, CharSpan::fromCharString("111112222233") },
+ { ResourceMonitoring::ProductIdentifierTypeEnum::kGtin8, CharSpan::fromCharString("gtin8xca") },
+ { ResourceMonitoring::ProductIdentifierTypeEnum::kEan, CharSpan::fromCharString("4444455555666") },
+ { ResourceMonitoring::ProductIdentifierTypeEnum::kGtin14, CharSpan::fromCharString("gtin14xcarbonx") },
+ { ResourceMonitoring::ProductIdentifierTypeEnum::kOem, CharSpan::fromCharString("oem20xcarbonxxxxxxxx") },
};
StaticReplacementProductListManager
sActivatedCarbonFilterReplacementProductListManager(&sActivatedCarbonFilterReplacementProductsList[0],
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 c0ee95e..6404f97 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,7 +16,7 @@
* limitations under the License.
*/
-#include <StaticReplacementProductListManager.h>
+#include <ImmutableReplacementProductListManager.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/clusters/resource-monitoring-server/resource-monitoring-cluster-objects.h>
@@ -31,22 +31,10 @@
using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::ResourceMonitoring;
+using namespace chip::app::Clusters::ResourceMonitoring::Attributes;
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));
+static ImmutableReplacementProductListManager sHepaFilterReplacementProductListManager;
//-- Hepa filter Monitoring instance methods
CHIP_ERROR HepaFilterMonitoringInstance::AppInit()
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
index b252597..bd63dab 100644
--- a/src/app/clusters/resource-monitoring-server/replacement-product-list-manager.h
+++ b/src/app/clusters/resource-monitoring-server/replacement-product-list-manager.h
@@ -34,15 +34,24 @@
class ReplacementProductListManager
{
public:
+ // The max replacement product list size as defined in the specification
+ static constexpr size_t kReplacementProductListMaxSize = 5u;
+
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;
+ /**
+ * Iterates through the entries in the ReplacementProductListManager. Each call to this function copies the next item into
+ * the out param. Calls to this function will return CHIP_NO_ERROR if there are still valid elements in the list. The function
+ * will return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED if the end of the list has been reached.
+ *
+ * @param[out] item An out parameter that has a copy of the item retrieved in the list.
+ * @return CHIP_NO_ERROR if the pointer to the list element has moved to the next element and there are still valid remaining
+ * entries in the list. Otherwise returns CHIP_ERROR_PROVIDER_LIST_EXHAUSTED if the list has hit the last element.
+ */
+ virtual CHIP_ERROR Next(ReplacementProductStruct & item) = 0;
protected:
uint8_t mIndex;
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 932c95c..34388cb 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,22 +44,6 @@
} // 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 995f42b..970a85c 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,9 @@
namespace Clusters {
namespace ResourceMonitoring {
-static constexpr std::array<ClusterId, 2> AliasedClusters = { HepaFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Id };
+// max of 20 characters as defined by the constraint on the ProductIdentifierValue in the specification
+static constexpr size_t kProductIdentifierValueMaxNameLength = 20u;
+static constexpr std::array<ClusterId, 2> AliasedClusters = { HepaFilterMonitoring::Id, ActivatedCarbonFilterMonitoring::Id };
// Enum for ChangeIndicationEnum
enum class ChangeIndicationEnum : uint8_t
@@ -74,6 +76,74 @@
kOem = 0x04
};
+// A struct used during reads of the ReplacementProductList to store a single list instance we request
+// from the application.
+//
+// Inherit from an auto-generated struct to pick up the implementation bits, but make
+// it private inheritance so people can't accidentally use this struct where the other
+// is expected.
+struct ReplacementProductStruct : private HepaFilterMonitoring::Structs::ReplacementProductStruct::Type
+{
+private:
+ char productIdentifierValueBuffer[kProductIdentifierValueMaxNameLength];
+
+public:
+ static constexpr bool kIsFabricScoped = false;
+ virtual ~ReplacementProductStruct() = default;
+ ReplacementProductStruct() {}
+ ReplacementProductStruct(ResourceMonitoring::ProductIdentifierTypeEnum aProductIdentifierType,
+ chip::CharSpan aProductIdentifierValue)
+ {
+ SetProductIdentifierType(aProductIdentifierType);
+ SetProductIdentifierValue(aProductIdentifierValue);
+ }
+
+ ReplacementProductStruct & operator=(const ReplacementProductStruct & aReplacementProductStruct)
+ {
+ SetProductIdentifierType(aReplacementProductStruct.GetProductIdentifierType());
+ SetProductIdentifierValue(aReplacementProductStruct.GetProductIdentifierValue());
+ return *this;
+ }
+
+ using HepaFilterMonitoring::Structs::ReplacementProductStruct::Type::Encode;
+
+ /**
+ * Sets the product identifier type.
+ *
+ * @param aProductIdentifierType The product identifier type.
+ */
+ void SetProductIdentifierType(ResourceMonitoring::ProductIdentifierTypeEnum aProductIdentifierType)
+ {
+ productIdentifierType = static_cast<HepaFilterMonitoring::ProductIdentifierTypeEnum>(aProductIdentifierType);
+ }
+
+ /**
+ * Sets the product identifier value.
+ * This implementation will copy the argument into this struct's buffer.
+ *
+ * @param aProductIdentifierValue The value of the product identifier to set.
+ * @return CHIP_ERROR_INVALID_ARGUMENT when aProductIdentifierValue is invalid
+ * or the size exceeds kProductIdentifierValueMaxNameLength, returns CHIP_NO_ERROR
+ * otherwise.
+ */
+ CHIP_ERROR SetProductIdentifierValue(chip::CharSpan aProductIdentifierValue)
+ {
+ VerifyOrReturnError(IsSpanUsable(aProductIdentifierValue), CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(aProductIdentifierValue.size() <= sizeof(productIdentifierValueBuffer), CHIP_ERROR_INVALID_ARGUMENT);
+
+ memcpy(productIdentifierValueBuffer, aProductIdentifierValue.data(), aProductIdentifierValue.size());
+ productIdentifierValue = CharSpan(productIdentifierValueBuffer, aProductIdentifierValue.size());
+
+ return CHIP_NO_ERROR;
+ }
+
+ ProductIdentifierTypeEnum GetProductIdentifierType() const
+ {
+ return static_cast<ProductIdentifierTypeEnum>(productIdentifierType);
+ };
+ chip::CharSpan GetProductIdentifierValue() const { return productIdentifierValue; };
+};
+
namespace Attributes {
namespace Condition {
@@ -141,42 +211,9 @@
};
} // namespace LastChangedTime
-namespace ReplacementProductStruct {
-enum class Fields : uint8_t
-{
- kProductIdentifierType = 0,
- kProductIdentifierValue = 1,
-};
-
-struct Type
-{
-public:
- ProductIdentifierTypeEnum productIdentifierType = static_cast<ProductIdentifierTypeEnum>(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<const ReplacementProductStruct::Type>;
- using DecodableType = chip::app::DataModel::DecodableList<ReplacementProductStruct::Type>;
- using DecodableArgType = const chip::app::DataModel::DecodableList<ReplacementProductStruct::Type> &;
-
- 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;
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 2cbcb43..c568746 100644
--- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp
+++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp
@@ -244,10 +244,10 @@
CHIP_ERROR Instance::ReadReplacableProductList(AttributeValueEncoder & aEncoder)
{
- CHIP_ERROR err;
- if (Instance::HasFeature(ResourceMonitoring::Feature::kReplacementProductList))
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ if (HasFeature(ResourceMonitoring::Feature::kReplacementProductList))
{
- ReplacementProductListManager * productListManagerInstance = Instance::GetReplacementProductListManagerInstance();
+ ReplacementProductListManager * productListManagerInstance = GetReplacementProductListManagerInstance();
if (nullptr == productListManagerInstance)
{
aEncoder.EncodeEmptyList();
@@ -256,16 +256,19 @@
productListManagerInstance->Reset();
- err = aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR {
- Attributes::ReplacementProductStruct::Type replacementProductStruct;
- while (productListManagerInstance->Next(replacementProductStruct) == CHIP_NO_ERROR)
+ err = aEncoder.EncodeList([productListManagerInstance](const auto & encoder) -> CHIP_ERROR {
+ ReplacementProductStruct replacementProductStruct;
+ CHIP_ERROR iteratorError = productListManagerInstance->Next(replacementProductStruct);
+
+ while (CHIP_NO_ERROR == iteratorError)
{
ReturnErrorOnFailure(encoder.Encode(replacementProductStruct));
+ iteratorError = productListManagerInstance->Next(replacementProductStruct);
}
- return CHIP_NO_ERROR;
+ return (CHIP_ERROR_PROVIDER_LIST_EXHAUSTED == iteratorError) ? CHIP_NO_ERROR : iteratorError;
});
}
- return CHIP_NO_ERROR;
+ return err;
}
// Implements the read functionality for non-standard attributes.
diff --git a/src/app/tests/suites/TestActivatedCarbonFilterMonitoring.yaml b/src/app/tests/suites/TestActivatedCarbonFilterMonitoring.yaml
new file mode 100644
index 0000000..c47e01f
--- /dev/null
+++ b/src/app/tests/suites/TestActivatedCarbonFilterMonitoring.yaml
@@ -0,0 +1,57 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# 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.
+
+name: Activated Carbon Filter Monitoring Cluster Tests
+
+config:
+ nodeId: 0x12344321
+ cluster: "Activated Carbon Filter Monitoring"
+ endpoint: 1
+
+tests:
+ - label: "Wait for the commissioned device to be retrieved"
+ cluster: "DelayCommands"
+ command: "WaitForCommissionee"
+ arguments:
+ values:
+ - name: "nodeId"
+ value: nodeId
+
+ - label: "Read Replacement Product List"
+ command: "readAttribute"
+ attribute: "ReplacementProductList"
+ response:
+ value:
+ [
+ {
+ ProductIdentifierType: 0,
+ ProductIdentifierValue: "111112222233",
+ },
+ {
+ ProductIdentifierType: 1,
+ ProductIdentifierValue: "gtin8xxx",
+ },
+ {
+ ProductIdentifierType: 2,
+ ProductIdentifierValue: "4444455555666",
+ },
+ {
+ ProductIdentifierType: 3,
+ ProductIdentifierValue: "gtin14xxxxxxxx",
+ },
+ {
+ ProductIdentifierType: 4,
+ ProductIdentifierValue: "oem20xxxxxxxxxxxxxxx",
+ },
+ ]
diff --git a/src/app/tests/suites/TestHepaFilterMonitoring.yaml b/src/app/tests/suites/TestHepaFilterMonitoring.yaml
new file mode 100644
index 0000000..44b79ee
--- /dev/null
+++ b/src/app/tests/suites/TestHepaFilterMonitoring.yaml
@@ -0,0 +1,57 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# 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.
+
+name: HEPA Filter Monitoring Cluster Tests
+
+config:
+ nodeId: 0x12344321
+ cluster: "HEPA Filter Monitoring"
+ endpoint: 1
+
+tests:
+ - label: "Wait for the commissioned device to be retrieved"
+ cluster: "DelayCommands"
+ command: "WaitForCommissionee"
+ arguments:
+ values:
+ - name: "nodeId"
+ value: nodeId
+
+ - label: "Read Replacement Product List"
+ command: "readAttribute"
+ attribute: "ReplacementProductList"
+ response:
+ value:
+ [
+ {
+ ProductIdentifierType: 0,
+ ProductIdentifierValue: "111112222233",
+ },
+ {
+ ProductIdentifierType: 1,
+ ProductIdentifierValue: "gtin8xxx",
+ },
+ {
+ ProductIdentifierType: 2,
+ ProductIdentifierValue: "4444455555666",
+ },
+ {
+ ProductIdentifierType: 3,
+ ProductIdentifierValue: "gtin14xxxxxxxx",
+ },
+ {
+ ProductIdentifierType: 4,
+ ProductIdentifierValue: "oem20xxxxxxxxxxxxxxx",
+ },
+ ]
diff --git a/src/app/tests/suites/ciTests.json b/src/app/tests/suites/ciTests.json
index 377dd56..a22aea1 100644
--- a/src/app/tests/suites/ciTests.json
+++ b/src/app/tests/suites/ciTests.json
@@ -303,6 +303,8 @@
],
"Scenes": ["Test_TC_S_1_1"],
"ResourceMonitoring": [
+ "TestActivatedCarbonFilterMonitoring",
+ "TestHepaFilterMonitoring",
"Test_TC_ACFREMON_1_1",
"Test_TC_ACFREMON_2_1",
"Test_TC_HEPAFREMON_1_1",
diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h
index e800416..a07a8e2 100644
--- a/zzz_generated/chip-tool/zap-generated/test/Commands.h
+++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h
@@ -322,6 +322,8 @@
printf("TestGroupKeyManagementCluster\n");
printf("Test_TC_G_1_1\n");
printf("Test_TC_G_2_1\n");
+ printf("TestActivatedCarbonFilterMonitoring\n");
+ printf("TestHepaFilterMonitoring\n");
printf("Test_TC_ACFREMON_1_1\n");
printf("Test_TC_ACFREMON_2_1\n");
printf("Test_TC_HEPAFREMON_1_1\n");
@@ -113646,6 +113648,236 @@
}
};
+class TestActivatedCarbonFilterMonitoringSuite : public TestCommand
+{
+public:
+ TestActivatedCarbonFilterMonitoringSuite(CredentialIssuerCommands * credsIssuerConfig) :
+ TestCommand("TestActivatedCarbonFilterMonitoring", 2, credsIssuerConfig)
+ {
+ AddArgument("nodeId", 0, UINT64_MAX, &mNodeId);
+ AddArgument("cluster", &mCluster);
+ AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint);
+ AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
+ }
+
+ ~TestActivatedCarbonFilterMonitoringSuite() {}
+
+ chip::System::Clock::Timeout GetWaitDuration() const override
+ {
+ return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds));
+ }
+
+private:
+ chip::Optional<chip::NodeId> mNodeId;
+ chip::Optional<chip::CharSpan> mCluster;
+ chip::Optional<chip::EndpointId> mEndpoint;
+ chip::Optional<uint16_t> mTimeout;
+
+ chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; }
+
+ //
+ // Tests methods
+ //
+
+ void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override
+ {
+ bool shouldContinue = false;
+
+ switch (mTestIndex - 1)
+ {
+ case 0:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ shouldContinue = true;
+ break;
+ case 1:
+ 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)));
+ {
+ auto iter_0 = value.begin();
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 0));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[0].productIdentifierType", iter_0.GetValue().productIdentifierType, 0U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[0].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("111112222233", 12)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 1));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[1].productIdentifierType", iter_0.GetValue().productIdentifierType, 1U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[1].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue, chip::CharSpan("gtin8xxx", 8)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 2));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[2].productIdentifierType", iter_0.GetValue().productIdentifierType, 2U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[2].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("4444455555666", 13)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 3));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[3].productIdentifierType", iter_0.GetValue().productIdentifierType, 3U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[3].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("gtin14xxxxxxxx", 14)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 4));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[4].productIdentifierType", iter_0.GetValue().productIdentifierType, 4U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[4].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("oem20xxxxxxxxxxxxxxx", 20)));
+ VerifyOrReturn(CheckNoMoreListItems<decltype(value)>("replacementProductList", iter_0, 5));
+ }
+ }
+ break;
+ default:
+ LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT));
+ }
+
+ if (shouldContinue)
+ {
+ ContinueOnChipMainThread(CHIP_NO_ERROR);
+ }
+ }
+
+ CHIP_ERROR DoTestStep(uint16_t testIndex) override
+ {
+ using namespace chip::app::Clusters;
+ switch (testIndex)
+ {
+ case 0: {
+ LogStep(0, "Wait for the commissioned device to be retrieved");
+ ListFreer listFreer;
+ chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value;
+ value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL;
+ return WaitForCommissionee(kIdentityAlpha, value);
+ }
+ case 1: {
+ LogStep(1, "Read Replacement Product List");
+ return ReadAttribute(kIdentityAlpha, GetEndpoint(1), ActivatedCarbonFilterMonitoring::Id,
+ ActivatedCarbonFilterMonitoring::Attributes::ReplacementProductList::Id, true, chip::NullOptional);
+ }
+ }
+ return CHIP_NO_ERROR;
+ }
+};
+
+class TestHepaFilterMonitoringSuite : public TestCommand
+{
+public:
+ TestHepaFilterMonitoringSuite(CredentialIssuerCommands * credsIssuerConfig) :
+ TestCommand("TestHepaFilterMonitoring", 2, credsIssuerConfig)
+ {
+ AddArgument("nodeId", 0, UINT64_MAX, &mNodeId);
+ AddArgument("cluster", &mCluster);
+ AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint);
+ AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
+ }
+
+ ~TestHepaFilterMonitoringSuite() {}
+
+ chip::System::Clock::Timeout GetWaitDuration() const override
+ {
+ return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds));
+ }
+
+private:
+ chip::Optional<chip::NodeId> mNodeId;
+ chip::Optional<chip::CharSpan> mCluster;
+ chip::Optional<chip::EndpointId> mEndpoint;
+ chip::Optional<uint16_t> mTimeout;
+
+ chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; }
+
+ //
+ // Tests methods
+ //
+
+ void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override
+ {
+ bool shouldContinue = false;
+
+ switch (mTestIndex - 1)
+ {
+ case 0:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ shouldContinue = true;
+ break;
+ case 1:
+ 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)));
+ {
+ auto iter_0 = value.begin();
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 0));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[0].productIdentifierType", iter_0.GetValue().productIdentifierType, 0U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[0].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("111112222233", 12)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 1));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[1].productIdentifierType", iter_0.GetValue().productIdentifierType, 1U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[1].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue, chip::CharSpan("gtin8xxx", 8)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 2));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[2].productIdentifierType", iter_0.GetValue().productIdentifierType, 2U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[2].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("4444455555666", 13)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 3));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[3].productIdentifierType", iter_0.GetValue().productIdentifierType, 3U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[3].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("gtin14xxxxxxxx", 14)));
+ VerifyOrReturn(CheckNextListItemDecodes<decltype(value)>("replacementProductList", iter_0, 4));
+ VerifyOrReturn(
+ CheckValue("replacementProductList[4].productIdentifierType", iter_0.GetValue().productIdentifierType, 4U));
+ VerifyOrReturn(CheckValueAsString("replacementProductList[4].productIdentifierValue",
+ iter_0.GetValue().productIdentifierValue,
+ chip::CharSpan("oem20xxxxxxxxxxxxxxx", 20)));
+ VerifyOrReturn(CheckNoMoreListItems<decltype(value)>("replacementProductList", iter_0, 5));
+ }
+ }
+ break;
+ default:
+ LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT));
+ }
+
+ if (shouldContinue)
+ {
+ ContinueOnChipMainThread(CHIP_NO_ERROR);
+ }
+ }
+
+ CHIP_ERROR DoTestStep(uint16_t testIndex) override
+ {
+ using namespace chip::app::Clusters;
+ switch (testIndex)
+ {
+ case 0: {
+ LogStep(0, "Wait for the commissioned device to be retrieved");
+ ListFreer listFreer;
+ chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value;
+ value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL;
+ return WaitForCommissionee(kIdentityAlpha, value);
+ }
+ case 1: {
+ LogStep(1, "Read Replacement Product List");
+ return ReadAttribute(kIdentityAlpha, GetEndpoint(1), HepaFilterMonitoring::Id,
+ HepaFilterMonitoring::Attributes::ReplacementProductList::Id, true, chip::NullOptional);
+ }
+ }
+ return CHIP_NO_ERROR;
+ }
+};
+
class Test_TC_ACFREMON_1_1Suite : public TestCommand
{
public:
@@ -144954,6 +145186,8 @@
make_unique<TestGroupKeyManagementClusterSuite>(credsIssuerConfig),
make_unique<Test_TC_G_1_1Suite>(credsIssuerConfig),
make_unique<Test_TC_G_2_1Suite>(credsIssuerConfig),
+ make_unique<TestActivatedCarbonFilterMonitoringSuite>(credsIssuerConfig),
+ make_unique<TestHepaFilterMonitoringSuite>(credsIssuerConfig),
make_unique<Test_TC_ACFREMON_1_1Suite>(credsIssuerConfig),
make_unique<Test_TC_ACFREMON_2_1Suite>(credsIssuerConfig),
make_unique<Test_TC_HEPAFREMON_1_1Suite>(credsIssuerConfig),
diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
index 3d69b11..125b351 100644
--- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
+++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
@@ -286,6 +286,8 @@
printf("TestGroupsCluster\n");
printf("TestGroupKeyManagementCluster\n");
printf("Test_TC_G_1_1\n");
+ printf("TestActivatedCarbonFilterMonitoring\n");
+ printf("TestHepaFilterMonitoring\n");
printf("Test_TC_ACFREMON_1_1\n");
printf("Test_TC_ACFREMON_2_1\n");
printf("Test_TC_HEPAFREMON_1_1\n");
@@ -172696,6 +172698,295 @@
}
};
+class TestActivatedCarbonFilterMonitoring : public TestCommandBridge {
+public:
+ // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced
+ TestActivatedCarbonFilterMonitoring()
+ : TestCommandBridge("TestActivatedCarbonFilterMonitoring")
+ , mTestIndex(0)
+ {
+ AddArgument("nodeId", 0, UINT64_MAX, &mNodeId);
+ AddArgument("cluster", &mCluster);
+ AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint);
+ AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
+ }
+ // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull)
+
+ ~TestActivatedCarbonFilterMonitoring() {}
+
+ /////////// TestCommand Interface /////////
+ void NextTest() override
+ {
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (0 == mTestIndex) {
+ ChipLogProgress(chipTool, " **** Test Start: TestActivatedCarbonFilterMonitoring\n");
+ }
+
+ if (mTestCount == mTestIndex) {
+ ChipLogProgress(chipTool, " **** Test Complete: TestActivatedCarbonFilterMonitoring\n");
+ SetCommandExitStatus(CHIP_NO_ERROR);
+ return;
+ }
+
+ Wait();
+
+ // Ensure we increment mTestIndex before we start running the relevant
+ // command. That way if we lose the timeslice after we send the message
+ // but before our function call returns, we won't end up with an
+ // incorrect mTestIndex value observed when we get the response.
+ switch (mTestIndex++) {
+ case 0:
+ ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n");
+ err = TestWaitForTheCommissionedDeviceToBeRetrieved_0();
+ break;
+ case 1:
+ ChipLogProgress(chipTool, " ***** Test Step 1 : Read Replacement Product List\n");
+ err = TestReadReplacementProductList_1();
+ break;
+ }
+
+ if (CHIP_NO_ERROR != err) {
+ ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err));
+ SetCommandExitStatus(err);
+ }
+ }
+
+ void OnStatusUpdate(const chip::app::StatusIB & status) override
+ {
+ switch (mTestIndex - 1) {
+ case 0:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 1:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ }
+
+ // Go on to the next test.
+ ContinueOnChipMainThread(CHIP_NO_ERROR);
+ }
+
+ chip::System::Clock::Timeout GetWaitDuration() const override
+ {
+ return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds));
+ }
+
+private:
+ std::atomic_uint16_t mTestIndex;
+ const uint16_t mTestCount = 2;
+
+ chip::Optional<chip::NodeId> mNodeId;
+ chip::Optional<chip::CharSpan> mCluster;
+ chip::Optional<chip::EndpointId> mEndpoint;
+ chip::Optional<uint16_t> mTimeout;
+
+ CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0()
+ {
+
+ chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value;
+ value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL;
+ return WaitForCommissionee("alpha", value);
+ }
+
+ CHIP_ERROR TestReadReplacementProductList_1()
+ {
+
+ MTRBaseDevice * device = GetDevice("alpha");
+ __auto_type * cluster = [[MTRBaseClusterActivatedCarbonFilterMonitoring alloc] initWithDevice:device
+ endpointID:@(1)
+ queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ [cluster readAttributeReplacementProductListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Read Replacement Product List Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValue("ReplacementProductList", [actualValue count], static_cast<uint32_t>(5)));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[0]).productIdentifierType,
+ 0U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[0]).productIdentifierValue,
+ @"111112222233"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[1]).productIdentifierType,
+ 1U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[1]).productIdentifierValue,
+ @"gtin8xxx"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[2]).productIdentifierType,
+ 2U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[2]).productIdentifierValue,
+ @"4444455555666"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[3]).productIdentifierType,
+ 3U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[3]).productIdentifierValue,
+ @"gtin14xxxxxxxx"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[4]).productIdentifierType,
+ 4U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRActivatedCarbonFilterMonitoringClusterReplacementProductStruct *) actualValue[4]).productIdentifierValue,
+ @"oem20xxxxxxxxxxxxxxx"));
+ }
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+};
+
+class TestHepaFilterMonitoring : public TestCommandBridge {
+public:
+ // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced
+ TestHepaFilterMonitoring()
+ : TestCommandBridge("TestHepaFilterMonitoring")
+ , mTestIndex(0)
+ {
+ AddArgument("nodeId", 0, UINT64_MAX, &mNodeId);
+ AddArgument("cluster", &mCluster);
+ AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint);
+ AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
+ }
+ // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull)
+
+ ~TestHepaFilterMonitoring() {}
+
+ /////////// TestCommand Interface /////////
+ void NextTest() override
+ {
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (0 == mTestIndex) {
+ ChipLogProgress(chipTool, " **** Test Start: TestHepaFilterMonitoring\n");
+ }
+
+ if (mTestCount == mTestIndex) {
+ ChipLogProgress(chipTool, " **** Test Complete: TestHepaFilterMonitoring\n");
+ SetCommandExitStatus(CHIP_NO_ERROR);
+ return;
+ }
+
+ Wait();
+
+ // Ensure we increment mTestIndex before we start running the relevant
+ // command. That way if we lose the timeslice after we send the message
+ // but before our function call returns, we won't end up with an
+ // incorrect mTestIndex value observed when we get the response.
+ switch (mTestIndex++) {
+ case 0:
+ ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n");
+ err = TestWaitForTheCommissionedDeviceToBeRetrieved_0();
+ break;
+ case 1:
+ ChipLogProgress(chipTool, " ***** Test Step 1 : Read Replacement Product List\n");
+ err = TestReadReplacementProductList_1();
+ break;
+ }
+
+ if (CHIP_NO_ERROR != err) {
+ ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err));
+ SetCommandExitStatus(err);
+ }
+ }
+
+ void OnStatusUpdate(const chip::app::StatusIB & status) override
+ {
+ switch (mTestIndex - 1) {
+ case 0:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 1:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ }
+
+ // Go on to the next test.
+ ContinueOnChipMainThread(CHIP_NO_ERROR);
+ }
+
+ chip::System::Clock::Timeout GetWaitDuration() const override
+ {
+ return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds));
+ }
+
+private:
+ std::atomic_uint16_t mTestIndex;
+ const uint16_t mTestCount = 2;
+
+ chip::Optional<chip::NodeId> mNodeId;
+ chip::Optional<chip::CharSpan> mCluster;
+ chip::Optional<chip::EndpointId> mEndpoint;
+ chip::Optional<uint16_t> mTimeout;
+
+ CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0()
+ {
+
+ chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value;
+ value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL;
+ return WaitForCommissionee("alpha", value);
+ }
+
+ CHIP_ERROR TestReadReplacementProductList_1()
+ {
+
+ MTRBaseDevice * device = GetDevice("alpha");
+ __auto_type * cluster = [[MTRBaseClusterHEPAFilterMonitoring alloc] initWithDevice:device
+ endpointID:@(1)
+ queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ [cluster readAttributeReplacementProductListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Read Replacement Product List Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValue("ReplacementProductList", [actualValue count], static_cast<uint32_t>(5)));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[0]).productIdentifierType, 0U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[0]).productIdentifierValue,
+ @"111112222233"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[1]).productIdentifierType, 1U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[1]).productIdentifierValue,
+ @"gtin8xxx"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[2]).productIdentifierType, 2U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[2]).productIdentifierValue,
+ @"4444455555666"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[3]).productIdentifierType, 3U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[3]).productIdentifierValue,
+ @"gtin14xxxxxxxx"));
+ VerifyOrReturn(CheckValue("ProductIdentifierType",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[4]).productIdentifierType, 4U));
+ VerifyOrReturn(CheckValueAsString("ProductIdentifierValue",
+ ((MTRHEPAFilterMonitoringClusterReplacementProductStruct *) actualValue[4]).productIdentifierValue,
+ @"oem20xxxxxxxxxxxxxxx"));
+ }
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+};
+
class Test_TC_ACFREMON_1_1 : public TestCommandBridge {
public:
// NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced
@@ -174471,6 +174762,8 @@
make_unique<TestGroupsCluster>(),
make_unique<TestGroupKeyManagementCluster>(),
make_unique<Test_TC_G_1_1>(),
+ make_unique<TestActivatedCarbonFilterMonitoring>(),
+ make_unique<TestHepaFilterMonitoring>(),
make_unique<Test_TC_ACFREMON_1_1>(),
make_unique<Test_TC_ACFREMON_2_1>(),
make_unique<Test_TC_HEPAFREMON_1_1>(),