本人刚接触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请求吧,与我们之前发送部分是吻合的。
还有个别的体会的可以与本人联系