Skip to content

Commit 280df4f

Browse files
Changing MainState and Countdowntime Implementation
1 parent 236a68b commit 280df4f

File tree

2 files changed

+124
-4
lines changed

2 files changed

+124
-4
lines changed

src/app/clusters/closure-control-server/closure-control-server.cpp

+77-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,82 @@ bool Instance::SupportsOptAttr(OptionalAttributes aOptionalAttrs) const
6161
return mOptionalAttrs.Has(aOptionalAttrs);
6262
}
6363

64+
bool Instance::IsSupportedState(MainStateEnum aMainState)
65+
{
66+
switch (aMainState)
67+
{
68+
case MainStateEnum::kCalibrating:
69+
return HasFeature(Feature::kCalibration);
70+
case MainStateEnum::kProtected:
71+
return HasFeature(Feature::kProtection);
72+
case MainStateEnum::kDisengaged:
73+
return HasFeature(Feature::kManuallyOperable);
74+
case MainStateEnum::kPendingFallback:
75+
return HasFeature(Feature::kFallback);
76+
default:
77+
return true;
78+
}
79+
return true;
80+
}
81+
82+
CHIP_ERROR Instance::SetMainState(const MainStateEnum & aMainState)
83+
{
84+
if (!IsSupportedState(aMainState))
85+
{
86+
return CHIP_ERROR_INVALID_ARGUMENT;
87+
}
88+
89+
MainStateEnum oldMainState = mMainState;
90+
mMainState = aMainState;
91+
if (mMainState != oldMainState)
92+
{
93+
MatterReportingAttributeChangeCallback(mDelegate.GetEndpointId(), mClusterId, Attributes::MainState::Id);
94+
UpdateCountdownTimeFromClusterLogic();
95+
}
96+
return CHIP_NO_ERROR;
97+
}
98+
99+
MainStateEnum Instance::GetMainState() const
100+
{
101+
return mMainState;
102+
}
103+
104+
void Instance::UpdateCountdownTime(bool fromDelegate)
105+
{
106+
app::DataModel::Nullable<uint32_t> newCountdownTime = mDelegate.GetCountdownTime();
107+
auto now = System::SystemClock().GetMonotonicTimestamp();
108+
109+
bool markDirty = false;
110+
111+
if (fromDelegate)
112+
{
113+
// Updates from delegate are reduce-reported to every 10s max (choice of this implementation), in addition
114+
// to default change-from-null, change-from-zero and increment policy.
115+
auto predicate = [](const decltype(mCountdownTime)::SufficientChangePredicateCandidate & candidate) -> bool {
116+
if (candidate.lastDirtyValue.IsNull() || candidate.newValue.IsNull())
117+
{
118+
return false;
119+
}
120+
121+
uint32_t lastDirtyValue = candidate.lastDirtyValue.Value();
122+
uint32_t newValue = candidate.newValue.Value();
123+
uint32_t kNumSecondsDeltaToReport = 10;
124+
return (newValue < lastDirtyValue) && ((lastDirtyValue - newValue) > kNumSecondsDeltaToReport);
125+
};
126+
markDirty = (mCountdownTime.SetValue(newCountdownTime, now, predicate) == AttributeDirtyState::kMustReport);
127+
}
128+
else
129+
{
130+
auto predicate = [](const decltype(mCountdownTime)::SufficientChangePredicateCandidate &) -> bool { return true; };
131+
markDirty = (mCountdownTime.SetValue(newCountdownTime, now, predicate) == AttributeDirtyState::kMustReport);
132+
}
133+
134+
if (markDirty)
135+
{
136+
MatterReportingAttributeChangeCallback(mDelegate.GetEndpointId(), mClusterId, Attributes::CountdownTime::Id);
137+
}
138+
}
139+
64140
// AttributeAccessInterface
65141
CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
66142
{
@@ -75,7 +151,7 @@ CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValu
75151
}
76152
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
77153
case MainState::Id:
78-
return aEncoder.Encode(mDelegate.GetMainState());
154+
return aEncoder.Encode(GetMainState());
79155
case CurrentErrorList::Id:
80156
return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { return this->EncodeCurrentErrorList(encoder); });
81157
case OverallState::Id:

src/app/clusters/closure-control-server/closure-control-server.h

+47-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <app/util/attribute-storage.h>
2929
#include <lib/core/CHIPError.h>
3030
#include <protocols/interaction_model/StatusCode.h>
31+
#include <app/cluster-building-blocks/QuieterReporting.h>
3132

3233
namespace chip {
3334
namespace app {
@@ -60,7 +61,6 @@ class Delegate
6061
// ------------------------------------------------------------------
6162
// Get attribute methods
6263
virtual DataModel::Nullable<uint32_t> GetCountdownTime() = 0;
63-
virtual MainStateEnum GetMainState() = 0;
6464
virtual DataModel::Nullable<Structs::OverallStateStruct::Type> GetOverallState() = 0;
6565
virtual DataModel::Nullable<Structs::OverallTargetStruct::Type> GetOverallTarget() = 0;
6666
virtual RestingProcedureEnum GetRestingProcedure() = 0;
@@ -91,9 +91,9 @@ enum class OptionalAttributes : uint32_t
9191
class Instance : public AttributeAccessInterface, public CommandHandlerInterface
9292
{
9393
public:
94-
Instance(EndpointId aEndpointId, Delegate & aDelegate, Feature aFeature, OptionalAttributes aOptionalAttrs) :
94+
Instance(EndpointId aEndpointId, Delegate & aDelegate, Feature aFeature, OptionalAttributes aOptionalAttrs, ClusterId aClusterId) :
9595
AttributeAccessInterface(MakeOptional(aEndpointId), Id), CommandHandlerInterface(MakeOptional(aEndpointId), Id),
96-
mDelegate(aDelegate), mFeature(aFeature), mOptionalAttrs(aOptionalAttrs)
96+
mDelegate(aDelegate), mClusterId(aClusterId), mFeature(aFeature), mOptionalAttrs(aOptionalAttrs)
9797
{
9898
/* set the base class delegates endpointId */
9999
mDelegate.SetEndpointId(aEndpointId);
@@ -105,11 +105,55 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface
105105

106106
bool HasFeature(Feature aFeature) const;
107107
bool SupportsOptAttr(OptionalAttributes aOptionalAttrs) const;
108+
109+
// Attribute setters
110+
/**
111+
* Set Main State.
112+
* @param aMainState The Main state that should now be the current one.
113+
* @return CHIP_NO_ERROR if set was successful.
114+
*/
115+
CHIP_ERROR SetMainState(const MainStateEnum & aMainState);
116+
117+
// Attribute getters
118+
/**
119+
* Get Main State.
120+
* @return The Main State.
121+
*/
122+
MainStateEnum GetMainState() const;
123+
124+
/**
125+
* @brief Whenever application delegate wants to possibly report a new updated time,
126+
* call this method. The `GetCountdownTime()` method will be called on the delegate.
127+
*/
128+
void UpdateCountdownTimeFromDelegate() { UpdateCountdownTime(/* fromDelegate = */ true); }
129+
130+
/**
131+
* This function returns true if the phase value given exists in the PhaseList attribute, otherwise it returns false.
132+
*/
133+
bool IsSupportedState(MainStateEnum aMainState);
134+
135+
protected:
136+
/**
137+
* Causes reporting/udpating of CountdownTime attribute from driver if sufficient changes have
138+
* occurred (based on Q quality definition for operational state). Calls the Delegate::GetCountdownTime() method.
139+
*
140+
* @param fromDelegate true if the change notice was triggered by the delegate, false if internal to cluster logic.
141+
*/
142+
void UpdateCountdownTime(bool fromDelegate);
143+
144+
/**
145+
* @brief Whenever the cluster logic thinks time should be updated, call this.
146+
*/
147+
void UpdateCountdownTimeFromClusterLogic() { UpdateCountdownTime(/* fromDelegate=*/false); }
108148

109149
private:
110150
Delegate & mDelegate;
151+
const ClusterId mClusterId;
152+
111153
BitMask<Feature> mFeature;
112154
BitMask<OptionalAttributes> mOptionalAttrs;
155+
MainStateEnum mMainState;
156+
app::QuieterReportingAttribute<uint32_t> mCountdownTime{ DataModel::NullNullable };
113157

114158
// AttributeAccessInterface
115159
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;

0 commit comments

Comments
 (0)