初学者关于协议栈中绑定流程的一点认识

本人刚接触zigbee不久,在学习中将不断记录每天的进步,期待大家的指导!!

在这里指出我还是参考了ZStack-CC2530-2.3.1-1.4.0\Projects\zstack\Samples\GenericApp例程

在协议栈中关于bind的服务主要有一下几类。
    End_Device_Bind_req       ((uint16)0x0020)
    Bind_req                            ((uint16)0x0021)
    Unbind_req                       ((uint16)0x0022)
     Bind_rsp                          (Bind_req | ZDO_RESPONSE_BIT)
    End_Device_Bind_rsp        (End_Device_Bind_req | ZDO_RESPONSE_BIT)
    Unbind_rsp                         (Unbind_req | ZDO_RESPONSE_BIT)
我借由GenericApp中 End_Device_Bind_req  服务请求来一步步说明bind蛋疼的传来传去的流程。
   假设一个bind节点1,它要发出End_Device_Bind_req请求。这个是在 GenericApp_HandleKeys发出的
  if ( keys & HAL_KEY_SW_2 )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );

      // Initiate an End Device Bind Request for the mandatory endpoint
      dstAddr.addrMode = Addr16Bit;
      dstAddr.addr.shortAddr = 0x0000; // Coordinator
      ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(),
                            GenericApp_epDesc.endPoint,
                            GENERICAPP_PROFID,
                            GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,
                            GENERICAPP_MAX_CLUSTERS, (cId_t *)GenericApp_ClusterList,
                            FALSE );
    }

在ZIGBEE SPECIFICATION有如下的描述
The End_Device_Bind_req is generated from a Local Device wishing to perform End Device Bind with a Remote Device. The                          End_Device_Bind_req is generated, typically based on some user action like a button press. The destination addressing on
this command shall be unicast, and the destination address shall be that of the  ZigBee Coordinator.
就是说这个End_Device_Bind_req 请求是发给我们的 Coordinator,代码也是这样写的。
ZDP_EndDeviceBindReq具体内容我就不贴出来了,这个函数很简单就是发送一个End_Device_Bind_req格式帧给Coordinator,帧格式为
LocalCoordinator(本地nwk地址) + SrcExtAddr (本地ieee地址)+ ep(请求bind的endpoint) + ProfileID +  NumInClusters(簇的个数) + NumOutClusters(簇列表)

就这样这个End_Device_Bind_req请求到了Coordinator,接收部分我不想多说了,要说又是一大堆了。但要注意的是Coordinator的End_Device_Bind_req请求处理函数不是在CONST zdpMsgProcItem_t zdpMsgProcs[]数组,我们不能像Match_Desc_req那样轻松的借由AF_INCOMING_MSG_CMD进入 ZDP_IncomingData调用服务函数的。相比的要绕个弯子,我们先要注册一下。
void ZDApp_RegisterCBs( void )
{
#if defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )
  ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );
#endif
#if defined ( ZDO_NWKADDR_REQUEST ) || defined ( REFLECTOR )
  ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );
#endif
#if ZG_BUILD_COORDINATOR_TYPE
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp );
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp );
  ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req ); //注册了End_Device_Bind_req 服务
#endif
#if defined ( REFLECTOR )
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req );
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );
#endif
}
这个注册函数和之前帖子提到的
ZDO_RegisterForZDOMsg( GenericApp_TaskID, End_Device_Bind_rsp );
ZDO_RegisterForZDOMsg( GenericApp_TaskID, Match_Desc_rsp );
功能一样。
End_Device_Bind_req 服务调用分为2步,首先在ZDP_IncomingData中的ZDO_SendMsgCBs标记ZDO_CB_MSG然后通过osal调用ZDApp_ProcessMsgCBs真正的完成。
ZDApp_ProcessMsgCBs这个函数之后我们会多次打交道,我在这只贴相出于End_Device_Bind_req有关的部分
switch ( inMsg->clusterID )
  {.........
case End_Device_Bind_req:
      if (ZG_DEVICE_COORDINATOR_TYPE)
      {
        ZDEndDeviceBind_t bindReq;
        ZDO_ParseEndDeviceBindReq( inMsg, &bindReq );
        ZDO_MatchEndDeviceBind( &bindReq );

        // Freeing the cluster lists - if allocated.
        if ( bindReq.numInClusters )
          osal_mem_free( bindReq.inClusters );
        if ( bindReq.numOutClusters )
          osal_mem_free( bindReq.outClusters );
      }
      break;
强调只有COORDINATOR才能处理End_Device_Bind_req请求吧,与我们之前发送部分是吻合的。
还有个别的体会的可以与本人联系

posted @ 2011-04-27 22:07  雪帕  阅读(2406)  评论(0编辑  收藏  举报