forked from project-chip/connectedhomeip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathactions-server.h
344 lines (293 loc) · 15.8 KB
/
actions-server.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/*
*
* Copyright (c) 2024 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-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandlerInterface.h>
#include <app/reporting/reporting.h>
#include <protocols/interaction_model/StatusCode.h>
namespace chip {
namespace app {
namespace Clusters {
namespace Actions {
static constexpr size_t kActionNameMaxSize = 128u;
static constexpr size_t kEndpointListNameMaxSize = 128u;
static constexpr size_t kEndpointListMaxSize = 256u;
class Delegate;
struct ActionStructStorage : public Structs::ActionStruct::Type
{
ActionStructStorage(){};
ActionStructStorage(uint16_t aAction, const CharSpan & aActionName, ActionTypeEnum aActionType, uint16_t aEpListID,
BitMask<CommandBits> aCommands, ActionStateEnum aActionState)
{
Set(aAction, aActionName, aActionType, aEpListID, aCommands, aActionState);
}
ActionStructStorage(const ActionStructStorage & aAction) { *this = aAction; }
ActionStructStorage & operator=(const ActionStructStorage & aAction)
{
Set(aAction.actionID, aAction.name, aAction.type, aAction.endpointListID, aAction.supportedCommands, aAction.state);
return *this;
}
void Set(uint16_t aAction, const CharSpan & aActionName, ActionTypeEnum aActionType, uint16_t aEpListID,
BitMask<CommandBits> aCommands, ActionStateEnum aActionState)
{
actionID = aAction;
type = aActionType;
endpointListID = aEpListID;
supportedCommands = aCommands;
state = aActionState;
MutableCharSpan actionName(mBuffer);
CopyCharSpanToMutableCharSpanWithTruncation(aActionName, actionName);
name = actionName;
}
private:
char mBuffer[kActionNameMaxSize];
};
struct EndpointListStorage : public Structs::EndpointListStruct::Type
{
EndpointListStorage(){};
EndpointListStorage(uint16_t aEpListId, const CharSpan & aEpListName, EndpointListTypeEnum aEpListType,
const DataModel::List<const EndpointId> & aEndpointList)
{
Set(aEpListId, aEpListName, aEpListType, aEndpointList);
}
EndpointListStorage(const EndpointListStorage & aEpList) { *this = aEpList; }
EndpointListStorage & operator=(const EndpointListStorage & aEpList)
{
Set(aEpList.endpointListID, aEpList.name, aEpList.type, aEpList.endpoints);
return *this;
}
void Set(uint16_t aEpListId, const CharSpan & aEpListName, EndpointListTypeEnum aEpListType,
const DataModel::List<const EndpointId> & aEndpointList)
{
endpointListID = aEpListId;
type = aEpListType;
size_t epListSize = std::min(aEndpointList.size(), MATTER_ARRAY_SIZE(mEpList));
for (size_t index = 0; index < epListSize; index++)
{
mEpList[index] = aEndpointList[index];
}
endpoints = DataModel::List<const EndpointId>(Span(mEpList, epListSize));
MutableCharSpan epListName(mBuffer);
CopyCharSpanToMutableCharSpanWithTruncation(aEpListName, epListName);
name = epListName;
}
private:
char mBuffer[kEndpointListNameMaxSize];
EndpointId mEpList[kEndpointListMaxSize];
};
class ActionsServer : public AttributeAccessInterface, public CommandHandlerInterface
{
public:
// Register for the Actions cluster on all endpoints.
ActionsServer(EndpointId aEndpointId, Delegate & aDelegate) :
AttributeAccessInterface(MakeOptional(aEndpointId), Actions::Id),
CommandHandlerInterface(MakeOptional(aEndpointId), Actions::Id), mDelegate(aDelegate), mEndpointId(aEndpointId)
{}
~ActionsServer();
/**
* Initialise the Actions server instance.
* @return Returns an error if the given endpoint and cluster have not been enabled in zap, if the
* AttributeAccessInterface or AttributeAccessInterface registration fails returns an error.
*/
CHIP_ERROR Init();
/**
* Unregisters the CommandHandlerInterface and AttributeAccessInterface.
*/
void Shutdown();
/**
* @brief
* Called when the state of an action is changed.
*/
void OnStateChanged(EndpointId aEndpoint, uint16_t aActionId, uint32_t aInvokeId, ActionStateEnum aActionState);
/**
* @brief
* Called when an action fails.
*/
void OnActionFailed(EndpointId aEndpoint, uint16_t aActionId, uint32_t aInvokeId, ActionStateEnum aActionState,
ActionErrorEnum aActionError);
void SetDefaultDelegate(EndpointId aEndpointId, Delegate * aDelegate);
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
/**
* A notification from an application to the sever that an ActionList is modified..
*
* @param aEndpoint The endpoint ID where the action should be updated
*/
void ActionListModified(EndpointId aEndpoint);
/**
* A notification from an application to the sever that an EndpointList is modified..
*
* @param aEndpoint The endpoint ID where the action should be updated
*/
void EndpointListModified(EndpointId aEndpoint);
private:
Delegate & mDelegate;
EndpointId mEndpointId;
static ActionsServer sInstance;
static constexpr size_t kMaxEndpointListLength = 256u;
static constexpr size_t kMaxActionListLength = 256u;
CHIP_ERROR ReadActionListAttribute(const ConcreteReadAttributePath & aPath,
const AttributeValueEncoder::ListEncodeHelper & aEncoder);
CHIP_ERROR ReadEndpointListAttribute(const ConcreteReadAttributePath & aPath,
const AttributeValueEncoder::ListEncodeHelper & aEncoder);
bool HaveActionWithId(EndpointId aEndpointId, uint16_t aActionId, uint16_t & aActionIndex);
// TODO: We should move to non-global dirty marker.
void MarkDirty(EndpointId aEndpointId, AttributeId aAttributeId)
{
MatterReportingAttributeChangeCallback(aEndpointId, Id, aAttributeId);
}
// Cannot use CommandHandlerInterface::HandleCommand directly because we need to do the HaveActionWithId() check before
// handling a command.
template <typename RequestT, typename FuncT>
void HandleCommand(HandlerContext & handlerContext, FuncT func);
void InvokeCommand(HandlerContext & handlerContext) override;
void HandleInstantAction(HandlerContext & ctx, const Commands::InstantAction::DecodableType & commandData);
void HandleInstantActionWithTransition(HandlerContext & ctx,
const Commands::InstantActionWithTransition::DecodableType & commandData);
void HandleStartAction(HandlerContext & ctx, const Commands::StartAction::DecodableType & commandData);
void HandleStartActionWithDuration(HandlerContext & ctx, const Commands::StartActionWithDuration::DecodableType & commandData);
void HandleStopAction(HandlerContext & ctx, const Commands::StopAction::DecodableType & commandData);
void HandlePauseAction(HandlerContext & ctx, const Commands::PauseAction::DecodableType & commandData);
void HandlePauseActionWithDuration(HandlerContext & ctx, const Commands::PauseActionWithDuration::DecodableType & commandData);
void HandleResumeAction(HandlerContext & ctx, const Commands::ResumeAction::DecodableType & commandData);
void HandleEnableAction(HandlerContext & ctx, const Commands::EnableAction::DecodableType & commandData);
void HandleEnableActionWithDuration(HandlerContext & ctx,
const Commands::EnableActionWithDuration::DecodableType & commandData);
void HandleDisableAction(HandlerContext & ctx, const Commands::DisableAction::DecodableType & commandData);
void HandleDisableActionWithDuration(HandlerContext & ctx,
const Commands::DisableActionWithDuration::DecodableType & commandData);
};
class Delegate
{
public:
virtual ~Delegate() = default;
/**
* Get the action at the Nth index from list of actions.
* @param index The index of the action to be returned. It is assumed that actions are indexable from 0 and with no gaps.
* @param action A reference to the ActionStructStorage which should be initialized via copy/assignments or calling Set().
* @return Returns a CHIP_NO_ERROR if there was no error and the action was returned successfully.
* CHIP_ERROR_PROVIDER_LIST_EXHAUSTED if the index is past the end of the list of actions.
*/
virtual CHIP_ERROR ReadActionAtIndex(uint16_t index, ActionStructStorage & action) = 0;
/**
* Get the EndpointList at the Nth index from list of endpointList.
* @param index The index of the endpointList to be returned. It is assumed that endpoint lists are indexable from 0 and with no
* gaps.
* @param action A reference to the EndpointListStorage which should be initialized via copy/assignments or calling Set().
* @return Returns a CHIP_NO_ERROR if there was no error and the epList was returned successfully.
* CHIP_ERROR_PROVIDER_LIST_EXHAUSTED if the index is past the end of the list of endpointLists.
*/
virtual CHIP_ERROR ReadEndpointListAtIndex(uint16_t index, EndpointListStorage & epList) = 0;
/**
* Check whether there is an action with the given actionId in the list of actions.
* @param aActionId The action ID to search for.
* @param aActionIndex A reference to the index at which an action with matching aActionId.
* @return Returns a true if matching action is found otherwise false.
*/
virtual bool HaveActionWithId(uint16_t aActionId, uint16_t & aActionIndex) = 0;
/**
* The implementations of the Handle* command callbacks below are expected to call OnStateChanged or
* OnActionFailed as needed to generate the events required by the spec.
*/
/**
* @brief Callback that will be called to handle an InstantAction command.
* @param actionId The actionId of an action.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleInstantAction(uint16_t actionId, Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle an InstantActionWithTransition command.
* @param actionId The actionId of an action.
* @param transitionTime The time for transition from the current state to the new state.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleInstantActionWithTransition(uint16_t actionId, uint16_t transitionTime,
Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a StartAction command.
* @param actionId The actionId of an action.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleStartAction(uint16_t actionId, Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a StartActionWithDuration command.
* @param actionId The actionId of an action.
* @param duration The time for which an action shall be in start state.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleStartActionWithDuration(uint16_t actionId, uint32_t duration,
Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a StopAction command.
* @param actionId The actionId of an action.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleStopAction(uint16_t actionId, Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a PauseAction command.
* @param actionId The actionId of an action.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandlePauseAction(uint16_t actionId, Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a PauseActionWithDuration command.
* @param actionId The actionId of an action.
* @param duration The time for which an action shall be in pause state.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandlePauseActionWithDuration(uint16_t actionId, uint32_t duration,
Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a ResumeAction command.
* @param actionId The actionId of an action.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleResumeAction(uint16_t actionId, Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle an EnableAction command.
* @param actionId The actionId of an action.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleEnableAction(uint16_t actionId, Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle an EnableActionWithDuration command.
* @param actionId The actionId of an action.
* @param duration The time for which an action shall be in active state.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleEnableActionWithDuration(uint16_t actionId, uint32_t duration,
Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a DisableAction command.
* @param actionId The actionId of an action.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleDisableAction(uint16_t actionId, Optional<uint32_t> invokeId) = 0;
/**
* @brief Callback that will be called to handle a DisableActionWithDuration command.
* @param actionId The actionId of an action.
* @param duration The time for which an action shall be in disable state.
* It should report Status::Success if successful and may report other Status codes if it fails.
*/
virtual Protocols::InteractionModel::Status HandleDisableActionWithDuration(uint16_t actionId, uint32_t duration,
Optional<uint32_t> invokeId) = 0;
};
} // namespace Actions
} // namespace Clusters
} // namespace app
} // namespace chip