This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/CC2652R: Why z-stack can send and receive( execute ) a specific command not appearing in zclCommandRec?

Part Number: CC2652R
Other Parts Discussed in Thread: Z-STACK

Tool/software: TI-RTOS

As we know, the new version of ZCL has defined two command "ZCL_CMD_DISCOVER_CMDS_RECEIVED" and "ZCL_CMD_DISCOVER_CMDS_GEN" to query what specific commands dose the target device support. But in fact in Z-stack, devices can send and receive and execute commands which can't be queried by "ZCL_CMD_DISCOVER_CMDS_RECEIVED" and "ZCL_CMD_DISCOVER_CMDS_GEN".

So I suggest fix ZCL.c like this

first, add a new function "zclMatchCmdRecs"

static uint8 zclMatchCmdRecs( uint8 endpoint, uint16 clusterID, uint8 cmdID, uint8 flag )
{
  uint8 i;
  zclCmdRecsList_t *pRec = zclFindCmdRecsList( endpoint );

  if ( pRec != NULL )
  {
    for ( i = 0; i < pRec->numCommands; i++ )
    {
      if ( pRec->pCmdRecs[i].clusterID == clusterID && pRec->pCmdRecs[i].cmdID == cmdID )
      {
        if( (pRec->pCmdRecs[i].flag & flag) != 0 ) //Match 
        {
          return ( TRUE ); // EMBEDDED RETURN
        }
      }
    }
    return ( FALSE );
  }
  
  return ( TRUE ); //Not match un-registered command
}

then, add this code in function "zcl_SendCommandEx"

ZStatus_t zcl_SendCommandEx( uint8 srcEP, afAddrType_t *destAddr,
                           uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction,
                           uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum,
                           uint16 cmdFormatLen, uint8 *cmdFormat, uint8 isReqFromApp )
{
  endPointDesc_t *epDesc;
  zclFrameHdr_t hdr;
  uint8 *msgBuf;
  uint16 msgLen;
  uint8 *pBuf;
  uint8 options;
  ZStatus_t status;

#ifdef ZCL_DISCOVER
  if( specific ) //Match command with command record, added by Luoyiming 2019-06-26
  {
    if( direction == ZCL_FRAME_SERVER_CLIENT_DIR )
    {
      if( !zclMatchCmdRecs( srcEP, clusterID, cmd, CMD_DIR_SERVER_GENERATED ) )
      {
        return ( ZFailure );
      }
    }
    else
    {
      if( !zclMatchCmdRecs( srcEP, clusterID, cmd, CMD_DIR_CLIENT_GENERATED ) )
      {
        return ( ZFailure );
      }
    }
  }
#endif // ZCL_DISCOVER


...

}

then add this code in function"zcl_ProcessMessageMSG"

zclProcMsgStatus_t zcl_ProcessMessageMSG( afIncomingMSGPacket_t *pkt )
{


  ...


  // Is this a foundation type message
  if ( !interPanMsg && zcl_ProfileCmd( inMsg.hdr.fc.type ) )
  {
    
    
    ...

    
  }
  else  // Not a foundation type message, so it must be specific to the cluster ID.
  {
    uint8 supCmd = TRUE;

#ifdef ZCL_DISCOVER
    //Match command with command record, added by Luoyiming 2019-06-26
    if( inMsg.hdr.fc.direction == ZCL_FRAME_SERVER_CLIENT_DIR )
    {
      supCmd = zclMatchCmdRecs( pkt->endPoint, pkt->clusterId, inMsg.hdr.commandID, CMD_DIR_CLIENT_RECEIVED );
    }
    else
    {
      supCmd = zclMatchCmdRecs( pkt->endPoint, pkt->clusterId, inMsg.hdr.commandID, CMD_DIR_SERVER_RECEIVED );
    }
#endif // ZCL_DISCOVER

    if ( pInPlugin && pInPlugin->pfnIncomingHdlr && supCmd )
    {
      // The return value of the plugin function will be
      //  ZSuccess - Supported and need default response
      //  ZFailure - Unsupported
      //  ZCL_STATUS_CMD_HAS_RSP - Supported and do not need default rsp
      //  ZCL_STATUS_INVALID_FIELD - Supported, but the incoming msg is wrong formatted
      //  ZCL_STATUS_INVALID_VALUE - Supported, but the request not achievable by the h/w
      //  ZCL_STATUS_SOFTWARE_FAILURE - Supported but ZStack memory allocation fails
      status = pInPlugin->pfnIncomingHdlr( &inMsg );
      if ( status == ZCL_STATUS_CMD_HAS_RSP || ( interPanMsg && status == ZSuccess ) )
      {
        rawAFMsg = NULL;
        return ( ZCL_PROC_SUCCESS ); // We're done
      }
    }

    ...



}

  • Hi,

    Thanks for the suggestion. To me it seems feasible but unnecessary.

    First,

    In your function zclMatchCmdRecs(), should 

    return ( TRUE ); //Not match un-registered command

    be replaced with

    return ( FALSE ); //Not match un-registered command

    ?

    I don't believe this functionality is necessary because:
    Suppose you have device A with cluster1, which uses a set of commands cmds1. Now suppose you have device B, and it sends a command x to device 1.
    Then there are two cases:
    1. x is in cmds1. In this case, the corresponding cluster 1 handler (eg. zclGeneral_ProcessInOnOff() for the OnOff cluster) will call the application callback that was registered for the destination endpoint of x.
    2. x is not in cmds1. In this case, the corresponding cluster 1 handler will call the application callback that was registered for the destination endpoint of x.
    However, since x is a command unknown for cluster1, the handler will return stat = ZFailure (eg. see zclGeneral_ProcessInOnOff()).
    Functionality is equivalent in both cases whether or not your edits are included in zcl.c

    A similar argument can be made for commands that are sent from the application.
    In this case, the application should know which commands its clusters support.

    Regards,
    Toby

  • What command can be execute by device is determined by cluster handler. But what command is supported by device can be appearing by using ZCL_DISCOVER. 

    Some advanced permissions device such as coordinate or ZNP can control every type of device, it can discover other device what commands and attribute supporting, but it won't appear its commands and attribute, its commands and attribute also can't be discovered by other device. It don't need to register cluster handler, zlcCommandRec, attribute table.