Skip to content

Commit 66c6de7

Browse files
jadhavrohit924gmarcosb
authored andcommitted
Actions: Use an instance of the Actions cluster per endpoint instead of having global delegate array. (project-chip#37799)
* Actions: Use instance of the Actions cluster per endpoint instead of having global delegate array. * Fix unit tests. * Addressed review comments. * Add error logs.
1 parent ba2e6f9 commit 66c6de7

File tree

5 files changed

+104
-169
lines changed

5 files changed

+104
-169
lines changed

examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ using namespace chip::app::Clusters::Actions;
2424
using namespace chip::app::Clusters::Actions::Attributes;
2525
using namespace chip::Protocols::InteractionModel;
2626

27+
namespace {
28+
std::unique_ptr<Clusters::Actions::ActionsDelegateImpl> sActionsDelegateImpl;
29+
std::unique_ptr<Clusters::Actions::ActionsServer> sActionsServer;
30+
} // namespace
31+
2732
CHIP_ERROR ActionsDelegateImpl::ReadActionAtIndex(uint16_t index, ActionStructStorage & action)
2833
{
2934
if (index >= kActionList.size())
@@ -129,3 +134,17 @@ Status ActionsDelegateImpl::HandleDisableActionWithDuration(uint16_t actionId, u
129134
// Not implemented
130135
return Status::NotFound;
131136
}
137+
138+
void emberAfActionsClusterInitCallback(EndpointId endpoint)
139+
{
140+
VerifyOrReturn(endpoint == 1,
141+
ChipLogError(Zcl, "Actions cluster delegate is not implemented for endpoint with id %d.", endpoint));
142+
VerifyOrReturn(emberAfContainsServer(endpoint, Actions::Id) == true,
143+
ChipLogError(Zcl, "Endpoint %d does not support Actions cluster.", endpoint));
144+
VerifyOrReturn(!sActionsDelegateImpl && !sActionsServer);
145+
146+
sActionsDelegateImpl = std::make_unique<Actions::ActionsDelegateImpl>();
147+
sActionsServer = std::make_unique<Actions::ActionsServer>(endpoint, *sActionsDelegateImpl.get());
148+
149+
sActionsServer->Init();
150+
}

examples/all-clusters-app/linux/main-common.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
#include <app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.h>
5555
#include <app/server/Server.h>
5656
#include <app/util/attribute-storage.h>
57-
#include <bridged-actions-stub.h>
5857
#include <lib/support/CHIPMem.h>
5958
#include <platform/DeviceInstanceInfoProvider.h>
6059
#include <platform/DiagnosticDataProvider.h>
@@ -87,7 +86,6 @@ Clusters::TemperatureControl::AppSupportedTemperatureLevelsDelegate sAppSupporte
8786
Clusters::ModeSelect::StaticSupportedModesManager sStaticSupportedModesManager;
8887
Clusters::ValveConfigurationAndControl::ValveControlDelegate sValveDelegate;
8988
Clusters::TimeSynchronization::ExtendedTimeSyncDelegate sTimeSyncDelegate;
90-
Clusters::Actions::ActionsDelegateImpl sActionsDelegateImpl;
9189

9290
// Please refer to https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces
9391
constexpr const uint8_t kNamespaceCommon = 7;
@@ -342,12 +340,6 @@ void emberAfThermostatClusterInitCallback(EndpointId endpoint)
342340
SetDefaultDelegate(endpoint, &delegate);
343341
}
344342

345-
void emberAfActionsClusterInitCallback(EndpointId endpoint)
346-
{
347-
VerifyOrReturn(endpoint == 1);
348-
Clusters::Actions::ActionsServer::Instance().SetDefaultDelegate(endpoint, &sActionsDelegateImpl);
349-
}
350-
351343
Status emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId,
352344
const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
353345
uint16_t maxReadLength)

src/app/clusters/actions-server/actions-server.cpp

+27-125
Original file line numberDiff line numberDiff line change
@@ -32,44 +32,22 @@ using namespace chip::app::Clusters::Actions;
3232
using namespace chip::app::Clusters::Actions::Attributes;
3333
using namespace chip::Protocols::InteractionModel;
3434

35-
namespace {
36-
static constexpr size_t kActionsDelegateTableSize =
37-
MATTER_DM_ACTIONS_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT;
38-
static_assert(kActionsDelegateTableSize <= kEmberInvalidEndpointIndex, "Actions Delegate table size error");
39-
40-
// TODO: We should not use global array, instead we can use one cluster instance per endpoint.
41-
Delegate * gDelegateTable[kActionsDelegateTableSize] = { nullptr };
42-
43-
Delegate * GetDelegate(EndpointId aEndpoint)
35+
ActionsServer::~ActionsServer()
4436
{
45-
return (aEndpoint >= kActionsDelegateTableSize ? nullptr : gDelegateTable[aEndpoint]);
37+
Shutdown();
4638
}
4739

48-
CHIP_ERROR ValidateDelegate(Delegate * aDelegate, EndpointId aEndpoint)
40+
void ActionsServer::Shutdown()
4941
{
50-
if (aDelegate == nullptr)
51-
{
52-
ChipLogError(Zcl, "Actions delegate is null for endpoint: %d !!!", aEndpoint);
53-
return CHIP_ERROR_INCORRECT_STATE;
54-
}
55-
return CHIP_NO_ERROR;
56-
}
57-
58-
} // namespace
59-
60-
ActionsServer ActionsServer::sInstance;
61-
62-
void ActionsServer::SetDefaultDelegate(EndpointId aEndpoint, Delegate * aDelegate)
63-
{
64-
if (aEndpoint < kActionsDelegateTableSize)
65-
{
66-
gDelegateTable[aEndpoint] = aDelegate;
67-
}
42+
CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this);
43+
AttributeAccessInterfaceRegistry::Instance().Unregister(this);
6844
}
6945

70-
ActionsServer & ActionsServer::Instance()
46+
CHIP_ERROR ActionsServer::Init()
7147
{
72-
return sInstance;
48+
ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this));
49+
VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INCORRECT_STATE);
50+
return CHIP_NO_ERROR;
7351
}
7452

7553
void ActionsServer::OnStateChanged(EndpointId aEndpoint, uint16_t aActionId, uint32_t aInvokeId, ActionStateEnum aActionState)
@@ -126,14 +104,10 @@ CHIP_ERROR ActionsServer::Read(const ConcreteReadAttributePath & aPath, Attribut
126104
CHIP_ERROR ActionsServer::ReadActionListAttribute(const ConcreteReadAttributePath & aPath,
127105
const AttributeValueEncoder::ListEncodeHelper & aEncoder)
128106
{
129-
Delegate * delegate = GetDelegate(aPath.mEndpointId);
130-
ReturnErrorOnFailure(ValidateDelegate(delegate, aPath.mEndpointId));
131-
132107
for (uint16_t i = 0; i < kMaxActionListLength; i++)
133108
{
134109
ActionStructStorage action;
135-
CHIP_ERROR err = delegate->ReadActionAtIndex(i, action);
136-
110+
CHIP_ERROR err = mDelegate.ReadActionAtIndex(i, action);
137111
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
138112
{
139113
return CHIP_NO_ERROR;
@@ -147,14 +121,10 @@ CHIP_ERROR ActionsServer::ReadActionListAttribute(const ConcreteReadAttributePat
147121
CHIP_ERROR ActionsServer::ReadEndpointListAttribute(const ConcreteReadAttributePath & aPath,
148122
const AttributeValueEncoder::ListEncodeHelper & aEncoder)
149123
{
150-
Delegate * delegate = GetDelegate(aPath.mEndpointId);
151-
ReturnErrorOnFailure(ValidateDelegate(delegate, aPath.mEndpointId));
152-
153124
for (uint16_t i = 0; i < kMaxEndpointListLength; i++)
154125
{
155126
EndpointListStorage epList;
156-
157-
CHIP_ERROR err = delegate->ReadEndpointListAtIndex(i, epList);
127+
CHIP_ERROR err = mDelegate.ReadEndpointListAtIndex(i, epList);
158128
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
159129
{
160130
return CHIP_NO_ERROR;
@@ -167,9 +137,7 @@ CHIP_ERROR ActionsServer::ReadEndpointListAttribute(const ConcreteReadAttributeP
167137

168138
bool ActionsServer::HaveActionWithId(EndpointId aEndpointId, uint16_t aActionId, uint16_t & aActionIndex)
169139
{
170-
Delegate * delegate = GetDelegate(aEndpointId);
171-
VerifyOrReturnValue(ValidateDelegate(delegate, aEndpointId) == CHIP_NO_ERROR, false);
172-
return delegate->HaveActionWithId(aActionId, aActionIndex);
140+
return mDelegate.HaveActionWithId(aActionId, aActionIndex);
173141
}
174142

175143
template <typename RequestT, typename FuncT>
@@ -201,10 +169,8 @@ void ActionsServer::HandleCommand(HandlerContext & handlerContext, FuncT func)
201169
}
202170
if (actionIndex != kMaxActionListLength)
203171
{
204-
Delegate * delegate = GetDelegate(handlerContext.mRequestPath.mEndpointId);
205-
ReturnOnFailure(ValidateDelegate(delegate, handlerContext.mRequestPath.mEndpointId));
206172
ActionStructStorage action;
207-
delegate->ReadActionAtIndex(actionIndex, action);
173+
mDelegate.ReadActionAtIndex(actionIndex, action);
208174
// Check if the command bit is set in the SupportedCommands of an ations.
209175
if (!(action.supportedCommands.Raw() & (1 << handlerContext.mRequestPath.mCommandId)))
210176
{
@@ -220,139 +186,79 @@ void ActionsServer::HandleCommand(HandlerContext & handlerContext, FuncT func)
220186

221187
void ActionsServer::HandleInstantAction(HandlerContext & ctx, const Commands::InstantAction::DecodableType & commandData)
222188
{
223-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
224-
Status status = Status::InvalidInState;
225-
if (delegate != nullptr)
226-
{
227-
status = delegate->HandleInstantAction(commandData.actionID, commandData.invokeID);
228-
}
189+
Status status = mDelegate.HandleInstantAction(commandData.actionID, commandData.invokeID);
229190
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
230191
}
231192

232193
void ActionsServer::HandleInstantActionWithTransition(HandlerContext & ctx,
233194
const Commands::InstantActionWithTransition::DecodableType & commandData)
234195
{
235-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
236-
Status status = Status::InvalidInState;
237-
if (delegate != nullptr)
238-
{
239-
status =
240-
delegate->HandleInstantActionWithTransition(commandData.actionID, commandData.transitionTime, commandData.invokeID);
241-
}
196+
Status status =
197+
mDelegate.HandleInstantActionWithTransition(commandData.actionID, commandData.transitionTime, commandData.invokeID);
242198
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
243199
}
244200

245201
void ActionsServer::HandleStartAction(HandlerContext & ctx, const Commands::StartAction::DecodableType & commandData)
246202
{
247-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
248-
Status status = Status::InvalidInState;
249-
if (delegate != nullptr)
250-
{
251-
status = delegate->HandleStartAction(commandData.actionID, commandData.invokeID);
252-
}
203+
Status status = mDelegate.HandleStartAction(commandData.actionID, commandData.invokeID);
253204
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
254205
}
255206

256207
void ActionsServer::HandleStartActionWithDuration(HandlerContext & ctx,
257208
const Commands::StartActionWithDuration::DecodableType & commandData)
258209
{
259-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
260-
Status status = Status::InvalidInState;
261-
if (delegate != nullptr)
262-
{
263-
status = delegate->HandleStartActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
264-
}
210+
Status status = mDelegate.HandleStartActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
265211
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
266212
}
267213

268214
void ActionsServer::HandleStopAction(HandlerContext & ctx, const Commands::StopAction::DecodableType & commandData)
269215
{
270-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
271-
Status status = Status::InvalidInState;
272-
if (delegate != nullptr)
273-
{
274-
status = delegate->HandleStopAction(commandData.actionID, commandData.invokeID);
275-
}
216+
Status status = mDelegate.HandleStopAction(commandData.actionID, commandData.invokeID);
276217
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
277218
}
278219

279220
void ActionsServer::HandlePauseAction(HandlerContext & ctx, const Commands::PauseAction::DecodableType & commandData)
280221
{
281-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
282-
Status status = Status::InvalidInState;
283-
if (delegate != nullptr)
284-
{
285-
status = delegate->HandlePauseAction(commandData.actionID, commandData.invokeID);
286-
}
222+
Status status = mDelegate.HandlePauseAction(commandData.actionID, commandData.invokeID);
287223
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
288224
}
289225

290226
void ActionsServer::HandlePauseActionWithDuration(HandlerContext & ctx,
291227
const Commands::PauseActionWithDuration::DecodableType & commandData)
292228
{
293-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
294-
Status status = Status::InvalidInState;
295-
if (delegate != nullptr)
296-
{
297-
status = delegate->HandlePauseActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
298-
}
229+
Status status = mDelegate.HandlePauseActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
299230
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
300231
}
301232

302233
void ActionsServer::HandleResumeAction(HandlerContext & ctx, const Commands::ResumeAction::DecodableType & commandData)
303234
{
304-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
305-
Status status = Status::InvalidInState;
306-
if (delegate != nullptr)
307-
{
308-
status = delegate->HandleResumeAction(commandData.actionID, commandData.invokeID);
309-
}
235+
Status status = mDelegate.HandleResumeAction(commandData.actionID, commandData.invokeID);
310236
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
311237
}
312238

313239
void ActionsServer::HandleEnableAction(HandlerContext & ctx, const Commands::EnableAction::DecodableType & commandData)
314240
{
315-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
316-
Status status = Status::InvalidInState;
317-
if (delegate != nullptr)
318-
{
319-
status = delegate->HandleEnableAction(commandData.actionID, commandData.invokeID);
320-
}
241+
Status status = mDelegate.HandleEnableAction(commandData.actionID, commandData.invokeID);
321242
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
322243
}
323244

324245
void ActionsServer::HandleEnableActionWithDuration(HandlerContext & ctx,
325246
const Commands::EnableActionWithDuration::DecodableType & commandData)
326247
{
327-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
328-
Status status = Status::InvalidInState;
329-
if (delegate != nullptr)
330-
{
331-
status = delegate->HandleEnableActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
332-
}
248+
Status status = mDelegate.HandleEnableActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
333249
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
334250
}
335251

336252
void ActionsServer::HandleDisableAction(HandlerContext & ctx, const Commands::DisableAction::DecodableType & commandData)
337253
{
338-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
339-
Status status = Status::InvalidInState;
340-
if (delegate != nullptr)
341-
{
342-
status = delegate->HandleDisableAction(commandData.actionID, commandData.invokeID);
343-
}
254+
Status status = mDelegate.HandleDisableAction(commandData.actionID, commandData.invokeID);
344255
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
345256
}
346257

347258
void ActionsServer::HandleDisableActionWithDuration(HandlerContext & ctx,
348259
const Commands::DisableActionWithDuration::DecodableType & commandData)
349260
{
350-
Delegate * delegate = GetDelegate(ctx.mRequestPath.mEndpointId);
351-
Status status = Status::InvalidInState;
352-
if (delegate != nullptr)
353-
{
354-
status = delegate->HandleDisableActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
355-
}
261+
Status status = mDelegate.HandleDisableActionWithDuration(commandData.actionID, commandData.duration, commandData.invokeID);
356262
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
357263
}
358264

@@ -426,8 +332,4 @@ void ActionsServer::EndpointListModified(EndpointId aEndpoint)
426332
MarkDirty(aEndpoint, Attributes::EndpointLists::Id);
427333
}
428334

429-
void MatterActionsPluginServerInitCallback()
430-
{
431-
AttributeAccessInterfaceRegistry::Instance().Register(&ActionsServer::Instance());
432-
CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&ActionsServer::Instance());
433-
}
335+
void MatterActionsPluginServerInitCallback() {}

src/app/clusters/actions-server/actions-server.h

+19-4
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,24 @@ class ActionsServer : public AttributeAccessInterface, public CommandHandlerInte
114114
{
115115
public:
116116
// Register for the Actions cluster on all endpoints.
117-
ActionsServer() :
118-
AttributeAccessInterface(Optional<EndpointId>::Missing(), Actions::Id),
119-
CommandHandlerInterface(Optional<EndpointId>::Missing(), Actions::Id)
117+
ActionsServer(EndpointId aEndpointId, Delegate & aDelegate) :
118+
AttributeAccessInterface(MakeOptional(aEndpointId), Actions::Id),
119+
CommandHandlerInterface(MakeOptional(aEndpointId), Actions::Id), mDelegate(aDelegate), mEndpointId(aEndpointId)
120120
{}
121-
static ActionsServer & Instance();
121+
122+
~ActionsServer();
123+
124+
/**
125+
* Initialise the Actions server instance.
126+
* @return Returns an error if the given endpoint and cluster have not been enabled in zap, if the
127+
* AttributeAccessInterface or AttributeAccessInterface registration fails returns an error.
128+
*/
129+
CHIP_ERROR Init();
130+
131+
/**
132+
* Unregisters the CommandHandlerInterface and AttributeAccessInterface.
133+
*/
134+
void Shutdown();
122135

123136
/**
124137
* @brief
@@ -152,6 +165,8 @@ class ActionsServer : public AttributeAccessInterface, public CommandHandlerInte
152165
void EndpointListModified(EndpointId aEndpoint);
153166

154167
private:
168+
Delegate & mDelegate;
169+
EndpointId mEndpointId;
155170
static ActionsServer sInstance;
156171
static constexpr size_t kMaxEndpointListLength = 256u;
157172
static constexpr size_t kMaxActionListLength = 256u;

0 commit comments

Comments
 (0)