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.

Z-Stack 3.0.2 的 Discover Command Rsponse 命令的 Callback 参数有 BUG

Other Parts Discussed in Thread: Z-STACK, CC2538

协议栈:Z-Stack 3.0.2

协调器:CC2538

1、问题描述

(1)我用终端主动发送 “Discover Commands Received Response” 命令给协调器。

 (2)协调器在应用层的 ZCL_CMD_DISCOVER_CMDS_RECEIVED_RSP 中处理此消息。

  • static uint8 zclGenericApp_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg )
  • {
  •     zclDiscoverCmdsCmdRsp_t *discoverRspCmd;
  •     uint8 i;
  •     discoverRspCmd = (zclDiscoverCmdsCmdRsp_t *)pInMsg->attrCmd;
  •     for ( i = 0; i < discoverRspCmd->numCmd; i++ )
  •     {
  •         // Device is notified of the result of its attribute discovery command.
  •     }
  •     return ( TRUE );
  • }

(3)发现获取到的命令ID与终端发送过来的命令ID不同。

2、我更改 zclDiscoverCmdsCmdRsp_t 结构体后就可以了。

将:

typedef struct
{
uint8 discComplete;
uint8 cmdType; // either ZCL_CMD_DISCOVER_CMDS_GEN or ZCL_CMD_DISCOVER_CMDS_RECEIVED
uint8 numCmd; // number of provided commands
uint8 *pCmdID; // variable length array
} zclDiscoverCmdsCmdRsp_t;

改为:

typedef struct
{
uint8 discComplete;
uint8 cmdType; // either ZCL_CMD_DISCOVER_CMDS_GEN or ZCL_CMD_DISCOVER_CMDS_RECEIVED
uint8 numCmd; // number of provided commands
uint8 pCmdID[]; // variable length array
} zclDiscoverCmdsCmdRsp_t;

为什么像 zclDiscoverAttrsRspCmd_t 、zclReportCmd_t 这些结构体都是用数组 uint8 pCmdID[]; 而 zclDiscoverCmdsCmdRsp_t 却是用 uint8 *pCmdID; 呢,这两者有区别吗?

  • 你好,请使用下面的函数进行解析:

    static void *zclParseInDiscCmdsRspCmd( zclParseCmd_t *pCmd )
    {
      zclDiscoverCmdsCmdRsp_t *pDiscoverRspCmd;
      uint8 *pBuf = pCmd->pData;
      uint8 numCmds = ZCLDISCRSPCMD_DATALEN(pCmd->dataLen);  // length of command ID variable array
    
        // allocate memory for size of structure plus variable array
      pDiscoverRspCmd = (zclDiscoverCmdsCmdRsp_t *)zcl_mem_alloc( sizeof ( zclDiscoverCmdsCmdRsp_t ) +
                        ( numCmds * sizeof(uint8) ) );
      if ( pDiscoverRspCmd != NULL )
      {
        uint8 i;
        pDiscoverRspCmd->discComplete = *pBuf++;
        pDiscoverRspCmd->numCmd = numCmds;
    
        for ( i = 0; i < numCmds; i++ )
        {
          pDiscoverRspCmd->pCmdID[i] = *pBuf++;
        }
      }
    
      return ( (void *)pDiscoverRspCmd );
    }
    

  • 你好,你发给我的这个解析函数跟 Z-Stack 3.0.2 是一样的啊?

  • 我是通过更改 zclDiscoverCmdsCmdRsp_t 和 zclProcessInDiscCmd 处理函数来修复这个BUG的。我以为只有 Z-Stack 3.0.1 有这个问题,没想到 3.0.2 还是有这个问题。

    /* 修订编号:20180913022
    * ----- commented by Jesse_嘉伟 2018/05/03 ------
    *
    typedef struct
    {
      uint8 discComplete;
      uint8 cmdType;    // either ZCL_CMD_DISCOVER_CMDS_GEN or ZCL_CMD_DISCOVER_CMDS_RECEIVED
      uint8 numCmd;     // number of provided commands
      uint8 *pCmdID;    // variable length array
    } zclDiscoverCmdsCmdRsp_t;
    * 
    */
    /* ------ Added by Jesse_嘉伟 2018/05/03 ----- */ typedef struct { uint8 discComplete; uint8 cmdType; // either ZCL_CMD_DISCOVER_CMDS_GEN or ZCL_CMD_DISCOVER_CMDS_RECEIVED uint8 numCmd; // number of provided commands uint8 pCmdID[]; // variable length array } zclDiscoverCmdsCmdRsp_t; /* ----------------------------------------- */

    /* 修订编号:20180913031
    * ----- commented by Jesse_嘉伟 2018/05/03 ------
    *
    static uint8 zclProcessInDiscCmd( zclIncoming_t *pInMsg )
    {
      zclDiscoverCmdsCmd_t *pDiscoverCmd;
      zclDiscoverCmdsCmdRsp_t cmdRsp;
      ZStatus_t status;
      zclCommandRec_t cmdRec;
      uint8 cmdID;
      uint8 i;
      uint8 j;
    
      pDiscoverCmd = (zclDiscoverCmdsCmd_t *)pInMsg->attrCmd;
    
      // Find out the number of commands supported within the specified range
      for ( i = 0, cmdID = pDiscoverCmd->startCmdID; i < pDiscoverCmd->maxCmdID; i++, cmdID++ )
      {
        if ( !zclFindNextCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.commandID, pInMsg->hdr.fc.direction, &cmdID, &cmdRec ) )
        {
          break;  // Command not supported
        }
      }
    
      // Allocate space for the response command
      cmdRsp.pCmdID = zcl_mem_alloc( i ); // size of number of commands returned
    
      if ( cmdRsp.pCmdID == NULL )
      {
        return FALSE; // EMBEDDED RETURN
      }
    
      if ( i != 0 )
      {
        for ( j = 0, cmdID = pDiscoverCmd->startCmdID; j < i; j++, cmdID++ )
        {
          if ( !zclFindNextCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.commandID, pInMsg->hdr.fc.direction, &cmdID, &cmdRec ) )
          {
            break; // Attribute not supported
          }
    
          cmdRsp.pCmdID[j] = cmdRec.cmdID;
        }
      }
    
      // Are there more commands to be discovered?
      if ( zclFindNextCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.commandID, pInMsg->hdr.fc.direction, &cmdID, &cmdRec ) )
      {
        cmdRsp.discComplete = FALSE;
      }
      else
      {
        cmdRsp.discComplete = TRUE;
      }
    
      // pass the command requested
      cmdRsp.cmdType = pInMsg->hdr.commandID;
    
      // store number of commands returned
      cmdRsp.numCmd = j;
    
      status = zcl_SendDiscoverCmdsRspCmd( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
                                          pInMsg->msg->clusterId, &cmdRsp, !(pInMsg->hdr.fc.direction),
                                          true, pInMsg->hdr.transSeqNum );
    
      zcl_mem_free( cmdRsp.pCmdID );
    
      if ( status == ZSuccess )
      {
        return TRUE;
      }
      else
      {
        return FALSE;
      }
    }
    * 
    */
    /* ------ Added by Jesse_嘉伟 2018/05/03 ----- */
    static uint8 zclProcessInDiscCmd( zclIncoming_t *pInMsg )
    {
      zclDiscoverCmdsCmd_t *pDiscoverCmd;
      zclDiscoverCmdsCmdRsp_t* cmdRsp;
      ZStatus_t status;
      zclCommandRec_t cmdRec;
      uint8 cmdID;
      uint8 i;
      uint8 j;
    
      pDiscoverCmd = (zclDiscoverCmdsCmd_t *)pInMsg->attrCmd;
    
      // Find out the number of commands supported within the specified range
      for ( i = 0, cmdID = pDiscoverCmd->startCmdID; i < pDiscoverCmd->maxCmdID; i++, cmdID++ )
      {
        if ( !zclFindNextCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.commandID, pInMsg->hdr.fc.direction, &cmdID, &cmdRec ) )
        {
          break;  // Command not supported
        }
      }
    
      // Allocate space for the response command
      cmdRsp = (zclDiscoverCmdsCmdRsp_t *)zcl_mem_alloc( sizeof ( zclDiscoverCmdsCmdRsp_t ) + ( i * sizeof(uint8) ) );
      if ( cmdRsp == NULL )
      {
        return FALSE; // EMBEDDED RETURN
      }  
    
      if ( i != 0 )
      {
        for ( j = 0, cmdID = pDiscoverCmd->startCmdID; j < i; j++, cmdID++ )
        {
          if ( !zclFindNextCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.commandID, pInMsg->hdr.fc.direction, &cmdID, &cmdRec ) )
          {
            break; // Attribute not supported
          }
          cmdRsp->pCmdID[j] = cmdRec.cmdID;
        }
      }
    
      // Are there more commands to be discovered?
      if ( zclFindNextCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.commandID, pInMsg->hdr.fc.direction, &cmdID, &cmdRec ) )
      {
        cmdRsp->discComplete = FALSE;
      }
      else
      {
        cmdRsp->discComplete = TRUE;
      }
    
      // pass the command requested
      cmdRsp->cmdType = pInMsg->hdr.commandID;
    
      // store number of commands returned
      cmdRsp->numCmd = j;
    
      status = zcl_SendDiscoverCmdsRspCmd( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
                                          pInMsg->msg->clusterId, cmdRsp, !(pInMsg->hdr.fc.direction),
                                          true, pInMsg->hdr.transSeqNum );
    
      zcl_mem_free( cmdRsp );
    
      if ( status == ZSuccess )
      {
        return TRUE;
      }
      else
      {
        return FALSE;
      }
    }
    /* ----------------------------------------- */

  • zclProcessInDiscCmd:

      if ( i != 0 )
      {
        for ( j = 0, cmdID = pDiscoverCmd->startCmdID; j < i; j++, cmdID++ )
        {
          if ( !zclFindNextCmdRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, pInMsg->hdr.commandID, pInMsg->hdr.fc.direction, &cmdID, &cmdRec ) )
          {
            break; // Attribute not supported
          }
    
          cmdRsp.pCmdID[j] = cmdRec.cmdID;
        }
      }

    当用zcl_SendDiscoverCmdsRspCmd 回复里面:

        uint8 *pBuf = pCmdBuf;
    
        // Load the buffer - serially
        *pBuf++ = pDiscoverRspCmd->discComplete;
        for ( i = 0; i < pDiscoverRspCmd->numCmd; i++ )
        {
          *pBuf++ = pDiscoverRspCmd->pCmdID[i];
        }

    在zclParseInDiscCmdsRspCmd 处理也是这么拿出来的.

    if ( pDiscoverRspCmd != NULL )
    {
    uint8 i;
    pDiscoverRspCmd->discComplete = *pBuf++;
    pDiscoverRspCmd->numCmd = numCmds;

    for ( i = 0; i < numCmds; i++ )
    {
    pDiscoverRspCmd->pCmdID[i] = *pBuf++;
    }
    }

    应该没有什么问题吧

  • 好像是 zclProcessInDiscCmd 命令处理错误的问题,zclParseInDiscCmdsRspCmd 解析出来的 cmd id 还是正确的,你可以用原版的协议栈来测试一下。