| /* |
| * |
| * 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 "concentration-measurement-cluster-objects.h" |
| #include <app/AttributeAccessInterface.h> |
| #include <app/data-model/Nullable.h> |
| #include <app/reporting/reporting.h> |
| #include <app/util/af.h> |
| #include <app/util/attribute-storage.h> |
| #include <lib/support/IntrusiveList.h> |
| #include <type_traits> |
| |
| namespace chip { |
| namespace app { |
| namespace Clusters { |
| namespace ConcentrationMeasurement { |
| |
| namespace Detail { |
| |
| struct DummyNumericMeasurementMembers |
| { |
| }; |
| |
| struct DummyPeakMeasurementMembers |
| { |
| }; |
| |
| struct DummyAverageMeasurementMembers |
| { |
| }; |
| |
| struct DummyLevelIndicationMembers |
| { |
| }; |
| |
| class NumericMeasurementMembers |
| { |
| protected: |
| DataModel::Nullable<float> mMeasuredValue; |
| DataModel::Nullable<float> mMinMeasuredValue; |
| DataModel::Nullable<float> mMaxMeasuredValue; |
| MeasurementUnitEnum mMeasurementUnit; |
| float mUncertainty; |
| }; |
| |
| class PeakMeasurementMembers |
| { |
| protected: |
| DataModel::Nullable<float> mPeakMeasuredValue; |
| uint32_t mPeakMeasuredValueWindow; |
| }; |
| |
| class AverageMeasurementMembers |
| { |
| protected: |
| DataModel::Nullable<float> mAverageMeasuredValue; |
| uint32_t mAverageMeasuredValueWindow; |
| }; |
| |
| class LevelIndicationMembers |
| { |
| protected: |
| LevelValueEnum mLevel; |
| }; |
| |
| } // namespace Detail |
| |
| /** |
| * This class provides the base implementation for the server side of the Concentration Measurement cluster as well as an API for |
| * setting the values of the attributes. |
| * |
| * @tparam NumericMeasurementEnabled whether the cluster supports numeric measurement |
| * @tparam LevelIndicationEnabled whether the cluster supports level indication |
| * @tparam MediumLevelEnabled whether the Level Indication Feature supports medium level |
| * @tparam CriticalLevelEnabled whether the Level Indication Feature supports critical level |
| * @tparam PeakMeasurementEnabled whether the Numeric Measurement Feature supports peak measurement |
| * @tparam AverageMeasurementEnabled whether the Numeric Measurement Feature supports average measurement |
| */ |
| template <bool NumericMeasurementEnabled, bool LevelIndicationEnabled, bool MediumLevelEnabled, bool CriticalLevelEnabled, |
| bool PeakMeasurementEnabled, bool AverageMeasurementEnabled> |
| class Instance |
| : public AttributeAccessInterface, |
| protected std::conditional_t<NumericMeasurementEnabled, Detail::NumericMeasurementMembers, |
| Detail::DummyNumericMeasurementMembers>, |
| protected std::conditional_t<PeakMeasurementEnabled, Detail::PeakMeasurementMembers, Detail::DummyPeakMeasurementMembers>, |
| protected std::conditional_t<AverageMeasurementEnabled, Detail::AverageMeasurementMembers, |
| Detail::DummyAverageMeasurementMembers>, |
| protected std::conditional_t<LevelIndicationEnabled, Detail::LevelIndicationMembers, Detail::DummyLevelIndicationMembers> |
| { |
| private: |
| static const int WINDOW_MAX = 604800; |
| |
| EndpointId mEndpointId{}; |
| ClusterId mClusterId{}; |
| |
| MeasurementMediumEnum mMeasurementMedium; |
| |
| uint32_t mFeatureMap = 0; |
| |
| // AttributeAccessInterface |
| CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override |
| { |
| switch (aPath.mAttributeId) |
| { |
| case Attributes::MeasuredValue::Id: |
| if constexpr (NumericMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mMeasuredValue)); |
| } |
| break; |
| |
| case Attributes::MinMeasuredValue::Id: |
| if constexpr (NumericMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mMinMeasuredValue)); |
| } |
| break; |
| |
| case Attributes::MaxMeasuredValue::Id: |
| if constexpr (NumericMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mMaxMeasuredValue)); |
| } |
| break; |
| |
| case Attributes::Uncertainty::Id: |
| if constexpr (NumericMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mUncertainty)); |
| } |
| break; |
| |
| case Attributes::MeasurementUnit::Id: |
| if constexpr (NumericMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mMeasurementUnit)); |
| break; |
| } |
| |
| case Attributes::PeakMeasuredValue::Id: |
| if constexpr (PeakMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mPeakMeasuredValue)); |
| } |
| break; |
| |
| case Attributes::PeakMeasuredValueWindow::Id: |
| if constexpr (PeakMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mPeakMeasuredValueWindow)); |
| } |
| break; |
| |
| case Attributes::AverageMeasuredValue::Id: |
| if constexpr (AverageMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mAverageMeasuredValue)); |
| } |
| break; |
| |
| case Attributes::AverageMeasuredValueWindow::Id: |
| if constexpr (AverageMeasurementEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mAverageMeasuredValueWindow)); |
| } |
| break; |
| |
| case Attributes::LevelValue::Id: |
| if constexpr (LevelIndicationEnabled) |
| { |
| ReturnErrorOnFailure(aEncoder.Encode(this->mLevel)); |
| } |
| break; |
| |
| case Attributes::MeasurementMedium::Id: |
| ReturnErrorOnFailure(aEncoder.Encode(mMeasurementMedium)); |
| break; |
| |
| case Attributes::FeatureMap::Id: |
| ReturnErrorOnFailure(aEncoder.Encode(mFeatureMap)); |
| break; |
| } |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| /** |
| * This checks if the clusters instance is a valid ResourceMonitoring cluster based on the AliasedClusters list. |
| * @return true if the cluster is a valid ResourceMonitoring cluster. |
| */ |
| bool IsValidAliasCluster() const |
| { |
| for (unsigned int AliasedCluster : AliasedClusters) |
| { |
| if (mClusterId == AliasedCluster) |
| { |
| return true; |
| } |
| } |
| return false; |
| }; |
| |
| /** |
| * This generates a feature bitmap from the enabled features and then returns its raw value. |
| * @return The raw feature bitmap. |
| */ |
| uint32_t GenerateFeatureMap() const |
| { |
| BitMask<Feature, uint32_t> featureMap(0); |
| |
| if constexpr (NumericMeasurementEnabled) |
| { |
| featureMap.Set(Feature::kNumericMeasurement); |
| } |
| |
| if constexpr (LevelIndicationEnabled) |
| { |
| featureMap.Set(Feature::kLevelIndication); |
| } |
| |
| if constexpr (MediumLevelEnabled) |
| { |
| featureMap.Set(Feature::kMediumLevel); |
| } |
| |
| if constexpr (CriticalLevelEnabled) |
| { |
| featureMap.Set(Feature::kCriticalLevel); |
| } |
| |
| if constexpr (PeakMeasurementEnabled) |
| { |
| featureMap.Set(Feature::kPeakMeasurement); |
| } |
| |
| if constexpr (AverageMeasurementEnabled) |
| { |
| featureMap.Set(Feature::kAverageMeasurement); |
| } |
| |
| return featureMap.Raw(); |
| }; |
| |
| /** |
| * This checks if a given nullable float is within the min and max constraints or two other nullable floats. |
| * @param value The value to check. |
| * @param minValue The minimum value. |
| * @param maxValue The maximum value. |
| * @return true if the value is within the min and max constraints. If either of the pair of values being compared is null, |
| * that's considered to be within the constraint. |
| */ |
| static bool CheckConstraintMinMax(DataModel::Nullable<float> value, DataModel::Nullable<float> minValue, |
| DataModel::Nullable<float> maxValue) |
| { |
| return (minValue.IsNull() || value.IsNull() || (value.Value() >= minValue.Value())) && |
| (maxValue.IsNull() || value.IsNull() || (value.Value() <= maxValue.Value())); |
| }; |
| |
| /** |
| * This checks if a given nullable float is less than or equal to another given nullable float. |
| * @param value The value to check. |
| * @param valueToBeLessThanOrEqualTo The value to be less than or equal to. |
| * @return true if value is less than or equal to valueToBeLessThanOrEqualTo, or if either of the values is Null. |
| */ |
| static bool CheckConstraintsLessThanOrEqualTo(DataModel::Nullable<float> value, |
| DataModel::Nullable<float> valueToBeLessThanOrEqualTo) |
| { |
| return valueToBeLessThanOrEqualTo.IsNull() || value.IsNull() || (value.Value() <= valueToBeLessThanOrEqualTo.Value()); |
| }; |
| |
| /** |
| * This checks if a given nullable float is greater than or equal to another given nullable float. |
| * @param value The value to check. |
| * @param valueToBeGreaterThanOrEqualTo The value to be greater than or equal to. |
| * @return true if value is greater than or equal to valueToBeGreaterThanOrEqualTo, or if either of the values is Null. |
| */ |
| static bool CheckConstraintsGreaterThanOrEqualTo(DataModel::Nullable<float> value, |
| DataModel::Nullable<float> valueToBeGreaterThanOrEqualTo) |
| { |
| return valueToBeGreaterThanOrEqualTo.IsNull() || value.IsNull() || (value.Value() >= valueToBeGreaterThanOrEqualTo.Value()); |
| }; |
| |
| public: |
| /** |
| * Creates a mode base cluster instance. The Init() function needs to be called for this instance to be registered and |
| * called by the interaction model at the appropriate times. |
| * This constructor should be used when not using the kNumericMeasurement feature. |
| * @param aEndpointId The endpoint on which this cluster exists. This must match the zap configuration. |
| * @param aClusterId The ID of the ModeBase aliased cluster to be instantiated. |
| * @param aMeasurementMedium The measurement medium. |
| */ |
| Instance(EndpointId aEndpointId, ClusterId aClusterId, MeasurementMediumEnum aMeasurementMedium) : |
| AttributeAccessInterface(Optional<EndpointId>(aEndpointId), aClusterId), mEndpointId(aEndpointId), mClusterId(aClusterId), |
| mMeasurementMedium(aMeasurementMedium){}; |
| |
| /** |
| * Creates a mode base cluster instance. The Init() function needs to be called for this instance to be registered and |
| * called by the interaction model at the appropriate times. |
| * This constructor should be used when using the kNumericMeasurement feature. |
| * @param aEndpointId The endpoint on which this cluster exists. This must match the zap configuration. |
| * @param aClusterId The ID of the ModeBase aliased cluster to be instantiated. |
| * @param aMeasurementMedium The measurement medium. |
| * @param aMeasurementUnit The measurement unit. |
| */ |
| Instance(EndpointId aEndpointId, ClusterId aClusterId, MeasurementMediumEnum aMeasurementMedium, |
| MeasurementUnitEnum aMeasurementUnit) : |
| AttributeAccessInterface(Optional<EndpointId>(aEndpointId), aClusterId), |
| mEndpointId(aEndpointId), mClusterId(aClusterId), mMeasurementMedium(aMeasurementMedium) |
| { |
| this->mMeasurementUnit = aMeasurementUnit; |
| }; |
| |
| ~Instance() override { unregisterAttributeAccessOverride(this); }; |
| |
| CHIP_ERROR Init() |
| { |
| static_assert(NumericMeasurementEnabled || LevelIndicationEnabled, |
| "At least one of NumericMeasurement or LevelIndication " |
| "should be enabled"); |
| |
| static_assert(!MediumLevelEnabled || LevelIndicationEnabled, |
| "MediumLevelEnabled requires LevelIndicationEnabled to be true"); |
| |
| static_assert(!CriticalLevelEnabled || LevelIndicationEnabled, |
| "CriticalLevelEnabled requires LevelIndicationEnabled to be true"); |
| |
| static_assert(!PeakMeasurementEnabled || NumericMeasurementEnabled, |
| "PeakMeasurementEnabled requires NumericMeasurementEnabled to be true"); |
| |
| static_assert(!AverageMeasurementEnabled || NumericMeasurementEnabled, |
| "AverageMeasurementEnabled requires NumericMeasurementEnabled to be true"); |
| |
| VerifyOrReturnError(IsValidAliasCluster(), CHIP_ERROR_INCORRECT_STATE); |
| |
| // Check if the cluster has been selected in zap |
| VerifyOrReturnError(emberAfContainsServer(mEndpointId, mClusterId), CHIP_ERROR_INCORRECT_STATE); |
| |
| // Register the object as attribute provider |
| VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); |
| |
| mFeatureMap = GenerateFeatureMap(); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = NumericMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetMeasuredValue(DataModel::Nullable<float> aMeasuredValue) |
| { |
| if (!CheckConstraintMinMax(aMeasuredValue, this->mMinMeasuredValue, this->mMaxMeasuredValue)) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mMeasuredValue != aMeasuredValue, CHIP_NO_ERROR); |
| this->mMeasuredValue = aMeasuredValue; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::MeasuredValue::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = NumericMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetMinMeasuredValue(DataModel::Nullable<float> aMinMeasuredValue) |
| { |
| if (!CheckConstraintsLessThanOrEqualTo(aMinMeasuredValue, this->mMaxMeasuredValue)) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| if (!CheckConstraintsLessThanOrEqualTo(aMinMeasuredValue, this->mMeasuredValue)) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mMinMeasuredValue != aMinMeasuredValue, CHIP_NO_ERROR); |
| this->mMinMeasuredValue = aMinMeasuredValue; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::MinMeasuredValue::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = NumericMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetMaxMeasuredValue(DataModel::Nullable<float> aMaxMeasuredValue) |
| { |
| if (!CheckConstraintsGreaterThanOrEqualTo(aMaxMeasuredValue, this->mMinMeasuredValue)) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| if (!CheckConstraintsGreaterThanOrEqualTo(aMaxMeasuredValue, this->mMeasuredValue)) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mMaxMeasuredValue != aMaxMeasuredValue, CHIP_NO_ERROR); |
| this->mMaxMeasuredValue = aMaxMeasuredValue; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::MaxMeasuredValue::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = NumericMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetUncertainty(float aUncertainty) |
| { |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mUncertainty != aUncertainty, CHIP_NO_ERROR); |
| this->mUncertainty = aUncertainty; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::Uncertainty::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = PeakMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetPeakMeasuredValue(DataModel::Nullable<float> aPeakMeasuredValue) |
| { |
| if (!CheckConstraintMinMax(aPeakMeasuredValue, this->mMinMeasuredValue, this->mMaxMeasuredValue)) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mPeakMeasuredValue != aPeakMeasuredValue, CHIP_NO_ERROR); |
| this->mPeakMeasuredValue = aPeakMeasuredValue; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::PeakMeasuredValue::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = PeakMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetPeakMeasuredValueWindow(uint32_t aPeakMeasuredValueWindow) |
| { |
| if (aPeakMeasuredValueWindow > WINDOW_MAX) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mPeakMeasuredValueWindow != aPeakMeasuredValueWindow, CHIP_NO_ERROR); |
| this->mPeakMeasuredValueWindow = aPeakMeasuredValueWindow; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::PeakMeasuredValueWindow::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = AverageMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetAverageMeasuredValue(DataModel::Nullable<float> aAverageMeasuredValue) |
| { |
| if (!CheckConstraintMinMax(aAverageMeasuredValue, this->mMinMeasuredValue, this->mMaxMeasuredValue)) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mAverageMeasuredValue != aAverageMeasuredValue, CHIP_NO_ERROR); |
| this->mAverageMeasuredValue = aAverageMeasuredValue; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::AverageMeasuredValue::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = AverageMeasurementEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetAverageMeasuredValueWindow(uint32_t aAverageMeasuredValueWindow) |
| { |
| if (aAverageMeasuredValueWindow > WINDOW_MAX) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mAverageMeasuredValueWindow != aAverageMeasuredValueWindow, CHIP_NO_ERROR); |
| this->mAverageMeasuredValueWindow = aAverageMeasuredValueWindow; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::AverageMeasuredValueWindow::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| |
| template <bool Enabled = LevelIndicationEnabled, typename = std::enable_if_t<Enabled, CHIP_ERROR>> |
| CHIP_ERROR SetLevelValue(LevelValueEnum aLevel) |
| { |
| if constexpr (!MediumLevelEnabled) |
| { |
| if (aLevel == LevelValueEnum::kMedium) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| } |
| |
| if constexpr (!CriticalLevelEnabled) |
| { |
| if (aLevel == LevelValueEnum::kCritical) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| } |
| |
| // Check to see if a change has ocurred |
| VerifyOrReturnError(this->mLevel != aLevel, CHIP_NO_ERROR); |
| this->mLevel = aLevel; |
| MatterReportingAttributeChangeCallback(mEndpointId, mClusterId, Attributes::LevelValue::Id); |
| |
| return CHIP_NO_ERROR; |
| }; |
| }; |
| |
| /** |
| * A factory function to create a new instance of a Concentration Measurement Cluster with only the NumericMeasurement feature |
| * enabled. |
| * |
| * @tparam PeakMeasurementEnabled Whether the PeakMeasurement feature is enabled. |
| * @tparam AverageMeasurementEnabled Whether the AverageMeasurement feature is enabled. |
| * @param endpoint Endpoint that the cluster is on. |
| * @param clusterId Cluster that the cluster is on. |
| * @param aMeasurementMedium The measurement medium. |
| * @param aMeasurementUnit The measurement unit. |
| * @return A new instance of Concentration Measurement Cluster. |
| */ |
| template <bool PeakMeasurementEnabled, bool AverageMeasurementEnabled> |
| Instance<true, false, false, false, PeakMeasurementEnabled, AverageMeasurementEnabled> |
| CreateNumericMeasurementConcentrationCluster(EndpointId endpoint, ClusterId clusterId, MeasurementMediumEnum aMeasurementMedium, |
| MeasurementUnitEnum aMeasurementUnit) |
| { |
| return Instance<true, false, false, false, PeakMeasurementEnabled, AverageMeasurementEnabled>( |
| endpoint, clusterId, aMeasurementMedium, aMeasurementUnit); |
| } |
| |
| /** |
| * A factory function to create a new instance of a Concentration Measurement Cluster with only the Level Indication feature |
| * enabled. |
| * |
| * @tparam MediumLevelEnabled Whether the MediumLevel feature is enabled. |
| * @tparam CriticalLevelEnabled Whether the CriticalLevel feature is enabled. |
| * @param endpoint Endpoint that the cluster is on. |
| * @param clusterId Cluster that the cluster is on. |
| * @param aMeasurementMedium The measurement medium. |
| * @return A new instance of Concentration Measurement Cluster. |
| */ |
| template <bool MediumLevelEnabled, bool CriticalLevelEnabled> |
| Instance<false, true, MediumLevelEnabled, CriticalLevelEnabled, false, false> |
| CreateLevelIndicationConcentrationCluster(EndpointId endpoint, ClusterId clusterId, MeasurementMediumEnum aMeasurementMedium) |
| { |
| return Instance<false, true, MediumLevelEnabled, CriticalLevelEnabled, false, false>(endpoint, clusterId, aMeasurementMedium); |
| } |
| |
| /** |
| * A factory function to create a new instance of a Concentration Measurement Cluster with both the NumericMeasurement and Level |
| * Indication features enabled. |
| * |
| * @tparam MediumLevelEnabled Whether the MediumLevel feature is enabled. |
| * @tparam CriticalLevelEnabled Whether the CriticalLevel feature is enabled. |
| * @tparam PeakMeasurementEnabled Whether the PeakMeasurement feature is enabled. |
| * @tparam AverageMeasurementEnabled Whether the AverageMeasurement feature is enabled. |
| * @param endpoint Endpoint that the cluster is on. |
| * @param clusterId Cluster that the cluster is on. |
| * @param aMeasurementMedium The measurement medium. |
| * @param aMeasurementUnit The measurement unit. |
| * @return A new instance of Concentration Measurement Cluster. |
| */ |
| template <bool MediumLevelEnabled, bool CriticalLevelEnabled, bool PeakMeasurementEnabled, bool AverageMeasurementEnabled> |
| Instance<true, true, MediumLevelEnabled, CriticalLevelEnabled, PeakMeasurementEnabled, AverageMeasurementEnabled> |
| CreateNumericMeasurementAndLevelIndicationConcentrationCluster(EndpointId endpoint, ClusterId clusterId, |
| MeasurementMediumEnum aMeasurementMedium, |
| MeasurementUnitEnum aMeasurementUnit) |
| { |
| return Instance<true, true, MediumLevelEnabled, CriticalLevelEnabled, PeakMeasurementEnabled, AverageMeasurementEnabled>( |
| endpoint, clusterId, aMeasurementMedium, aMeasurementUnit); |
| } |
| |
| } // namespace ConcentrationMeasurement |
| } // namespace Clusters |
| } // namespace app |
| } // namespace chip |