Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CC253x固件的非标准ZCL包支持_C_Embedded_Microcontroller_Texas Instruments_Zigbee - Fatal编程技术网

CC253x固件的非标准ZCL包支持

CC253x固件的非标准ZCL包支持,c,embedded,microcontroller,texas-instruments,zigbee,C,Embedded,Microcontroller,Texas Instruments,Zigbee,我的问题是: Livolo交换机有自己的Zigbee门。我想用CC2531 USB加密狗从zigbee2mqtt连接它们。一般来说,它可以工作,但当我打开/关闭开关按钮(在物理设备上)时,开关会发送不正确的ZCL包 我绝对是微控制器编程和Zigbee架构的新手。所以我希望有人能帮我回答这些问题: 我在哪里可以截获那个格式错误的包 如何修复该包以支持Zigbee标准 我使用Z-STACK-HOME 1.2.2a固件,并按照此处所述进行编译: upd: 我想,我可以在afIncomingDat

我的问题是:

Livolo交换机有自己的Zigbee门。我想用CC2531 USB加密狗从zigbee2mqtt连接它们。一般来说,它可以工作,但当我打开/关闭开关按钮(在物理设备上)时,开关会发送不正确的ZCL包

我绝对是微控制器编程和Zigbee架构的新手。所以我希望有人能帮我回答这些问题:

  • 我在哪里可以截获那个格式错误的包
  • 如何修复该包以支持Zigbee标准
我使用Z-STACK-HOME 1.2.2a固件,并按照此处所述进行编译:

upd: 我想,我可以在afIncomingData函数中拦截AF.c文件中的消息,并在afBuildMSGIncoming中修复

所以现在我希望,有人能帮助我正确的消息格式。可由标准ZCL包裹机处理

void afIncomingData( aps_FrameFormat_t *aff, zAddrType_t *SrcAddress, uint16 SrcPanId,
                     NLDE_Signal_t *sig, uint8 nwkSeqNum, uint8 SecurityUse,
                     uint32 timestamp, uint8 radius )
{
  endPointDesc_t *epDesc = NULL;
  epList_t *pList = epList;
#if !defined ( APS_NO_GROUPS )
  uint8 grpEp = APS_GROUPS_EP_NOT_FOUND;
#endif

  if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) )
  {
#if !defined ( APS_NO_GROUPS )
    // Find the first endpoint for this group
    grpEp = aps_FindGroupForEndpoint( aff->GroupID, APS_GROUPS_FIND_FIRST );
    if ( grpEp == APS_GROUPS_EP_NOT_FOUND ) {
      // No endpoint found, default to endpoint 1.
      // In the original source code there is a return here. 
      // This prevent the messags from being forwarded.
      // For our use-case we want to capture all messages. 
      // Even if the coordinator is not in the group.
      epDesc = afFindEndPointDesc( 1 );
    }
    else {
      epDesc = afFindEndPointDesc( grpEp );
    }

    if ( epDesc == NULL )
      return;   // Endpoint descriptor not found

    pList = afFindEndPointDescList( epDesc->endPoint );
#else
    return; // Not supported
#endif
  }
  else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT )
  {
    // Set the list
    if ( pList != NULL )
    {
      epDesc = pList->epDesc;
    }
  }
  else if ( aff->DstEndPoint == 10 || aff->DstEndPoint == 11 ) {
    if ( (epDesc = afFindEndPointDesc( 1 )) )
    {
      pList = afFindEndPointDescList( epDesc->endPoint );
    }
  }
  else if ( (epDesc = afFindEndPointDesc( aff->DstEndPoint )) )
  {
    pList = afFindEndPointDescList( epDesc->endPoint );
  }

  while ( epDesc )
  {
    uint16 epProfileID = 0xFFFE;  // Invalid Profile ID

    if ( pList->pfnDescCB )
    {
      uint16 *pID = (uint16 *)(pList->pfnDescCB(
                                 AF_DESCRIPTOR_PROFILE_ID, epDesc->endPoint ));
      if ( pID )
      {
        epProfileID = *pID;
        osal_mem_free( pID );
      }
    }
    else if ( epDesc->simpleDesc )
    {
      epProfileID = epDesc->simpleDesc->AppProfId;
    }

    // First part of verification is to make sure that:
    // the local Endpoint ProfileID matches the received ProfileID OR
    // the message is specifically send to ZDO (this excludes the broadcast endpoint) OR
    // if the Wildcard ProfileID is received the message should not be sent to ZDO endpoint
    if ( (aff->ProfileID == epProfileID) ||
         ((epDesc->endPoint == ZDO_EP) && (aff->ProfileID == ZDO_PROFILE_ID)) ||
         ((epDesc->endPoint != ZDO_EP) && ( aff->ProfileID == ZDO_WILDCARD_PROFILE_ID )) )
    {
      // Save original endpoint
      uint8 endpoint = aff->DstEndPoint;

      // overwrite with descriptor's endpoint
      aff->DstEndPoint = epDesc->endPoint;

      afBuildMSGIncoming( aff, epDesc, SrcAddress, SrcPanId, sig,
                         nwkSeqNum, SecurityUse, timestamp, radius );

      // Restore with original endpoint
      aff->DstEndPoint = endpoint;
    }

    if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) )
    {
#if !defined ( APS_NO_GROUPS )
      // Find the next endpoint for this group
      grpEp = aps_FindGroupForEndpoint( aff->GroupID, grpEp );
      if ( grpEp == APS_GROUPS_EP_NOT_FOUND )
        return;   // No endpoint found

      epDesc = afFindEndPointDesc( grpEp );
      if ( epDesc == NULL )
        return;   // Endpoint descriptor not found

      pList = afFindEndPointDescList( epDesc->endPoint );
#else
      return;
#endif
    }
    else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT )
    {
      pList = pList->nextDesc;
      if ( pList )
        epDesc = pList->epDesc;
      else
        epDesc = NULL;
    }
    else
      epDesc = NULL;
  }
}

static void afBuildMSGIncoming( aps_FrameFormat_t *aff, endPointDesc_t *epDesc,
                 zAddrType_t *SrcAddress, uint16 SrcPanId, NLDE_Signal_t *sig,
                 uint8 nwkSeqNum, uint8 SecurityUse, uint32 timestamp, uint8 radius )
{
  afIncomingMSGPacket_t *MSGpkt;
  const uint8 len = sizeof( afIncomingMSGPacket_t ) + aff->asduLength;
  uint8 *asdu = aff->asdu;
  MSGpkt = (afIncomingMSGPacket_t *)osal_msg_allocate( len );

  if ( MSGpkt == NULL )
  {
    return;
  }

  MSGpkt->hdr.event = AF_INCOMING_MSG_CMD;
  MSGpkt->groupId = aff->GroupID;
  MSGpkt->clusterId = aff->ClusterID;
  afCopyAddress( &MSGpkt->srcAddr, SrcAddress );
  MSGpkt->srcAddr.endPoint = aff->SrcEndPoint;
  MSGpkt->endPoint = epDesc->endPoint;
  MSGpkt->wasBroadcast = aff->wasBroadcast;
  MSGpkt->LinkQuality = sig->LinkQuality;
  MSGpkt->correlation = sig->correlation;
  MSGpkt->rssi = sig->rssi;
  MSGpkt->SecurityUse = SecurityUse;
  MSGpkt->timestamp = timestamp;
  MSGpkt->nwkSeqNum = nwkSeqNum;
  MSGpkt->macSrcAddr = aff->macSrcAddr;
  MSGpkt->macDestAddr = aff->macDestAddr;
  MSGpkt->srcAddr.panId = SrcPanId;
  MSGpkt->cmd.TransSeqNumber = 0;
  MSGpkt->cmd.DataLength = aff->asduLength;
  MSGpkt->radius = radius;

  if ( MSGpkt->cmd.DataLength )
  {
    MSGpkt->cmd.Data = (uint8 *)(MSGpkt + 1);
    osal_memcpy( MSGpkt->cmd.Data, asdu, MSGpkt->cmd.DataLength );
  }
  else
  {
    MSGpkt->cmd.Data = NULL;
  }

#if defined ( MT_AF_CB_FUNC )
  // If ZDO or SAPI have registered for this endpoint, dont intercept it here
  if (AFCB_CHECK(CB_ID_AF_DATA_IND, *(epDesc->task_id)))
  {
    MT_AfIncomingMsg( (void *)MSGpkt );
    // Release the memory.
    osal_msg_deallocate( (void *)MSGpkt );
  }
  else
#endif
  {
    // Send message through task message.
    osal_msg_send( *(epDesc->task_id), (uint8 *)MSGpkt );
  }
}

我认为你没有正确解码帧控制字节。查看我编写的一些代码,我将其解释如下:

0x7c, // [0111 1100]
      // 011 - reserved
      // 1 - disable default response 
      // 1 - direction = "from server to client"
      // 1 - manufacturer spec = manufacturer code present
      // 00 - frame type = "Command acts across entire profile"
这是基于一个旧的ZCL规范(大约在2008年?)的,也许保留位在该规范的更高版本中具有某种意义

我相信特定于制造商的位表示这不是标准的Zigbee命令(读取属性)。如果是读取属性,我认为后面应该有偶数个字节(16位属性ID)

该帧的源和目标端点、配置文件ID和集群ID是什么

更新: 看起来您可以修改
afIncomingData()
以查看
aff
的字段,以确定确切的消息类型(帧控制、端点、集群、概要文件),然后将其交给您自己的函数进行处理(并在必要时进行响应)

但是我还要看一看
MT_AF_CB_FUNC
MT_AfIncomingMsg()
的文档,看看这是否是识别要在自己的代码中处理的帧的“官方”方法。

在函数afIncomingData和afBuildMSGIncoming的文件中添加了标记为

#if defined ( LIVOLO_SUPPORT ) 
#endif
在afIncomingData中,我添加了:

#if defined ( LIVOLO_SUPPORT )  
  else if ( aff->DstEndPoint == 0x08 ) 
  {
    if ( (epDesc = afFindEndPointDesc( 1 )) )
    {
      pList = afFindEndPointDescList( epDesc->endPoint );
    }
  }  
#endif  
它预先过滤发送到未知端点的消息

在afBuildMSGIncoming函数中:

#if defined ( LIVOLO_SUPPORT )
  uint8 fixedPackage[] = { 
        0x18, 0xd8, 0x01, // header
        0x00, 0x00, // attrId
        0x00, // success
        0x10, // boolean
        0x00
      };

  if (aff->SrcEndPoint == 0x06 && aff->DstEndPoint == 0x01 
      && aff->ClusterID == 0x0001 && aff->ProfileID == 0x0104) {

    const uint8 mlfrmdHdr[] = { 0x7c, 0xd2, 0x15, 0xd8, 0x00 }; 
    if (osal_memcmp(asdu, mlfrmdHdr, 5) == TRUE) {      
      fixedPackage[7] = asdu[aff->asduLength - 1];
      MSGpkt->cmd.DataLength = 8; // sizeof(fixedPackage)
      MSGpkt->clusterId = 0x06; // genOnOff
      asdu = fixedPackage;
    }
  }
#endif

它会将不支持的包更改为readAttrResp包。

APS帧看起来像:00 08 01 00 04 06 ba。终点08;Src端点06;群集id 00 01;档案id 01 04;thanksAPS frame*Header我应该发送什么消息来代替此非标准消息?谢谢你显示了你得到的整个格式错误的帧-我的意思是如果可能的话包括APS层?不幸的是,现在我刷新了我的加密狗,我用它作为嗅探器,没有足够的例子,一个是APS头=00 08 01 00 04 01 06 ba。
#if defined ( LIVOLO_SUPPORT )
  uint8 fixedPackage[] = { 
        0x18, 0xd8, 0x01, // header
        0x00, 0x00, // attrId
        0x00, // success
        0x10, // boolean
        0x00
      };

  if (aff->SrcEndPoint == 0x06 && aff->DstEndPoint == 0x01 
      && aff->ClusterID == 0x0001 && aff->ProfileID == 0x0104) {

    const uint8 mlfrmdHdr[] = { 0x7c, 0xd2, 0x15, 0xd8, 0x00 }; 
    if (osal_memcmp(asdu, mlfrmdHdr, 5) == TRUE) {      
      fixedPackage[7] = asdu[aff->asduLength - 1];
      MSGpkt->cmd.DataLength = 8; // sizeof(fixedPackage)
      MSGpkt->clusterId = 0x06; // genOnOff
      asdu = fixedPackage;
    }
  }
#endif