blob: 8892fb1e1cb32c71a19b96fe9cb7f6ed3960d445 [file]
/**
*
* Copyright (c) 2025 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.
*
*/
#pragma once
#include <app/cluster-building-blocks/QuieterReporting.h>
#include <app/clusters/closure-dimension-server/ClosureDimensionClusterDelegate.h>
#include <app/clusters/closure-dimension-server/GenericDimensionState.h>
#include <app/server-cluster/DefaultServerCluster.h>
#include <app/server-cluster/OptionalAttributeSet.h>
#include <lib/core/CHIPError.h>
#include <lib/support/BitFlags.h>
#include <lib/support/logging/CHIPLogging.h>
namespace chip {
namespace app {
namespace Clusters {
namespace ClosureDimension {
class ClosureDimensionCluster : public DefaultServerCluster
{
public:
struct Config
{
Config(EndpointId endpoint, ClosureDimensionClusterDelegate & delegate) : mEndpointId(endpoint), mDelegate(delegate) {}
Config & WithPositioning(Percent100ths resolution, Percent100ths stepValue)
{
mFeatureMap.Set(Feature::kPositioning);
mResolution = resolution;
mStepValue = stepValue;
return *this;
}
Config & WithMotionLatching(BitFlags<LatchControlModesBitmap> latchControlModes)
{
mFeatureMap.Set(Feature::kMotionLatching);
mLatchControlModes = latchControlModes;
return *this;
}
Config & WithUnit(ClosureUnitEnum unit, DataModel::Nullable<Structs::UnitRangeStruct::Type> unitRange)
{
mFeatureMap.Set(Feature::kUnit);
mUnit = unit;
mUnitRange = unitRange;
return *this;
}
Config & WithLimitation(Structs::RangePercent100thsStruct::Type limitRange)
{
mFeatureMap.Set(Feature::kLimitation);
mLimitRange = limitRange;
return *this;
}
Config & WithSpeed()
{
mFeatureMap.Set(Feature::kSpeed);
return *this;
}
Config & WithTranslation(TranslationDirectionEnum translationDirection)
{
mFeatureMap.Set(Feature::kTranslation);
mTranslationDirection = translationDirection;
return *this;
}
Config & WithRotation(RotationAxisEnum rotationAxis, OverflowEnum overflow)
{
mFeatureMap.Set(Feature::kRotation);
mRotationAxis = rotationAxis;
mOverflow = overflow;
return *this;
}
Config & WithModulation(ModulationTypeEnum modulationType)
{
mFeatureMap.Set(Feature::kModulation);
mModulationType = modulationType;
return *this;
}
Config & WithAccess()
{
mFeatureMap.Set(Feature::kAccess);
return *this;
}
EndpointId mEndpointId;
ClosureDimensionClusterDelegate & mDelegate;
BitMask<Feature> mFeatureMap;
Percent100ths mResolution = 1;
Percent100ths mStepValue = 1;
ClosureUnitEnum mUnit = ClosureUnitEnum::kUnknownEnumValue;
DataModel::Nullable<Structs::UnitRangeStruct::Type> mUnitRange = DataModel::Nullable<Structs::UnitRangeStruct::Type>();
Structs::RangePercent100thsStruct::Type mLimitRange{};
TranslationDirectionEnum mTranslationDirection = TranslationDirectionEnum::kUnknownEnumValue;
RotationAxisEnum mRotationAxis = RotationAxisEnum::kUnknownEnumValue;
OverflowEnum mOverflow = OverflowEnum::kUnknownEnumValue;
ModulationTypeEnum mModulationType = ModulationTypeEnum::kUnknownEnumValue;
BitFlags<LatchControlModesBitmap> mLatchControlModes;
};
ClosureDimensionCluster(const Config & config);
~ClosureDimensionCluster();
CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<DataModel::AttributeEntry> & builder) override;
CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path,
ReadOnlyBufferBuilder<DataModel::AcceptedCommandEntry> & builder) override;
DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request,
AttributeValueEncoder & encoder) override;
std::optional<DataModel::ActionReturnStatus> InvokeCommand(const DataModel::InvokeRequest & request,
chip::TLV::TLVReader & input_arguments,
CommandHandler * handler) override;
/**
* @brief Set Current State.
*
* @param[in] currentState Current State Position, Latch and Speed.
*
* @return CHIP_NO_ERROR if set was successful.
* CHIP_ERROR_INCORRECT_STATE if the cluster has not been initialized.
* CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE if feature is not supported.
* CHIP_ERROR_INVALID_ARGUMENT if argument are not valid
*/
CHIP_ERROR SetCurrentState(const DataModel::Nullable<GenericDimensionStateStruct> & currentState);
/**
* @brief Set TargetState.
*
* @param[in] targetState TargetState Position, Latch and Speed.
*
* @return CHIP_NO_ERROR if set was successful.
* CHIP_ERROR_INCORRECT_STATE if the cluster has not been initialized.
* CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE if feature is not supported.
* CHIP_ERROR_INVALID_ARGUMENT if argument are not valid
*/
CHIP_ERROR SetTargetState(const DataModel::Nullable<GenericDimensionStateStruct> & targetState);
/**
* @brief Set UnitRange.
*
* @param[in] unitRange Minimum and Maximum values expressed by positioning following the unit.
*
* @return CHIP_NO_ERROR if set was successful.
* CHIP_ERROR_INCORRECT_STATE if the cluster has not been initialized
* CHIP_ERROR_INVALID_ARGUMENT if argument are not valid
* CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE if feature is not supported.
*/
CHIP_ERROR SetUnitRange(const DataModel::Nullable<Structs::UnitRangeStruct::Type> & unitRange);
/**
* @brief Set LimitRange.
*
* @param[in] limitRange Range of possible values for the position field in Current attribute.
*
* @return CHIP_NO_ERROR if set was successful.
* CHIP_ERROR_INCORRECT_STATE if the cluster has not been initialized
* CHIP_ERROR_INVALID_ARGUMENT if argument are not valid
* CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE if feature is not supported.
*/
CHIP_ERROR SetLimitRange(const Structs::RangePercent100thsStruct::Type & limitRange);
// All Get functions:
// Return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE if the attribute is not supported.
// Otherwise return CHIP_NO_ERROR and set the input parameter value to the current cluster state value
DataModel::Nullable<GenericDimensionStateStruct> GetCurrentState() const { return mCurrentState; }
DataModel::Nullable<GenericDimensionStateStruct> GetTargetState() const { return mTargetState; }
Percent100ths GetResolution() const { return mResolution; }
Percent100ths GetStepValue() const { return mStepValue; }
ClosureUnitEnum GetUnit() const { return mUnit; }
DataModel::Nullable<Structs::UnitRangeStruct::Type> GetUnitRange() const { return mUnitRange; }
Structs::RangePercent100thsStruct::Type GetLimitRange() const { return mLimitRange; }
TranslationDirectionEnum GetTranslationDirection() const { return mTranslationDirection; }
RotationAxisEnum GetRotationAxis() const { return mRotationAxis; }
OverflowEnum GetOverflow() const { return mOverflow; }
ModulationTypeEnum GetModulationType() const { return mModulationType; }
BitFlags<LatchControlModesBitmap> GetLatchControlModes() const { return mLatchControlModes; }
BitFlags<Feature> GetFeatureMap() const { return mFeatureMap; }
private:
ClosureDimensionClusterDelegate & mDelegate;
DataModel::Nullable<GenericDimensionStateStruct> mCurrentState{ DataModel::NullNullable };
DataModel::Nullable<GenericDimensionStateStruct> mTargetState{ DataModel::NullNullable };
Percent100ths mResolution = 1;
Percent100ths mStepValue = 1;
ClosureUnitEnum mUnit = ClosureUnitEnum::kUnknownEnumValue;
DataModel::Nullable<Structs::UnitRangeStruct::Type> mUnitRange = DataModel::Nullable<Structs::UnitRangeStruct::Type>();
Structs::RangePercent100thsStruct::Type mLimitRange{};
TranslationDirectionEnum mTranslationDirection = TranslationDirectionEnum::kUnknownEnumValue;
RotationAxisEnum mRotationAxis = RotationAxisEnum::kUnknownEnumValue;
OverflowEnum mOverflow = OverflowEnum::kUnknownEnumValue;
ModulationTypeEnum mModulationType = ModulationTypeEnum::kUnknownEnumValue;
BitFlags<LatchControlModesBitmap> mLatchControlModes;
BitMask<Feature> mFeatureMap = BitMask<Feature>(0);
/**
* @brief Calls delegate HandleSetTarget function after validating the parameters and conformance.
*
* @param [in] position TargetState position
* @param [in] latch TargetState latch
* @param [in] speed TargetState speed
*
* @return Exits if the cluster is not initialized.
* InvalidCommand if none of the input parameters are present.
* ConstraintError if the input values are out is out of range.
* InvalidInState if the current position of closure is not known.
* Success on succesful handling.
*/
Protocols::InteractionModel::Status HandleSetTargetCommand(Optional<Percent100ths> position, Optional<bool> latch,
Optional<Globals::ThreeLevelAutoEnum> speed);
/**
* @brief Calls delegate HandleStep function after validating the parameters and conformance.
*
* @param [in] direction step direction
* @param [in] numberOfSteps Number of steps
* @param [in] speed step speed
*
* @return Exits if the cluster is not initialized.
* UnsupportedCommand if Positioning feature is not supported.
* ConstraintError if the input values are out is out of range.
* InvalidInState if the current position of closure is not known.
* Success on successful handling.
*/
Protocols::InteractionModel::Status HandleStepCommand(StepDirectionEnum direction, uint16_t numberOfSteps,
Optional<Globals::ThreeLevelAutoEnum> speed);
// At Present, QuieterReportingAttribute doesnt support Structs.
// So, this variable will be used for Quietreporting of current state position.
// TODO: Refactor CurrentState Atrribute to use QuieterReportingAttribute once Issue#39801 is resolved
QuieterReportingAttribute<Percent100ths> quietReportableCurrentStatePosition{ DataModel::NullNullable };
EndpointId GetEndpointId() { return mPath.mEndpointId; }
};
} // namespace ClosureDimension
} // namespace Clusters
} // namespace app
} // namespace chip