|
之前发了关于match的帖子,趁着还有劲头我就接着看了关于协议栈中关于bind服务的内容。看了之后才发现,bind要比match复杂的多了,好在参考了小峰的博客(http://wjf88223.blog.163.com/blog/static/3516800120105110493623/)才勉强看下,在这里向小峰表示十二分的感谢。虽然关于bind服务小峰已经说的很详细了,但我还是脸皮很厚的写点自己的认识,也算是记录下自己的学习过程吧。
和之前的帖子一样,我还是参考了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请求吧,与我们之前发送部分是吻合的。
说了这么多我们从只是从bind节点到了Coordinator,End_Device_Bind_req请求处理ZDO_MatchEndDeviceBind还没开始呢。别急啊,bind服务就是传来传去让你头疼的。我们要心平气和的慢慢来。感觉说这么多一个帖子太长了,我们下回再讲吧。 |
评分
-
1
查看全部评分
-
|