Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b305afb

Browse files
sabollim-silabssatyanaag-silabsrestyled-commits
authored andcommittedMar 4, 2025
Closure control cluster server code implementation (project-chip#37561)
* Closure control sluster Server Code * Restyled by whitespace * Restyled by clang-format * Changing MainState and Countdowntime Implementation * Handling OverallState and OverallTarget from Instance * Addressing PR comments * Restyled by whitespace * Restyled by clang-format * Updating missing zap changes * Adding wrapper for struct handling * Restyled by whitespace * Restyled by clang-format * Addressing PR comments * Addressing PR comments * Restyled by clang-format * addressing PR comments * changing IsEqual to operator== * Addressing PR comments * Addresssing PR comments * Removing Fallback feature attribute and commands as FB feature is removed from spec * Addressing PR comments * Updating countdonwtime quiet reporting policy * Restyled by whitespace * Restyled by clang-format --------- Co-authored-by: sabollim <satyanaag.bollimpalli@silabs.com> Co-authored-by: Restyled.io <commits@restyled.io>
1 parent cac9210 commit b305afb

File tree

7 files changed

+632
-31
lines changed

7 files changed

+632
-31
lines changed
 

‎src/app/chip_data_model.gni

+6
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,12 @@ template("chip_data_model") {
456456
"${_app_root}/clusters/${cluster}/ArlEncoder.cpp",
457457
"${_app_root}/clusters/${cluster}/ArlEncoder.h",
458458
]
459+
} else if (cluster == "closure-control-server") {
460+
sources += [
461+
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
462+
"${_app_root}/clusters/${cluster}/${cluster}.h",
463+
"${_app_root}/clusters/${cluster}/closure-control-cluster-objects.h",
464+
]
459465
} else {
460466
sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ]
461467
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
*
3+
* Copyright (c) 2025 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
#include <app-common/zap-generated/cluster-objects.h>
22+
#include <lib/support/CommonIterator.h>
23+
24+
namespace chip {
25+
namespace app {
26+
namespace Clusters {
27+
namespace ClosureControl {
28+
29+
/**
30+
* Structure represents the overall state of a closure control cluster derivation instance.
31+
*/
32+
struct GenericOverallState : public Structs::OverallStateStruct::Type
33+
{
34+
GenericOverallState(Optional<PositioningEnum> positioningValue = NullOptional,
35+
Optional<LatchingEnum> latchingValue = NullOptional,
36+
Optional<Globals::ThreeLevelAutoEnum> speedValue = NullOptional,
37+
Optional<uint32_t> extraInfoValue = NullOptional)
38+
{
39+
Set(positioningValue, latchingValue, speedValue, extraInfoValue);
40+
}
41+
42+
GenericOverallState(const GenericOverallState & overallState) { *this = overallState; }
43+
44+
GenericOverallState & operator=(const GenericOverallState & overallState)
45+
{
46+
Set(overallState.positioning, overallState.latching, overallState.speed, overallState.extraInfo);
47+
return *this;
48+
}
49+
50+
void Set(Optional<PositioningEnum> positioningValue = NullOptional, Optional<LatchingEnum> latchingValue = NullOptional,
51+
Optional<Globals::ThreeLevelAutoEnum> speedValue = NullOptional, Optional<uint32_t> extraInfoValue = NullOptional)
52+
{
53+
positioning = positioningValue;
54+
latching = latchingValue;
55+
speed = speedValue;
56+
extraInfo = extraInfoValue;
57+
}
58+
59+
bool operator==(const Structs::OverallStateStruct::Type & rhs) const
60+
{
61+
return positioning == rhs.positioning && latching == rhs.latching && speed == rhs.speed && extraInfo == rhs.extraInfo;
62+
}
63+
};
64+
65+
/**
66+
* Structure represents the overall target state of a closure control cluster derivation instance.
67+
*/
68+
struct GenericOverallTarget : public Structs::OverallTargetStruct::Type
69+
{
70+
GenericOverallTarget(Optional<TagPositionEnum> tagPositionValue = NullOptional,
71+
Optional<TagLatchEnum> tagLatchValue = NullOptional,
72+
Optional<Globals::ThreeLevelAutoEnum> speedValue = NullOptional)
73+
{
74+
Set(tagPositionValue, tagLatchValue, speedValue);
75+
}
76+
77+
GenericOverallTarget(const GenericOverallTarget & overallTarget) { *this = overallTarget; }
78+
79+
GenericOverallTarget & operator=(const GenericOverallTarget & overallTarget)
80+
{
81+
Set(overallTarget.tagPosition, overallTarget.tagLatch, overallTarget.speed);
82+
return *this;
83+
}
84+
85+
void Set(Optional<TagPositionEnum> tagPositionValue = NullOptional, Optional<TagLatchEnum> tagLatchValue = NullOptional,
86+
Optional<Globals::ThreeLevelAutoEnum> speedValue = NullOptional)
87+
{
88+
tagPosition = tagPositionValue;
89+
tagLatch = tagLatchValue;
90+
speed = speedValue;
91+
}
92+
93+
bool operator==(const Structs::OverallTargetStruct::Type & rhs) const
94+
{
95+
return tagPosition == rhs.tagPosition && tagLatch == rhs.tagLatch && speed == rhs.speed;
96+
}
97+
};
98+
99+
} // namespace ClosureControl
100+
} // namespace Clusters
101+
} // namespace app
102+
} // namespace chip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
/*
2+
* Copyright (c) 2025 Project CHIP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "closure-control-server.h"
18+
19+
#include <app/AttributeAccessInterface.h>
20+
#include <app/AttributeAccessInterfaceRegistry.h>
21+
#include <app/CommandHandlerInterfaceRegistry.h>
22+
#include <app/ConcreteAttributePath.h>
23+
#include <app/InteractionModelEngine.h>
24+
#include <app/util/attribute-storage.h>
25+
26+
using namespace chip;
27+
using namespace chip::app;
28+
using namespace chip::app::DataModel;
29+
using namespace chip::app::Clusters;
30+
using namespace chip::app::Clusters::ClosureControl;
31+
using namespace chip::app::Clusters::ClosureControl::Attributes;
32+
using namespace chip::app::Clusters::ClosureControl::Commands;
33+
using chip::Protocols::InteractionModel::Status;
34+
35+
namespace chip {
36+
namespace app {
37+
namespace Clusters {
38+
namespace ClosureControl {
39+
40+
CHIP_ERROR Instance::Init()
41+
{
42+
ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this));
43+
VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INCORRECT_STATE);
44+
45+
return CHIP_NO_ERROR;
46+
}
47+
48+
void Instance::Shutdown()
49+
{
50+
CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this);
51+
AttributeAccessInterfaceRegistry::Instance().Unregister(this);
52+
}
53+
54+
bool Instance::HasFeature(Feature aFeatures) const
55+
{
56+
return mFeatures.Has(aFeatures);
57+
}
58+
59+
bool Instance::SupportsOptAttr(OptionalAttribute aOptionalAttrs) const
60+
{
61+
return mOptionalAttrs.Has(aOptionalAttrs);
62+
}
63+
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+
// Remaining MainState have Mandatory conformance,so will be supported.
78+
return true;
79+
}
80+
return true;
81+
}
82+
83+
CHIP_ERROR Instance::SetMainState(MainStateEnum aMainState)
84+
{
85+
if (!IsSupportedState(aMainState))
86+
{
87+
return CHIP_ERROR_INVALID_ARGUMENT;
88+
}
89+
// If the Main State has changed, trigger the attribute change callback
90+
if (mMainState != aMainState)
91+
{
92+
mMainState = aMainState;
93+
MatterReportingAttributeChangeCallback(mDelegate.GetEndpointId(), ClosureControl::Id, Attributes::MainState::Id);
94+
UpdateCountdownTimeFromClusterLogic();
95+
}
96+
return CHIP_NO_ERROR;
97+
}
98+
99+
CHIP_ERROR Instance::SetOverallState(const GenericOverallState & aOverallState)
100+
{
101+
// If the overall state has changed, trigger the attribute change callback
102+
if (!(mOverallState == aOverallState))
103+
{
104+
mOverallState = aOverallState;
105+
MatterReportingAttributeChangeCallback(mDelegate.GetEndpointId(), ClosureControl::Id, Attributes::OverallState::Id);
106+
}
107+
108+
return CHIP_NO_ERROR;
109+
}
110+
111+
CHIP_ERROR Instance::SetOverallTarget(const GenericOverallTarget & aOverallTarget)
112+
{
113+
// If the overall target has changed, trigger the attribute change callback
114+
if (!(mOverallTarget == aOverallTarget))
115+
{
116+
mOverallTarget = aOverallTarget;
117+
MatterReportingAttributeChangeCallback(mDelegate.GetEndpointId(), ClosureControl::Id, Attributes::OverallTarget::Id);
118+
}
119+
120+
return CHIP_NO_ERROR;
121+
}
122+
123+
MainStateEnum Instance::GetMainState() const
124+
{
125+
return mMainState;
126+
}
127+
128+
const GenericOverallState & Instance::GetOverallState() const
129+
{
130+
return mOverallState;
131+
}
132+
133+
const GenericOverallTarget & Instance::GetOverallTarget() const
134+
{
135+
return mOverallTarget;
136+
}
137+
138+
void Instance::UpdateCountdownTime(bool fromDelegate)
139+
{
140+
app::DataModel::Nullable<uint32_t> newCountdownTime = mDelegate.GetCountdownTime();
141+
auto now = System::SystemClock().GetMonotonicTimestamp();
142+
143+
bool markDirty = false;
144+
145+
if (fromDelegate)
146+
{
147+
// Updates from delegate are reduce-reported to every 1s max (choice of this implementation), in addition
148+
// to default change-from-null, change-from-zero and increment policy.
149+
System::Clock::Milliseconds64 reportInterval = System::Clock::Milliseconds64(1000);
150+
auto predicate = mCountdownTime.GetPredicateForSufficientTimeSinceLastDirty(reportInterval);
151+
markDirty = (mCountdownTime.SetValue(newCountdownTime, now, predicate) == AttributeDirtyState::kMustReport);
152+
}
153+
else
154+
{
155+
auto predicate = [](const decltype(mCountdownTime)::SufficientChangePredicateCandidate &) -> bool { return true; };
156+
markDirty = (mCountdownTime.SetValue(newCountdownTime, now, predicate) == AttributeDirtyState::kMustReport);
157+
}
158+
159+
if (markDirty)
160+
{
161+
MatterReportingAttributeChangeCallback(mDelegate.GetEndpointId(), ClosureControl::Id, Attributes::CountdownTime::Id);
162+
}
163+
}
164+
165+
// AttributeAccessInterface
166+
CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
167+
{
168+
VerifyOrDie(aPath.mClusterId == ClosureControl::Id);
169+
170+
switch (aPath.mAttributeId)
171+
{
172+
case CountdownTime::Id:
173+
// Optional Attribute
174+
if (SupportsOptAttr(OptionalAttribute::kCountdownTime))
175+
{
176+
return aEncoder.Encode(mDelegate.GetCountdownTime());
177+
}
178+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
179+
180+
case MainState::Id:
181+
return aEncoder.Encode(GetMainState());
182+
183+
case CurrentErrorList::Id:
184+
return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { return this->EncodeCurrentErrorList(encoder); });
185+
186+
case OverallState::Id:
187+
return aEncoder.Encode(GetOverallState());
188+
189+
case OverallTarget::Id:
190+
return aEncoder.Encode(GetOverallTarget());
191+
192+
/* FeatureMap - is held locally */
193+
case FeatureMap::Id:
194+
return aEncoder.Encode(mFeatures);
195+
}
196+
197+
return CHIP_NO_ERROR;
198+
}
199+
200+
CHIP_ERROR Instance::EncodeCurrentErrorList(const AttributeValueEncoder::ListEncodeHelper & encoder)
201+
{
202+
CHIP_ERROR err = CHIP_NO_ERROR;
203+
204+
ReturnErrorOnFailure(mDelegate.StartCurrentErrorListRead());
205+
for (size_t i = 0; true; i++)
206+
{
207+
ClosureErrorEnum error;
208+
209+
err = mDelegate.GetCurrentErrorListAtIndex(i, error);
210+
// Convert end of list to CHIP_NO_ERROR
211+
VerifyOrExit(err != CHIP_ERROR_PROVIDER_LIST_EXHAUSTED, err = CHIP_NO_ERROR);
212+
213+
// Check if another error occurred before trying to encode
214+
SuccessOrExit(err);
215+
216+
err = encoder.Encode(error);
217+
SuccessOrExit(err);
218+
}
219+
220+
exit:
221+
// Tell the delegate the read is complete
222+
ReturnErrorOnFailure(mDelegate.EndCurrentErrorListRead());
223+
return err;
224+
}
225+
226+
CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
227+
{
228+
VerifyOrDie(aPath.mClusterId == ClosureControl::Id);
229+
230+
switch (aPath.mAttributeId)
231+
{
232+
case CountdownTime::Id:
233+
if (SupportsOptAttr(OptionalAttribute::kCountdownTime))
234+
{
235+
return CHIP_IM_GLOBAL_STATUS(UnsupportedWrite);
236+
}
237+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
238+
case MainState::Id:
239+
case CurrentErrorList::Id:
240+
case OverallState::Id:
241+
case OverallTarget::Id:
242+
return CHIP_IM_GLOBAL_STATUS(UnsupportedWrite);
243+
default:
244+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
245+
}
246+
}
247+
248+
// CommandHandlerInterface
249+
void Instance::InvokeCommand(HandlerContext & handlerContext)
250+
{
251+
using namespace Commands;
252+
253+
switch (handlerContext.mRequestPath.mCommandId)
254+
{
255+
case Stop::Id:
256+
if (!HasFeature(Feature::kInstantaneous))
257+
{
258+
HandleCommand<Stop::DecodableType>(
259+
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleStop(ctx, commandData); });
260+
}
261+
else
262+
{
263+
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand);
264+
}
265+
break;
266+
case MoveTo::Id:
267+
HandleCommand<MoveTo::DecodableType>(
268+
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleMoveTo(ctx, commandData); });
269+
break;
270+
case Calibrate::Id:
271+
if (HasFeature(Feature::kCalibration))
272+
{
273+
HandleCommand<Calibrate::DecodableType>(
274+
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleCalibrate(ctx, commandData); });
275+
}
276+
else
277+
{
278+
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand);
279+
}
280+
break;
281+
}
282+
}
283+
284+
void Instance::HandleStop(HandlerContext & ctx, const Commands::Stop::DecodableType & commandData)
285+
{
286+
Status status = mDelegate.Stop();
287+
288+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
289+
}
290+
291+
void Instance::HandleMoveTo(HandlerContext & ctx, const Commands::MoveTo::DecodableType & commandData)
292+
{
293+
Status status = mDelegate.MoveTo(commandData.tag, commandData.latch, commandData.speed);
294+
295+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
296+
}
297+
298+
void Instance::HandleCalibrate(HandlerContext & ctx, const Commands::Calibrate::DecodableType & commandData)
299+
{
300+
Status status = mDelegate.Calibrate();
301+
302+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
303+
}
304+
305+
} // namespace ClosureControl
306+
} // namespace Clusters
307+
} // namespace app
308+
} // namespace chip
309+
310+
// -----------------------------------------------------------------------------
311+
// Plugin initialization
312+
313+
void MatterClosureControlPluginServerInitCallback() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/*
2+
*
3+
* Copyright (c) 2025 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
#include "closure-control-cluster-objects.h"
22+
#include <app-common/zap-generated/cluster-objects.h>
23+
#include <app/AttributeAccessInterface.h>
24+
#include <app/CommandHandlerInterface.h>
25+
#include <app/ConcreteAttributePath.h>
26+
#include <app/InteractionModelEngine.h>
27+
#include <app/MessageDef/StatusIB.h>
28+
#include <app/cluster-building-blocks/QuieterReporting.h>
29+
#include <app/reporting/reporting.h>
30+
#include <app/util/attribute-storage.h>
31+
#include <lib/core/CHIPError.h>
32+
#include <protocols/interaction_model/StatusCode.h>
33+
34+
namespace chip {
35+
namespace app {
36+
namespace Clusters {
37+
namespace ClosureControl {
38+
39+
/**
40+
* @brief Defines methods for implementing application-specific logic for the Closure Control Cluster.
41+
*/
42+
class Delegate
43+
{
44+
public:
45+
virtual ~Delegate() = default;
46+
47+
// Only Cluster Instance should be calling SetEdpointId.
48+
void SetEndpointId(EndpointId aEndpoint) { mEndpointId = aEndpoint; }
49+
EndpointId GetEndpointId() { return mEndpointId; }
50+
51+
// ------------------------------------------------------------------
52+
// Commands
53+
virtual Protocols::InteractionModel::Status Stop() = 0;
54+
virtual Protocols::InteractionModel::Status MoveTo(const Optional<TagPositionEnum> & tag, const Optional<TagLatchEnum> & latch,
55+
const Optional<Globals::ThreeLevelAutoEnum> & speed) = 0;
56+
virtual Protocols::InteractionModel::Status Calibrate() = 0;
57+
58+
// ------------------------------------------------------------------
59+
// Get attribute methods
60+
virtual DataModel::Nullable<uint32_t> GetCountdownTime() = 0;
61+
62+
/* These functions are called by the ReadAttribute handler to iterate through lists
63+
* The cluster server will call Start<Type>Read to allow the delegate to create a temporary
64+
* lock on the data.
65+
* The delegate is expected to not change these values once Start<Type>Read has been called
66+
* until the End<Type>Read() has been called (i.e. releasing a lock on the data)
67+
*/
68+
virtual CHIP_ERROR StartCurrentErrorListRead() = 0;
69+
// The delegate is expected to return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED to indicate end of list.
70+
virtual CHIP_ERROR GetCurrentErrorListAtIndex(size_t, ClosureErrorEnum &) = 0;
71+
virtual CHIP_ERROR EndCurrentErrorListRead() = 0;
72+
73+
protected:
74+
EndpointId mEndpointId = chip::kInvalidEndpointId;
75+
};
76+
77+
enum class OptionalAttribute : uint32_t
78+
{
79+
kCountdownTime = 0x1
80+
};
81+
82+
class Instance : public AttributeAccessInterface, public CommandHandlerInterface
83+
{
84+
public:
85+
/**
86+
* @brief Creates a closure control cluster instance. The Init() function needs to be called for
87+
* this instance to be registered and called by the interaction model at the appropriate times.
88+
* @param[in] aEndpointId The endpoint on which this cluster exists.
89+
* @param[in] aDelegate The Delegate used by this Instance.
90+
* @param[in] aFeatures The bitmask value that identifies which features are supported by this instance.
91+
* @param[in] aOptionalAttrs The bitmask Value that identifies which optional attributes are supported by this instance.
92+
*/
93+
Instance(EndpointId aEndpointId, Delegate & aDelegate, BitMask<Feature> aFeatures, BitMask<OptionalAttribute> aOptionalAttrs) :
94+
AttributeAccessInterface(MakeOptional(aEndpointId), ClosureControl::Id),
95+
CommandHandlerInterface(MakeOptional(aEndpointId), ClosureControl::Id), mDelegate(aDelegate), mFeatures(aFeatures),
96+
mOptionalAttrs(aOptionalAttrs)
97+
{
98+
/* set the base class delegates endpointId */
99+
mDelegate.SetEndpointId(aEndpointId);
100+
/* set Countdown Time quiet reporting policy as per reporting requirements in specification */
101+
mCountdownTime.policy()
102+
.Set(QuieterReportingPolicyEnum::kMarkDirtyOnIncrement)
103+
.Set(QuieterReportingPolicyEnum::kMarkDirtyOnChangeToFromZero);
104+
}
105+
~Instance() { Shutdown(); }
106+
107+
CHIP_ERROR Init();
108+
void Shutdown();
109+
110+
bool HasFeature(Feature aFeatures) const;
111+
bool SupportsOptAttr(OptionalAttribute aOptionalAttrs) const;
112+
113+
// Attribute setters
114+
/**
115+
* @brief Set Main State.
116+
* @param[in] aMainState The Main state that should now be the current one.
117+
* @return CHIP_NO_ERROR if set was successful.
118+
*/
119+
CHIP_ERROR SetMainState(MainStateEnum aMainState);
120+
121+
/**
122+
* @brief Set OverallState.
123+
* @param[in] aOverallState The OverallState that should now be the current State.
124+
* @return CHIP_NO_ERROR if set was successful.
125+
*/
126+
CHIP_ERROR SetOverallState(const GenericOverallState & aOverallState);
127+
128+
/**
129+
* @brief Set OverallTarget.
130+
* @param[in] aOverallTarget The OverallTarget that should now be the Overall Target.
131+
* @return CHIP_NO_ERROR if set was successful.
132+
*/
133+
CHIP_ERROR SetOverallTarget(const GenericOverallTarget & aOverallTarget);
134+
135+
// Attribute getters
136+
/**
137+
* @brief Get MainState.
138+
* @return Current MainState.
139+
*/
140+
MainStateEnum GetMainState() const;
141+
142+
/**
143+
* @brief Get OverallState.
144+
* @return Current OverallState.
145+
*/
146+
const GenericOverallState & GetOverallState() const;
147+
148+
/**
149+
* @brief Get OverallTarget.
150+
* @return Current OverallTarget.
151+
*/
152+
const GenericOverallTarget & GetOverallTarget() const;
153+
154+
/**
155+
* @brief Whenever application wants to trigger an update to report a new updated time,
156+
* call this method. The `GetCountdownTime()` method will be called on the application.
157+
*/
158+
inline void UpdateCountdownTimeFromDelegate() { UpdateCountdownTime(/* fromDelegate = */ true); }
159+
160+
/**
161+
* @brief This function checks if Main State is supported or not based on features supported.
162+
* @param[in] aMainState MainState
163+
* @return true if State is supported, false if State is not supported
164+
*/
165+
bool IsSupportedState(MainStateEnum aMainState);
166+
167+
protected:
168+
/**
169+
* @brief Causes reporting/udpating of CountdownTime attribute from driver if sufficient changes have
170+
* occurred (based on Q quality definition for operational state). Calls the Delegate::GetCountdownTime() method.
171+
*
172+
* @param[in] fromDelegate true if the change notice was triggered by the delegate, false if internal to cluster logic.
173+
*/
174+
void UpdateCountdownTime(bool fromDelegate);
175+
176+
/**
177+
* @brief Whenever cluster logic wants to trigger an update to report a new updated time,
178+
* call this method.
179+
*/
180+
inline void UpdateCountdownTimeFromClusterLogic() { UpdateCountdownTime(/* fromDelegate=*/false); }
181+
182+
private:
183+
Delegate & mDelegate;
184+
BitMask<Feature> mFeatures;
185+
BitMask<OptionalAttribute> mOptionalAttrs;
186+
187+
app::QuieterReportingAttribute<uint32_t> mCountdownTime{ DataModel::NullNullable };
188+
MainStateEnum mMainState;
189+
GenericOverallState mOverallState;
190+
GenericOverallTarget mOverallTarget;
191+
192+
// AttributeAccessInterface
193+
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
194+
CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override;
195+
196+
CHIP_ERROR EncodeCurrentErrorList(const AttributeValueEncoder::ListEncodeHelper & aEncoder);
197+
198+
// CommandHandlerInterface
199+
void InvokeCommand(HandlerContext & handlerContext) override;
200+
201+
void HandleStop(HandlerContext & ctx, const Commands::Stop::DecodableType & commandData);
202+
void HandleMoveTo(HandlerContext & ctx, const Commands::MoveTo::DecodableType & commandData);
203+
void HandleCalibrate(HandlerContext & ctx, const Commands::Calibrate::DecodableType & commandData);
204+
};
205+
206+
} // namespace ClosureControl
207+
} // namespace Clusters
208+
} // namespace app
209+
} // namespace chip

‎src/app/common/templates/config-data.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ CommandHandlerInterfaceOnlyClusters:
5555
- Wi-Fi Network Diagnostics
5656
- Administrator Commissioning
5757
- Actions
58+
- Closure Control
5859

5960
# We need a more configurable way of deciding which clusters have which init functions....
6061
# See https://github.com/project-chip/connectedhomeip/issues/4369

‎src/app/zap_cluster_list.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178
],
179179
"CHANNEL_CLUSTER": ["channel-server"],
180180
"CHIME_CLUSTER": ["chime-server"],
181-
"CLOSURE_CONTROL_CLUSTER": [],
181+
"CLOSURE_CONTROL_CLUSTER": ["closure-control-server"],
182182
"COLOR_CONTROL_CLUSTER": ["color-control-server"],
183183
"COMMISSIONER_CONTROL_CLUSTER": ["commissioner-control-server"],
184184
"COMMISSIONING_CLUSTER": [],

‎zzz_generated/app-common/app-common/zap-generated/callback.h

-30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.