Tool/software:
With respect to the Get Group Membership ZCL command and response, the ZCL (rev 7/8) states:
Section 3.6.2.3.4.2 (Effect on Receipt)
On receipt of the get group membership command, each receiving entity SHALL respond with group mem-
bership information using the get group membership response frame as follows:
If the group count field of the command frame has a value of 0 indicating that the group list field is empty,
the entity SHALL respond with all group identifiers of which the entity is a member.
If the group list field of the command frame contains at least one group of which the entity is a member, the
entity SHALL respond with each entity group identifier that match a group in the group list field.
If the group count is non-zero, and the group list field of the command frame does not contain any group of
which the entity is a member, the entity SHALL only respond if the command is unicast. The response
SHALL return a group count of zero.
Regarding the final case, if a client sends a get group membership command with one or more groups, and the receiving device has no groups that match those in the command, then it should send a response with group count == 0.
The current ZStack does not send a response in this scenario. The relevant code is in `source/ti/zstack/stack/zcl/zcl_general.c`:
case COMMAND_GROUPS_GET_GROUP_MEMBERSHIP: { grpCnt = *pData++; // Allocate space for the group list grpList = zcl_mem_alloc( sizeof( uint16_t ) * APS_MAX_GROUPS ); if ( grpList != NULL ) { if ( grpCnt == 0 ) { // Find out all the groups of which the endpoint is a member. grpRspCnt = aps_FindAllGroupsForEndpoint( pInMsg->msg->endPoint, grpList ); } else { // Find out the groups (in the list) of which the endpoint is a member. for ( i = 0; i < grpCnt; i++ ) { group.ID = BUILD_UINT16( pData[0], pData[1] ); pData += 2; if ( aps_FindGroup( pInMsg->msg->endPoint, group.ID ) ) grpList[grpRspCnt++] = group.ID; } } if ( grpCnt == 0 || grpRspCnt != 0 ) { zclGeneral_SendGroupGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr, aps_GroupsRemaingCapacity(), grpRspCnt, grpList, true, pInMsg->hdr.transSeqNum ); } zcl_mem_free( grpList ); } else { // Couldn't allocate space for the group list -- send a Default Response command back. zclDefaultRspCmd_t defaultRspCmd; defaultRspCmd.commandID = pInMsg->hdr.commandID; defaultRspCmd.statusCode = ZCL_STATUS_INSUFFICIENT_SPACE; zcl_SendDefaultRspCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr), pInMsg->msg->clusterId, &defaultRspCmd, ZCL_FRAME_SERVER_CLIENT_DIR, true, 0, pInMsg->hdr.transSeqNum ); } stat = ZCL_STATUS_CMD_HAS_RSP; } break;
The correct4 behavior can be implemented by changing:
if ( grpCnt == 0 || grpRspCnt != 0 )
to:
if ( grpCnt == 0 || grpRspCnt != 0 || !pInMsg->msg->wasBroadcast )