[Chef] Fix Read/Write Attributes of AirPurifier's clusters. (#33848)
* Fix TLV Reader in LastChangedTime
* Restyled by whitespace
* Restyled by clang-format
* Fix debug messages
* Using BufferReader / BufferWriter to avoid Endianness
Using BufferReader / BufferWriter to avoid Endianness issue
* Restyled by clang-format
* Fix DegradationDirection Get
---------
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/chef/common/chef-resource-monitoring-delegates.cpp b/examples/chef/common/chef-resource-monitoring-delegates.cpp
deleted file mode 100644
index ca2b713..0000000
--- a/examples/chef/common/chef-resource-monitoring-delegates.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *
- * 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 <chef-resource-monitoring-delegates.h>
-
-using namespace chip;
-using namespace chip::app;
-using namespace chip::app::Clusters;
-using namespace chip::app::Clusters::ResourceMonitoring;
-using namespace chip::app::Clusters::ActivatedCarbonFilterMonitoring;
-using namespace chip::app::Clusters::HepaFilterMonitoring;
-using chip::Protocols::InteractionModel::Status;
-
-const chip::BitMask<ResourceMonitoring::Feature> gHepaFilterFeatureMap(ResourceMonitoring::Feature::kCondition,
- ResourceMonitoring::Feature::kWarning,
- ResourceMonitoring::Feature::kReplacementProductList);
-const chip::BitMask<ResourceMonitoring::Feature> gActivatedCarbonFeatureMap(ResourceMonitoring::Feature::kCondition,
- ResourceMonitoring::Feature::kWarning,
- ResourceMonitoring::Feature::kReplacementProductList);
-
-static std::unique_ptr<ActivatedCarbonFilterMonitoringDelegate> gActivatedCarbonFilterDelegate;
-static std::unique_ptr<ResourceMonitoring::Instance> gActivatedCarbonFilterInstance;
-
-static std::unique_ptr<HepaFilterMonitoringDelegate> gHepaFilterDelegate;
-static std::unique_ptr<ResourceMonitoring::Instance> gHepaFilterInstance;
-
-static ImmutableReplacementProductListManager sReplacementProductListManager;
-
-//-- Activated Carbon Filter Monitoring delegate methods
-CHIP_ERROR ActivatedCarbonFilterMonitoringDelegate::Init()
-{
- ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::Init()");
- GetInstance()->SetReplacementProductListManagerInstance(&sReplacementProductListManager);
- return CHIP_NO_ERROR;
-}
-
-Status ActivatedCarbonFilterMonitoringDelegate::PreResetCondition()
-{
- ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::PreResetCondition()");
- return Status::Success;
-}
-
-Status ActivatedCarbonFilterMonitoringDelegate::PostResetCondition()
-{
- ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::PostResetCondition()");
- return Status::Success;
-}
-
-void ActivatedCarbonFilterMonitoring::Shutdown()
-{
- gActivatedCarbonFilterInstance.reset();
- gActivatedCarbonFilterDelegate.reset();
-}
-
-//-- Hepa Filter Monitoring delegate methods
-CHIP_ERROR HepaFilterMonitoringDelegate::Init()
-{
- ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::Init()");
- GetInstance()->SetReplacementProductListManagerInstance(&sReplacementProductListManager);
- return CHIP_NO_ERROR;
-}
-
-Status HepaFilterMonitoringDelegate::PreResetCondition()
-{
- ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::PreResetCondition()");
- return Status::Success;
-}
-
-Status HepaFilterMonitoringDelegate::PostResetCondition()
-{
- ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::PostResetCondition()");
- return Status::Success;
-}
-
-void HepaFilterMonitoring::Shutdown()
-{
- gHepaFilterInstance.reset();
- gHepaFilterDelegate.reset();
-}
-
-void emberAfActivatedCarbonFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
-{
- VerifyOrDie(!gActivatedCarbonFilterInstance && !gActivatedCarbonFilterDelegate);
- gActivatedCarbonFilterDelegate = std::make_unique<ActivatedCarbonFilterMonitoringDelegate>();
- bool bResetConditionCommandSupported = true; // The ResetCondition command is supported by the ResourceMonitor cluster
- gActivatedCarbonFilterInstance = std::make_unique<ResourceMonitoring::Instance>(
- gActivatedCarbonFilterDelegate.get(), endpoint, ActivatedCarbonFilterMonitoring::Id,
- static_cast<uint32_t>(gActivatedCarbonFeatureMap.Raw()), ResourceMonitoring::DegradationDirectionEnum::kDown,
- bResetConditionCommandSupported);
- gActivatedCarbonFilterInstance->Init();
-}
-
-void emberAfHepaFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
-{
- VerifyOrDie(!gHepaFilterInstance && !gHepaFilterDelegate);
-
- gHepaFilterDelegate = std::make_unique<HepaFilterMonitoringDelegate>();
- bool bResetConditionCommandSupported = true; // The ResetCondition command is supported by the ResourceMonitor cluster
- gHepaFilterInstance = std::make_unique<ResourceMonitoring::Instance>(
- gHepaFilterDelegate.get(), endpoint, HepaFilterMonitoring::Id, static_cast<uint32_t>(gHepaFilterFeatureMap.Raw()),
- ResourceMonitoring::DegradationDirectionEnum::kDown, bResetConditionCommandSupported);
- 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;
- }
- mIndex++;
- return CHIP_NO_ERROR;
-}
diff --git a/examples/chef/common/chef-resource-monitoring-delegates.h b/examples/chef/common/chef-resource-monitoring-delegates.h
deleted file mode 100644
index f161be0..0000000
--- a/examples/chef/common/chef-resource-monitoring-delegates.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *
- * 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>
-
-namespace chip {
-namespace app {
-namespace Clusters {
-
-namespace ActivatedCarbonFilterMonitoring {
-class ActivatedCarbonFilterMonitoringDelegate : public ResourceMonitoring::Delegate
-{
-private:
- CHIP_ERROR Init() override;
- chip::Protocols::InteractionModel::Status PreResetCondition() override;
- chip::Protocols::InteractionModel::Status PostResetCondition() override;
-
-public:
- ~ActivatedCarbonFilterMonitoringDelegate() override = default;
-};
-
-void Shutdown();
-
-} // namespace ActivatedCarbonFilterMonitoring
-
-namespace HepaFilterMonitoring {
-class HepaFilterMonitoringDelegate : public ResourceMonitoring::Delegate
-{
-private:
- CHIP_ERROR Init() override;
- chip::Protocols::InteractionModel::Status PreResetCondition() override;
- chip::Protocols::InteractionModel::Status PostResetCondition() override;
-
-public:
- ~HepaFilterMonitoringDelegate() override = default;
-};
-
-class ImmutableReplacementProductListManager : public ResourceMonitoring::ReplacementProductListManager
-{
-public:
- CHIP_ERROR
- Next(chip::app::Clusters::ResourceMonitoring::ReplacementProductStruct & item) override;
-};
-
-void Shutdown();
-
-} // namespace HepaFilterMonitoring
-
-} // namespace Clusters
-} // namespace app
-} // namespace chip
diff --git a/examples/chef/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.cpp b/examples/chef/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.cpp
new file mode 100644
index 0000000..9b0f6d8
--- /dev/null
+++ b/examples/chef/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.cpp
@@ -0,0 +1,311 @@
+/*
+ *
+ * Copyright (c) 2024 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 <lib/core/TLVReader.h>
+#include <lib/support/BufferReader.h>
+#include <lib/support/BufferWriter.h>
+#include <resource-monitoring/chef-resource-monitoring-delegates.h>
+#include <utility>
+
+using namespace chip;
+using namespace chip::app;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::ResourceMonitoring;
+using namespace chip::app::Clusters::ActivatedCarbonFilterMonitoring;
+using namespace chip::app::Clusters::HepaFilterMonitoring;
+using chip::Protocols::InteractionModel::Status;
+
+const chip::BitMask<ResourceMonitoring::Feature> gHepaFilterFeatureMap(ResourceMonitoring::Feature::kCondition,
+ ResourceMonitoring::Feature::kWarning,
+ ResourceMonitoring::Feature::kReplacementProductList);
+const chip::BitMask<ResourceMonitoring::Feature> gActivatedCarbonFeatureMap(ResourceMonitoring::Feature::kCondition,
+ ResourceMonitoring::Feature::kWarning,
+ ResourceMonitoring::Feature::kReplacementProductList);
+
+static std::unique_ptr<ActivatedCarbonFilterMonitoringDelegate> gActivatedCarbonFilterDelegate;
+static std::unique_ptr<ResourceMonitoring::ChefResourceMonitorInstance> gActivatedCarbonFilterInstance;
+
+static std::unique_ptr<HepaFilterMonitoringDelegate> gHepaFilterDelegate;
+static std::unique_ptr<ResourceMonitoring::ChefResourceMonitorInstance> gHepaFilterInstance;
+
+static ImmutableReplacementProductListManager sReplacementProductListManager;
+
+//-- Activated Carbon Filter Monitoring delegate methods
+CHIP_ERROR ActivatedCarbonFilterMonitoringDelegate::Init()
+{
+ ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::Init()");
+ GetInstance()->SetReplacementProductListManagerInstance(&sReplacementProductListManager);
+ return CHIP_NO_ERROR;
+}
+
+Status ActivatedCarbonFilterMonitoringDelegate::PreResetCondition()
+{
+ ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::PreResetCondition()");
+ return Status::Success;
+}
+
+Status ActivatedCarbonFilterMonitoringDelegate::PostResetCondition()
+{
+ ChipLogDetail(Zcl, "ActivatedCarbonFilterMonitoringDelegate::PostResetCondition()");
+ return Status::Success;
+}
+
+void ActivatedCarbonFilterMonitoring::Shutdown()
+{
+ gActivatedCarbonFilterInstance.reset();
+ gActivatedCarbonFilterDelegate.reset();
+}
+
+//-- Hepa Filter Monitoring delegate methods
+CHIP_ERROR HepaFilterMonitoringDelegate::Init()
+{
+ ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::Init()");
+ GetInstance()->SetReplacementProductListManagerInstance(&sReplacementProductListManager);
+ return CHIP_NO_ERROR;
+}
+
+Status HepaFilterMonitoringDelegate::PreResetCondition()
+{
+ ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::PreResetCondition()");
+ return Status::Success;
+}
+
+Status HepaFilterMonitoringDelegate::PostResetCondition()
+{
+ ChipLogDetail(Zcl, "HepaFilterMonitoringDelegate::PostResetCondition()");
+ return Status::Success;
+}
+
+void HepaFilterMonitoring::Shutdown()
+{
+ gHepaFilterInstance.reset();
+ gHepaFilterDelegate.reset();
+}
+
+chip::Protocols::InteractionModel::Status
+ChefResourceMonitorInstance::ExternalAttributeWrite(const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer)
+{
+ Protocols::InteractionModel::Status ret = Protocols::InteractionModel::Status::Success;
+ AttributeId attributeId = attributeMetadata->attributeId;
+
+ switch (attributeId)
+ {
+ case HepaFilterMonitoring::Attributes::Condition::Id: {
+ uint8_t newCondition = *(uint8_t *) buffer;
+ ret = UpdateCondition(newCondition);
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::ChangeIndication::Id: {
+ ResourceMonitoring::ChangeIndicationEnum newIndication =
+ static_cast<ResourceMonitoring::ChangeIndicationEnum>(*(uint8_t *) buffer);
+ ret = UpdateChangeIndication(newIndication);
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::InPlaceIndicator::Id: {
+ bool newInPlaceIndicator = *(bool *) buffer;
+ ret = UpdateInPlaceIndicator(newInPlaceIndicator);
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::LastChangedTime::Id: {
+ // We already know the input is a buffer started with a uint16_t as the length
+ chip::Encoding::LittleEndian::Reader bufReader(buffer, sizeof(uint16_t));
+ uint16_t tlvLen;
+ VerifyOrReturnError(CHIP_NO_ERROR == bufReader.Read16(&tlvLen).StatusCode(),
+ Protocols::InteractionModel::Status::UnsupportedWrite);
+
+ // Read from TLV
+ uint32_t newValue = 0;
+ chip::TLV::TLVReader tlvReader;
+ tlvReader.Init(buffer + sizeof(uint16_t), tlvLen);
+ tlvReader.Next();
+ tlvReader.Get(newValue);
+ DataModel::Nullable<uint32_t> newLastChangedTime = DataModel::MakeNullable(newValue);
+ ret = UpdateLastChangedTime(newLastChangedTime);
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::DegradationDirection::Id:
+ default: {
+ ChipLogError(Zcl, "Unsupported External Attribute Write: %d", static_cast<int>(attributeId));
+ ret = Protocols::InteractionModel::Status::UnsupportedWrite;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+void emberAfActivatedCarbonFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
+{
+ VerifyOrDie(!gActivatedCarbonFilterInstance && !gActivatedCarbonFilterDelegate);
+
+ bool bResetConditionCommandSupported = true; // The ResetCondition command is supported by the ResourceMonitor cluster
+ gActivatedCarbonFilterDelegate = std::make_unique<ActivatedCarbonFilterMonitoringDelegate>();
+ gActivatedCarbonFilterInstance = std::make_unique<ResourceMonitoring::ChefResourceMonitorInstance>(
+ gActivatedCarbonFilterDelegate.get(), endpoint, ActivatedCarbonFilterMonitoring::Id,
+ static_cast<uint32_t>(gActivatedCarbonFeatureMap.Raw()), ResourceMonitoring::DegradationDirectionEnum::kDown,
+ bResetConditionCommandSupported);
+ gActivatedCarbonFilterInstance->Init();
+}
+
+chip::Protocols::InteractionModel::Status
+chefResourceMonitoringExternalWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId,
+ const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer)
+{
+ Protocols::InteractionModel::Status ret = Protocols::InteractionModel::Status::Success;
+ AttributeId attributeId = attributeMetadata->attributeId;
+ ChipLogProgress(Zcl, "chefResourceMonitoringExternalWriteCallback EP: %d, Cluster: %04x, Att: %04x", static_cast<int>(endpoint),
+ static_cast<int>(clusterId), static_cast<int>(attributeId));
+
+ switch (clusterId)
+ {
+ case HepaFilterMonitoring::Id:
+ ret = gHepaFilterInstance->ExternalAttributeWrite(attributeMetadata, buffer);
+ break;
+ case ActivatedCarbonFilterMonitoring::Id:
+ ret = gActivatedCarbonFilterInstance->ExternalAttributeWrite(attributeMetadata, buffer);
+ break;
+ default:
+ ret = Protocols::InteractionModel::Status::UnsupportedWrite;
+ break;
+ }
+
+ return ret;
+}
+
+chip::Protocols::InteractionModel::Status
+chefResourceMonitoringExternalReadCallback(chip::EndpointId endpoint, chip::ClusterId clusterId,
+ const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
+ uint16_t maxReadLength)
+{
+ Protocols::InteractionModel::Status ret = Protocols::InteractionModel::Status::Success;
+ AttributeId attributeId = attributeMetadata->attributeId;
+ ChipLogProgress(Zcl, "chefResourceMonitoringExternalReadCallback EP: %d, Cluster: %d, Att: %d", static_cast<int>(endpoint),
+ static_cast<int>(clusterId), static_cast<int>(attributeId));
+
+ switch (clusterId)
+ {
+ case HepaFilterMonitoring::Id:
+ ret = gHepaFilterInstance->ExternalAttributeRead(attributeMetadata, buffer, maxReadLength);
+ break;
+ case ActivatedCarbonFilterMonitoring::Id:
+ ret = gActivatedCarbonFilterInstance->ExternalAttributeRead(attributeMetadata, buffer, maxReadLength);
+ break;
+ default:
+ ret = Protocols::InteractionModel::Status::UnsupportedRead;
+ break;
+ }
+
+ return ret;
+}
+
+chip::Protocols::InteractionModel::Status
+ChefResourceMonitorInstance::ExternalAttributeRead(const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
+ uint16_t maxReadLength)
+{
+ Protocols::InteractionModel::Status ret = Protocols::InteractionModel::Status::Success;
+ AttributeId attributeId = attributeMetadata->attributeId;
+
+ switch (attributeId)
+ {
+ case HepaFilterMonitoring::Attributes::Condition::Id: {
+ *buffer = GetCondition();
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::ChangeIndication::Id: {
+ ResourceMonitoring::ChangeIndicationEnum changeIndication = GetChangeIndication();
+ // The underlying type of ResourceMonitoring::ChangeIndicationEnum is uint8_t
+ *buffer = to_underlying(changeIndication);
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::InPlaceIndicator::Id: {
+ *(bool *) buffer = GetInPlaceIndicator();
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::LastChangedTime::Id: {
+ // Only LastChangedTime needs to handle Endianness
+ DataModel::Nullable<uint32_t> lastChangedTime = GetLastChangedTime();
+ chip::Encoding::LittleEndian::BufferWriter bufWriter(buffer, sizeof(uint16_t));
+
+ bufWriter.Put32(lastChangedTime.IsNull() ? 0 : lastChangedTime.Value());
+ }
+ break;
+ case HepaFilterMonitoring::Attributes::DegradationDirection::Id: {
+ ResourceMonitoring::DegradationDirectionEnum degradationDirection = GetDegradationDirection();
+ // The underlying type of ResourceMonitoring::DegradationDirectionEnum is uint8_t
+ *buffer = to_underlying(degradationDirection);
+ }
+ break;
+ default:
+ ChipLogError(Zcl, "Unsupported External Attribute Read: %d", static_cast<int>(attributeId));
+ ret = Protocols::InteractionModel::Status::UnsupportedRead;
+ break;
+ }
+
+ return ret;
+}
+
+void emberAfHepaFilterMonitoringClusterInitCallback(chip::EndpointId endpoint)
+{
+ VerifyOrDie(!gHepaFilterInstance && !gHepaFilterDelegate);
+
+ bool bResetConditionCommandSupported = true; // The ResetCondition command is supported by the ResourceMonitor cluster
+ gHepaFilterDelegate = std::make_unique<HepaFilterMonitoringDelegate>();
+ gHepaFilterInstance = std::make_unique<ResourceMonitoring::ChefResourceMonitorInstance>(
+ gHepaFilterDelegate.get(), endpoint, HepaFilterMonitoring::Id, static_cast<uint32_t>(gHepaFilterFeatureMap.Raw()),
+ ResourceMonitoring::DegradationDirectionEnum::kDown, bResetConditionCommandSupported);
+ 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;
+ }
+ mIndex++;
+ return CHIP_NO_ERROR;
+}
diff --git a/examples/chef/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.h b/examples/chef/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.h
new file mode 100644
index 0000000..2334be9
--- /dev/null
+++ b/examples/chef/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.h
@@ -0,0 +1,97 @@
+/*
+ *
+ * Copyright (c) 2024 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>
+
+namespace chip {
+namespace app {
+namespace Clusters {
+
+namespace ResourceMonitoring {
+
+// Inherit ResourceMonitoring class to able to write external attributes
+class ChefResourceMonitorInstance : public ResourceMonitoring::Instance
+{
+public:
+ ChefResourceMonitorInstance(Delegate * aDelegate, EndpointId aEndpointId, ClusterId aClusterId, uint32_t aFeatureMap,
+ ResourceMonitoring::Attributes::DegradationDirection::TypeInfo::Type aDegradationDirection,
+ bool aResetConditionCommandSupported) :
+ ResourceMonitoring::Instance(aDelegate, aEndpointId, aClusterId, aFeatureMap, aDegradationDirection,
+ aResetConditionCommandSupported){};
+
+ chip::Protocols::InteractionModel::Status ExternalAttributeWrite(const EmberAfAttributeMetadata * attributeMetadata,
+ uint8_t * buffer);
+ chip::Protocols::InteractionModel::Status ExternalAttributeRead(const EmberAfAttributeMetadata * attributeMetadata,
+ uint8_t * buffer, uint16_t maxReadLength);
+};
+
+} // namespace ResourceMonitoring
+
+namespace HepaFilterMonitoring {
+class HepaFilterMonitoringDelegate : public ResourceMonitoring::Delegate
+{
+private:
+ CHIP_ERROR Init() override;
+ chip::Protocols::InteractionModel::Status PreResetCondition() override;
+ chip::Protocols::InteractionModel::Status PostResetCondition() override;
+
+public:
+ ~HepaFilterMonitoringDelegate() override = default;
+};
+
+class ImmutableReplacementProductListManager : public ResourceMonitoring::ReplacementProductListManager
+{
+public:
+ CHIP_ERROR
+ Next(chip::app::Clusters::ResourceMonitoring::ReplacementProductStruct & item) override;
+};
+
+void Shutdown();
+
+} // namespace HepaFilterMonitoring
+
+namespace ActivatedCarbonFilterMonitoring {
+class ActivatedCarbonFilterMonitoringDelegate : public ResourceMonitoring::Delegate
+{
+private:
+ CHIP_ERROR Init() override;
+ chip::Protocols::InteractionModel::Status PreResetCondition() override;
+ chip::Protocols::InteractionModel::Status PostResetCondition() override;
+
+public:
+ ~ActivatedCarbonFilterMonitoringDelegate() override = default;
+};
+
+void Shutdown();
+
+} // namespace ActivatedCarbonFilterMonitoring
+
+} // namespace Clusters
+} // namespace app
+} // namespace chip
+
+chip::Protocols::InteractionModel::Status
+chefResourceMonitoringExternalWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId,
+ const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer);
+
+chip::Protocols::InteractionModel::Status
+chefResourceMonitoringExternalReadCallback(chip::EndpointId endpoint, chip::ClusterId clusterId,
+ const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
+ uint16_t maxReadLength);
diff --git a/examples/chef/common/stubs.cpp b/examples/chef/common/stubs.cpp
index c0935df..8771bf7 100644
--- a/examples/chef/common/stubs.cpp
+++ b/examples/chef/common/stubs.cpp
@@ -18,6 +18,9 @@
defined(MATTER_DM_PLUGIN_RADON_CONCENTRATION_MEASUREMENT_SERVER)
#include "chef-concentration-measurement.h"
#endif
+#if defined(MATTER_DM_PLUGIN_HEPA_FILTER_MONITORING_SERVER) || defined(MATTER_DM_PLUGIN_ACTIVATED_CARBON_FILTER_MONITORING_SERVER)
+#include "resource-monitoring/chef-resource-monitoring-delegates.h"
+#endif
#if defined(MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER) || defined(MATTER_DM_PLUGIN_RVC_CLEAN_MODE_SERVER)
#include "chef-rvc-mode-delegate.h"
@@ -65,6 +68,11 @@
case chip::app::Clusters::TotalVolatileOrganicCompoundsConcentrationMeasurement::Id:
return chefConcentrationMeasurementReadCallback(endpoint, clusterId, attributeMetadata, buffer, maxReadLength);
#endif
+#if defined(MATTER_DM_PLUGIN_HEPA_FILTER_MONITORING_SERVER) || defined(MATTER_DM_PLUGIN_ACTIVATED_CARBON_FILTER_MONITORING_SERVER)
+ case chip::app::Clusters::HepaFilterMonitoring::Id:
+ case chip::app::Clusters::ActivatedCarbonFilterMonitoring::Id:
+ return chefResourceMonitoringExternalReadCallback(endpoint, clusterId, attributeMetadata, buffer, maxReadLength);
+#endif
#ifdef MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
case chip::app::Clusters::RvcRunMode::Id:
return chefRvcRunModeReadCallback(endpoint, clusterId, attributeMetadata, buffer, maxReadLength);
@@ -125,6 +133,11 @@
case chip::app::Clusters::TotalVolatileOrganicCompoundsConcentrationMeasurement::Id:
return chefConcentrationMeasurementWriteCallback(endpoint, clusterId, attributeMetadata, buffer);
#endif
+#if defined(MATTER_DM_PLUGIN_HEPA_FILTER_MONITORING_SERVER) || defined(MATTER_DM_PLUGIN_ACTIVATED_CARBON_FILTER_MONITORING_SERVER)
+ case chip::app::Clusters::HepaFilterMonitoring::Id:
+ case chip::app::Clusters::ActivatedCarbonFilterMonitoring::Id:
+ return chefResourceMonitoringExternalWriteCallback(endpoint, clusterId, attributeMetadata, buffer);
+#endif
#ifdef MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
case chip::app::Clusters::RvcRunMode::Id:
return chefRvcRunModeWriteCallback(endpoint, clusterId, attributeMetadata, buffer);
diff --git a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter
index 2ec8dae..21d3d20 100644
--- a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter
+++ b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter
@@ -51,6 +51,78 @@
command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64;
}
+/** Attributes and commands for switching devices between 'On' and 'Off' states. */
+cluster OnOff = 6 {
+ revision 6;
+
+ enum DelayedAllOffEffectVariantEnum : enum8 {
+ kDelayedOffFastFade = 0;
+ kNoFade = 1;
+ kDelayedOffSlowFade = 2;
+ }
+
+ enum DyingLightEffectVariantEnum : enum8 {
+ kDyingLightFadeOff = 0;
+ }
+
+ enum EffectIdentifierEnum : enum8 {
+ kDelayedAllOff = 0;
+ kDyingLight = 1;
+ }
+
+ enum StartUpOnOffEnum : enum8 {
+ kOff = 0;
+ kOn = 1;
+ kToggle = 2;
+ }
+
+ bitmap Feature : bitmap32 {
+ kLighting = 0x1;
+ kDeadFrontBehavior = 0x2;
+ kOffOnly = 0x4;
+ }
+
+ bitmap OnOffControlBitmap : bitmap8 {
+ kAcceptOnlyWhenOn = 0x1;
+ }
+
+ readonly attribute boolean onOff = 0;
+ readonly attribute optional boolean globalSceneControl = 16384;
+ attribute optional int16u onTime = 16385;
+ attribute optional int16u offWaitTime = 16386;
+ attribute access(write: manage) optional nullable StartUpOnOffEnum startUpOnOff = 16387;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct OffWithEffectRequest {
+ EffectIdentifierEnum effectIdentifier = 0;
+ enum8 effectVariant = 1;
+ }
+
+ request struct OnWithTimedOffRequest {
+ OnOffControlBitmap onOffControl = 0;
+ int16u onTime = 1;
+ int16u offWaitTime = 2;
+ }
+
+ /** On receipt of this command, a device SHALL enter its ‘Off’ state. This state is device dependent, but it is recommended that it is used for power off or similar functions. On receipt of the Off command, the OnTime attribute SHALL be set to 0. */
+ command Off(): DefaultSuccess = 0;
+ /** On receipt of this command, a device SHALL enter its ‘On’ state. This state is device dependent, but it is recommended that it is used for power on or similar functions. On receipt of the On command, if the value of the OnTime attribute is equal to 0, the device SHALL set the OffWaitTime attribute to 0. */
+ command On(): DefaultSuccess = 1;
+ /** On receipt of this command, if a device is in its ‘Off’ state it SHALL enter its ‘On’ state. Otherwise, if it is in its ‘On’ state it SHALL enter its ‘Off’ state. On receipt of the Toggle command, if the value of the OnOff attribute is equal to FALSE and if the value of the OnTime attribute is equal to 0, the device SHALL set the OffWaitTime attribute to 0. If the value of the OnOff attribute is equal to TRUE, the OnTime attribute SHALL be set to 0. */
+ command Toggle(): DefaultSuccess = 2;
+ /** The OffWithEffect command allows devices to be turned off using enhanced ways of fading. */
+ command OffWithEffect(OffWithEffectRequest): DefaultSuccess = 64;
+ /** The OnWithRecallGlobalScene command allows the recall of the settings when the device was turned off. */
+ command OnWithRecallGlobalScene(): DefaultSuccess = 65;
+ /** The OnWithTimedOff command allows devices to be turned on for a specific duration with a guarded off duration so that SHOULD the device be subsequently switched off, further OnWithTimedOff commands, received during this time, are prevented from turning the devices back on. */
+ command OnWithTimedOff(OnWithTimedOffRequest): DefaultSuccess = 66;
+}
+
/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */
cluster Descriptor = 29 {
revision 2;
@@ -1552,6 +1624,20 @@
handle command Identify;
}
+ server cluster OnOff {
+ ram attribute onOff default = 0;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute eventList;
+ callback attribute attributeList;
+ ram attribute featureMap default = 0;
+ ram attribute clusterRevision default = 6;
+
+ handle command Off;
+ handle command On;
+ handle command Toggle;
+ }
+
server cluster Descriptor {
callback attribute deviceTypeList;
callback attribute serverList;
@@ -1578,6 +1664,8 @@
callback attribute attributeList;
callback attribute featureMap;
ram attribute clusterRevision default = 1;
+
+ handle command ResetCondition;
}
server cluster ActivatedCarbonFilterMonitoring {
diff --git a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap
index 4e5b324..fc392ea 100644
--- a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap
+++ b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap
@@ -1,6 +1,6 @@
{
"fileFormat": 2,
- "featureLevel": 100,
+ "featureLevel": 102,
"creator": "zap",
"keyValuePairs": [
{
@@ -29,6 +29,7 @@
"pathRelativity": "relativeToZap",
"path": "../../../src/app/zap-templates/app-templates.json",
"type": "gen-templates-json",
+ "category": "matter",
"version": "chip-v1"
}
],
@@ -2469,6 +2470,154 @@
]
},
{
+ "name": "On/Off",
+ "code": 6,
+ "mfgCode": null,
+ "define": "ON_OFF_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "Off",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "On",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "Toggle",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "OnOff",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "GeneratedCommandList",
+ "code": 65528,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AcceptedCommandList",
+ "code": 65529,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "EventList",
+ "code": 65530,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AttributeList",
+ "code": 65531,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "6",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
"name": "Descriptor",
"code": 29,
"mfgCode": null,
@@ -2645,6 +2794,16 @@
"define": "HEPA_FILTER_MONITORING_CLUSTER",
"side": "server",
"enabled": 1,
+ "commands": [
+ {
+ "name": "ResetCondition",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ }
+ ],
"attributes": [
{
"name": "Condition",
@@ -2836,7 +2995,7 @@
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
- "reportableChange": 0
+ "reportableChange": 1
}
]
},
diff --git a/examples/chef/esp32/main/CMakeLists.txt b/examples/chef/esp32/main/CMakeLists.txt
index c6b37a0..1614669 100644
--- a/examples/chef/esp32/main/CMakeLists.txt
+++ b/examples/chef/esp32/main/CMakeLists.txt
@@ -70,6 +70,7 @@
"${CMAKE_SOURCE_DIR}/../common/clusters/low-power/"
"${CMAKE_SOURCE_DIR}/../common/clusters/media-input/"
"${CMAKE_SOURCE_DIR}/../common/clusters/media-playback/"
+ "${CMAKE_SOURCE_DIR}/../common/clusters/resource-monitoring/"
"${CMAKE_SOURCE_DIR}/../common/clusters/switch/"
"${CMAKE_SOURCE_DIR}/../common/clusters/target-navigator/"
"${CMAKE_SOURCE_DIR}/../common/clusters/wake-on-lan/"
diff --git a/examples/chef/linux/BUILD.gn b/examples/chef/linux/BUILD.gn
index ce0bed5..c9c0be1 100644
--- a/examples/chef/linux/BUILD.gn
+++ b/examples/chef/linux/BUILD.gn
@@ -46,7 +46,6 @@
"${project_dir}/common/chef-laundry-washer-controls-delegate-impl.cpp",
"${project_dir}/common/chef-laundry-washer-mode.cpp",
"${project_dir}/common/chef-operational-state-delegate-impl.cpp",
- "${project_dir}/common/chef-resource-monitoring-delegates.cpp",
"${project_dir}/common/chef-rpc-actions-worker.cpp",
"${project_dir}/common/chef-rvc-mode-delegate.cpp",
"${project_dir}/common/chef-rvc-operational-state-delegate.cpp",
@@ -59,6 +58,7 @@
"${project_dir}/common/clusters/low-power/LowPowerManager.cpp",
"${project_dir}/common/clusters/media-input/MediaInputManager.cpp",
"${project_dir}/common/clusters/media-playback/MediaPlaybackManager.cpp",
+ "${project_dir}/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.cpp",
"${project_dir}/common/clusters/switch/SwitchEventHandler.cpp",
"${project_dir}/common/clusters/switch/SwitchManager.cpp",
"${project_dir}/common/clusters/target-navigator/TargetNavigatorManager.cpp",
diff --git a/examples/chef/nrfconnect/CMakeLists.txt b/examples/chef/nrfconnect/CMakeLists.txt
index a22f6b6..98f5cde 100644
--- a/examples/chef/nrfconnect/CMakeLists.txt
+++ b/examples/chef/nrfconnect/CMakeLists.txt
@@ -87,7 +87,6 @@
${CHEF}/common/chef-laundry-washer-controls-delegate-impl.cpp
${CHEF}/common/chef-laundry-washer-mode.cpp
${CHEF}/common/chef-operational-state-delegate-impl.cpp
- ${CHEF}/common/chef-resource-monitoring-delegates.cpp
${CHEF}/common/chef-rvc-mode-delegate.cpp
${CHEF}/common/chef-rvc-operational-state-delegate.cpp
${CHEF}/common/clusters/audio-output/AudioOutputManager.cpp
@@ -99,6 +98,7 @@
${CHEF}/common/clusters/low-power/LowPowerManager.cpp
${CHEF}/common/clusters/media-input/MediaInputManager.cpp
${CHEF}/common/clusters/media-playback/MediaPlaybackManager.cpp
+ ${CHEF}/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.cpp
${CHEF}/common/clusters/switch/SwitchEventHandler.cpp
${CHEF}/common/clusters/switch/SwitchManager.cpp
${CHEF}/common/clusters/target-navigator/TargetNavigatorManager.cpp