Skip to content

Commit

Permalink
Groups cluster server implemented using the Group Data provider. (#11132
Browse files Browse the repository at this point in the history
)

* Groups cluster server implemented using the Group Data provider.

* Groups cluster server: Review comments applied.

* Groups cluster server: Review comments applied.

* Groups cluster server: Review comments applied.

* Groups cluster server: Review comments applied.

* Groups cluster server: Rebased.
  • Loading branch information
rcasallas-silabs authored and pull[bot] committed Nov 27, 2023
1 parent aa7f7db commit 49b1838
Show file tree
Hide file tree
Showing 35 changed files with 1,866 additions and 506 deletions.
1 change: 1 addition & 0 deletions examples/chip-tool/templates/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ function getTests()
'TestDescriptorCluster',
'TestBasicInformation',
'TestIdentifyCluster',
'TestGroupsCluster',
'TestOperationalCredentialsCluster',
'TestModeSelectCluster',
'TestGroupMessaging',
Expand Down
509 changes: 226 additions & 283 deletions src/app/clusters/groups-server/groups-server.cpp

Large diffs are not rendered by default.

32 changes: 1 addition & 31 deletions src/app/clusters/groups-server/groups-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,6 @@
#include <app/util/basic-types.h>
#include <lib/support/Span.h>

/** @brief Get Group Name
*
* This function returns the name of a group with the provided group ID, should
* it exist.
*
* @param endpoint Endpoint Ver.: always
* @param groupId Group ID Ver.: always
* @param groupName Group Name Ver.: always
*/
void emberAfPluginGroupsServerGetGroupNameCallback(chip::EndpointId endpoint, chip::GroupId groupId, uint8_t * groupName);

/** @brief Set Group Name
*
* This function sets the name of a group with the provided group ID.
*
* @param endpoint Endpoint Ver.: always
* @param groupId Group ID Ver.: always
* @param groupName Group Name Ver.: always
*/
void emberAfPluginGroupsServerSetGroupNameCallback(chip::EndpointId endpoint, chip::GroupId groupId,
const chip::CharSpan & groupName);

/** @brief Group Names Supported
*
* This function returns whether or not group names are supported.
*
* @param endpoint Endpoint Ver.: always
*/
bool emberAfPluginGroupsServerGroupNamesSupportedCallback(chip::EndpointId endpoint);

/** @brief Groups Cluster Endpoint In Group
*
* This function is called by the framework when it needs to determine if an
Expand All @@ -59,4 +29,4 @@ bool emberAfPluginGroupsServerGroupNamesSupportedCallback(chip::EndpointId endpo
* @param endpoint The endpoint. Ver.: always
* @param groupId The group identifier. Ver.: always
*/
bool emberAfGroupsClusterEndpointInGroupCallback(chip::EndpointId endpoint, chip::GroupId groupId);
bool emberAfGroupsClusterEndpointInGroupCallback(chip::FabricIndex fabricIndex, chip::EndpointId endpoint, chip::GroupId groupId);
59 changes: 38 additions & 21 deletions src/app/clusters/scenes/scenes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ uint8_t emberAfPluginScenesServerEntriesInUse = 0;
EmberAfSceneTableEntry emberAfPluginScenesServerSceneTable[EMBER_AF_PLUGIN_SCENES_TABLE_SIZE];
#endif

static FabricIndex GetFabricIndex(app::CommandHandler * commandObj)
{
VerifyOrReturnError(nullptr != commandObj, 0);
VerifyOrReturnError(nullptr != commandObj->GetExchangeContext(), 0);
return commandObj->GetExchangeContext()->GetSessionHandle().GetFabricIndex();
}

static bool readServerAttribute(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, const char * name,
uint8_t * data, uint8_t size)
{
Expand Down Expand Up @@ -95,10 +102,11 @@ static EmberAfStatus writeServerAttribute(EndpointId endpoint, ClusterId cluster
return status;
}

bool isEndpointInGroup(EndpointId endpoint, GroupId groupId)
bool isEndpointInGroup(chip::FabricIndex fabricIndex, EndpointId endpoint, GroupId groupId)
{
#ifdef EMBER_AF_PLUGIN_GROUPS_SERVER
return (groupId == ZCL_SCENES_GLOBAL_SCENE_GROUP_ID || emberAfGroupsClusterEndpointInGroupCallback(endpoint, groupId));
return (groupId == ZCL_SCENES_GLOBAL_SCENE_GROUP_ID ||
emberAfGroupsClusterEndpointInGroupCallback(fabricIndex, endpoint, groupId));
#else
return (groupId == ZCL_SCENES_GLOBAL_SCENE_GROUP_ID);
#endif // EMBER_AF_PLUGIN_GROUPS_SERVER
Expand Down Expand Up @@ -244,15 +252,16 @@ bool emberAfScenesClusterViewSceneCallback(app::CommandHandler * commandObj, con
bool emberAfScenesClusterRemoveSceneCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Commands::RemoveScene::DecodableType & commandData)
{
auto & groupId = commandData.groupId;
auto & sceneId = commandData.sceneId;
auto fabricIndex = GetFabricIndex(commandObj);
auto & groupId = commandData.groupId;
auto & sceneId = commandData.sceneId;

EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND;
CHIP_ERROR err = CHIP_NO_ERROR;

emberAfScenesClusterPrintln("RX: RemoveScene 0x%2x, 0x%x", groupId, sceneId);

if (!isEndpointInGroup(emberAfCurrentEndpoint(), groupId))
if (!isEndpointInGroup(fabricIndex, emberAfCurrentEndpoint(), groupId))
{
status = EMBER_ZCL_STATUS_INVALID_FIELD;
}
Expand Down Expand Up @@ -302,14 +311,15 @@ bool emberAfScenesClusterRemoveSceneCallback(app::CommandHandler * commandObj, c
bool emberAfScenesClusterRemoveAllScenesCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Commands::RemoveAllScenes::DecodableType & commandData)
{
auto & groupId = commandData.groupId;
auto fabricIndex = GetFabricIndex(commandObj);
auto & groupId = commandData.groupId;

EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_FIELD;
CHIP_ERROR err = CHIP_NO_ERROR;

emberAfScenesClusterPrintln("RX: RemoveAllScenes 0x%2x", groupId);

if (isEndpointInGroup(emberAfCurrentEndpoint(), groupId))
if (isEndpointInGroup(fabricIndex, emberAfCurrentEndpoint(), groupId))
{
uint8_t i;
status = EMBER_ZCL_STATUS_SUCCESS;
Expand Down Expand Up @@ -354,13 +364,14 @@ bool emberAfScenesClusterRemoveAllScenesCallback(app::CommandHandler * commandOb
bool emberAfScenesClusterStoreSceneCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Commands::StoreScene::DecodableType & commandData)
{
auto & groupId = commandData.groupId;
auto & sceneId = commandData.sceneId;
auto fabricIndex = GetFabricIndex(commandObj);
auto & groupId = commandData.groupId;
auto & sceneId = commandData.sceneId;

EmberAfStatus status;
CHIP_ERROR err = CHIP_NO_ERROR;
emberAfScenesClusterPrintln("RX: StoreScene 0x%2x, 0x%x", groupId, sceneId);
status = emberAfScenesClusterStoreCurrentSceneCallback(emberAfCurrentEndpoint(), groupId, sceneId);
status = emberAfScenesClusterStoreCurrentSceneCallback(fabricIndex, emberAfCurrentEndpoint(), groupId, sceneId);

// Store Scene commands are only responded to when they are addressed to a
// single device.
Expand Down Expand Up @@ -389,8 +400,9 @@ bool emberAfScenesClusterStoreSceneCallback(app::CommandHandler * commandObj, co
bool emberAfScenesClusterRecallSceneCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Commands::RecallScene::DecodableType & commandData)
{
auto & groupId = commandData.groupId;
auto & sceneId = commandData.sceneId;
auto fabricIndex = GetFabricIndex(commandObj);
auto & groupId = commandData.groupId;
auto & sceneId = commandData.sceneId;

// NOTE: TransitionTime field in the RecallScene command is currently
// ignored. Per Zigbee Alliance ZCL 7 (07-5123-07):
Expand All @@ -408,7 +420,7 @@ bool emberAfScenesClusterRecallSceneCallback(app::CommandHandler * commandObj, c
EmberAfStatus status;
EmberStatus sendStatus = EMBER_SUCCESS;
emberAfScenesClusterPrintln("RX: RecallScene 0x%2x, 0x%x", groupId, sceneId);
status = emberAfScenesClusterRecallSavedSceneCallback(emberAfCurrentEndpoint(), groupId, sceneId);
status = emberAfScenesClusterRecallSavedSceneCallback(fabricIndex, emberAfCurrentEndpoint(), groupId, sceneId);
#ifdef EMBER_AF_PLUGIN_ZLL_SCENES_SERVER
if (status == EMBER_ZCL_STATUS_SUCCESS)
{
Expand All @@ -426,7 +438,8 @@ bool emberAfScenesClusterRecallSceneCallback(app::CommandHandler * commandObj, c
bool emberAfScenesClusterGetSceneMembershipCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Commands::GetSceneMembership::DecodableType & commandData)
{
auto & groupId = commandData.groupId;
auto fabricIndex = GetFabricIndex(commandObj);
auto & groupId = commandData.groupId;

CHIP_ERROR err = CHIP_NO_ERROR;
EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
Expand All @@ -435,7 +448,7 @@ bool emberAfScenesClusterGetSceneMembershipCallback(app::CommandHandler * comman

emberAfScenesClusterPrintln("RX: GetSceneMembership 0x%2x", groupId);

if (!isEndpointInGroup(emberAfCurrentEndpoint(), groupId))
if (!isEndpointInGroup(fabricIndex, emberAfCurrentEndpoint(), groupId))
{
status = EMBER_ZCL_STATUS_INVALID_FIELD;
}
Expand Down Expand Up @@ -485,12 +498,13 @@ bool emberAfScenesClusterGetSceneMembershipCallback(app::CommandHandler * comman
return true;
}

EmberAfStatus emberAfScenesClusterStoreCurrentSceneCallback(EndpointId endpoint, GroupId groupId, uint8_t sceneId)
EmberAfStatus emberAfScenesClusterStoreCurrentSceneCallback(chip::FabricIndex fabricIndex, EndpointId endpoint, GroupId groupId,
uint8_t sceneId)
{
EmberAfSceneTableEntry entry;
uint8_t i, index = EMBER_AF_SCENE_TABLE_NULL_INDEX;

if (!isEndpointInGroup(endpoint, groupId))
if (!isEndpointInGroup(fabricIndex, endpoint, groupId))
{
return EMBER_ZCL_STATUS_INVALID_FIELD;
}
Expand Down Expand Up @@ -610,9 +624,10 @@ EmberAfStatus emberAfScenesClusterStoreCurrentSceneCallback(EndpointId endpoint,
return EMBER_ZCL_STATUS_SUCCESS;
}

EmberAfStatus emberAfScenesClusterRecallSavedSceneCallback(EndpointId endpoint, GroupId groupId, uint8_t sceneId)
EmberAfStatus emberAfScenesClusterRecallSavedSceneCallback(chip::FabricIndex fabricIndex, EndpointId endpoint, GroupId groupId,
uint8_t sceneId)
{
if (!isEndpointInGroup(endpoint, groupId))
if (!isEndpointInGroup(fabricIndex, endpoint, groupId))
{
return EMBER_ZCL_STATUS_INVALID_FIELD;
}
Expand Down Expand Up @@ -755,6 +770,7 @@ bool emberAfPluginScenesServerParseAddScene(
EmberAfSceneTableEntry entry;
EmberAfStatus status;
bool enhanced = (cmd->commandId == ZCL_ENHANCED_ADD_SCENE_COMMAND_ID);
auto fabricIndex = GetFabricIndex(commandObj);
EndpointId endpoint = cmd->apsFrame->destinationEndpoint;
uint8_t i, index = EMBER_AF_SCENE_TABLE_NULL_INDEX;

Expand All @@ -764,7 +780,7 @@ bool emberAfPluginScenesServerParseAddScene(
auto fieldSetIter = extensionFieldSets.begin();

// Add Scene commands can only reference groups to which we belong.
if (!isEndpointInGroup(endpoint, groupId))
if (!isEndpointInGroup(fabricIndex, endpoint, groupId))
{
status = EMBER_ZCL_STATUS_INVALID_FIELD;
goto kickout;
Expand Down Expand Up @@ -1092,12 +1108,13 @@ bool emberAfPluginScenesServerParseViewScene(app::CommandHandler * commandObj, c
EmberAfSceneTableEntry entry = {};
EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND;
bool enhanced = (cmd->commandId == ZCL_ENHANCED_VIEW_SCENE_COMMAND_ID);
FabricIndex fabricIndex = GetFabricIndex(commandObj);
EndpointId endpoint = cmd->apsFrame->destinationEndpoint;

emberAfScenesClusterPrintln("RX: %pViewScene 0x%2x, 0x%x", (enhanced ? "Enhanced" : ""), groupId, sceneId);

// View Scene commands can only reference groups which we belong to.
if (!isEndpointInGroup(endpoint, groupId))
if (!isEndpointInGroup(fabricIndex, endpoint, groupId))
{
status = EMBER_ZCL_STATUS_INVALID_FIELD;
}
Expand Down
6 changes: 4 additions & 2 deletions src/app/clusters/scenes/scenes.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ bool emberAfPluginScenesServerParseViewScene(chip::app::CommandHandler * command
* @param groupId The group identifier. Ver.: always
* @param sceneId The scene identifier. Ver.: always
*/
EmberAfStatus emberAfScenesClusterRecallSavedSceneCallback(chip::EndpointId endpoint, chip::GroupId groupId, uint8_t sceneId);
EmberAfStatus emberAfScenesClusterRecallSavedSceneCallback(chip::FabricIndex fabricIndex, chip::EndpointId endpoint,
chip::GroupId groupId, uint8_t sceneId);

/** @brief Scenes Cluster Store Current Scene
*
Expand All @@ -114,7 +115,8 @@ EmberAfStatus emberAfScenesClusterRecallSavedSceneCallback(chip::EndpointId endp
* @param groupId The group identifier. Ver.: always
* @param sceneId The scene identifier. Ver.: always
*/
EmberAfStatus emberAfScenesClusterStoreCurrentSceneCallback(chip::EndpointId endpoint, chip::GroupId groupId, uint8_t sceneId);
EmberAfStatus emberAfScenesClusterStoreCurrentSceneCallback(chip::FabricIndex fabricIndex, chip::EndpointId endpoint,
chip::GroupId groupId, uint8_t sceneId);

/** @brief Scenes Cluster Remove Scenes In Group
*
Expand Down
Loading

0 comments on commit 49b1838

Please sign in to comment.