概述
http://hi.baidu.com/lee112168/item/a4ff46adcf676f2d020a4df6
Zigbee绑定流程(一)
绑定机制允许一个应用服务在不知道目标地址的情况下向对方(应用服务)发送数据包,发送时使用的目标地址将由应用支持子层从绑定表中自动获得,从而能是消息顺利被目标节点的一个或多个应用服务乃至分组接收。
注意:由于所有绑定信息都子啊在Zigbee协调器中,所有只有协调器才能接收绑定请求。
1.1 绑定方式:
Zigbee Device Object Bind Request
Zigbee Device Object End Device Bind Request
Device Application
1.2、绑定方式1:Zigbee Device Object Bind Request
有Zigbee device A、B和C,其中B和C是想建立绑定的两个设备,需要节点A的配合。
A连接的主机(如ARM或PC)应用会调用ZDP_BindReq()(ZDPProfile.h)来实现此绑定,该函数需要提供address、endpoint和cluster ID参数。主机发送命令给A,该命令中会带有C的信息,命令A调用该函数向B发送BindReq请求,该请求中包含C的参数address、endpoint和cluster ID等,B收到该请求后会建立关于C的绑定表。ZDP_BindReq()定义如下:
#if defined ( ZDO_BIND_UNBIND_REQUEST )
/*
* ZDP_BindReq - bind request
*
* @MT SPI_CMD_ZDO_BIND_REQ
* (UInt16 DstAddr,
* UInt64 SrcAddress,
* byte SrcEndpoint,
* uint16 ClusterID,
* zAddrType_t *DstAddress,
* byte DstEndpoint,
* byte SecuritySuite)
*
*/
#define ZDP_BindReq( dstAddr, SourceAddr, SrcEP,
ClusterID, DestinationAddr, DstEP, SecurityEnable )
ZDP_BindUnbindReq( Bind_req, dstAddr,
SourceAddr, SrcEP, ClusterID,
DestinationAddr, DstEP, SecurityEnable )
#endif
该函数的参数具体意思为:
* @param dstAddr - destination address of the message(即B,也就是绑定的原设备)
* @param SourceAddr - source 64 bit address of the binding(原绑定设备的64位地址)
* @param SrcEPIntf - Source endpoint/interface
* @param ClusterID - Binding cluster ID
* @param DestinationAddr - destination 64 bit addr of binding
* @param DstEPIntf - destination endpoint/interface
* @param SecurityEnable - Security Options
注:1)ZDO_BIND_UNBIND_REQUEST应该使能才能用此方式进行绑定
2)还可以用ZDP_UnBindReq()来解除绑定。
3)对于函数ZDP_BindUnbindReq其功能如下:
/*********************************************************************
* @fn ZDP_BindUnbindReq
*
* @brief This builds and send a Bind_req or Unbind_req message
* Depending on the ClusterID. This function
* sends a unicast message to the local coordinator.
当B收到此绑定消息后:
The target device will send back a Zigbee Device Object Bind or Unbind Response message which the ZDO code will parse and notify ZDApp.c by calling ZDApp_BindRsp() or ZDApp_UnbindRsp() with the status of the action.
注:ZDApp_BindRsp()函数在ZDApp.c文件中未找到?
Coordinator返回的绑定状态:
对于绑定时,协调器会返回以下状态到应用:
ZDP_SUCCESS, ZDP_TABLE_FULL or ZDP_NOT_SUPPORTED.
对于解除绑定时,协调器会返回以下状态到应用:
ZDP_SUCCESS, ZDP_NO_ENTRY or ZDP_NOT_SUPPORTED.
1.2、Zigbee Device Object End Device Bind Request
1)、工作原理
需要coordinator参入,若A为协调器,B和C是需要建立绑定的两个EndDevice。
节点B和C分别通过按键机制调用函数ZDP_EndDeviceBindReq,这个函数将会向协调器发出绑定请求,如果在16S内两个节点都执行了此函数,协调器就会协助实现绑定。绑定表放在OutCluster那边,即绑定表存放在输出控制命令的那边。
注意:
l 节点B和C需具有互补性,即B的outcluster是C的incluster。
l 绑定后只能是outcluster节点B给incluster节点C发送控制命令,因为只有B中保存C的信息(绑定表),不能反过来控制。
2)规定的时间
这个时间由参数APS_DEFAULT_MAXBINDING_TIME决定,默认为16秒。
3)end_device_bind_req和其响应的消息流程
涉及设备:终端C和B(进行绑定)
协调器A(协助建立绑定)
现以B和A为例说明绑定请求和响应的消息流程
(1) 终端B调用ZDP_EndDeviceBindReq()发起end_device_bind_req请求,目的地址为协调器A
该函数调用fillAndSend( &ZDP_TransID, dstAddr, End_Device_Bind_req, len );完成请求发送。注意这里的任务ID为ZDP_TransID
(2) 协调器A中
--afIncomingData()从APS(应用子层接收数据/消息)
--调用afBuildMSGIncoming()在接收的消息中添加AF_INCOMING_MSG_CMD事件,并调用osal_msg_send( *(epDesc->task_id), (uint8 *)MSGpkt )将此消息发送到应用层对应的任务中
--在osal_msg_send()中执行三个动作
OSAL_MSG_ID( msg_ptr ) = destination_task; //在消息中添加对应的任务ID
// queue message
osal_msg_enqueue( &osal_qHead, msg_ptr ); //将此消息添加到消息队列
// Signal the task that a message is waiting
osal_set_event( destination_task, SYS_EVENT_MSG );//触发SYS_EVENT_MSG事件,添加到tasksEvents[]中
到此接收到的绑定请求消息已经发到了应用层中,现在就轮到OSAL层对该消息进行响应处理了:
http://hi.baidu.com/lee112168/item/becbef4cfb1da6fea4c066f4
zigbee绑定流程(二)
--任务消息主循环函数osal_start_system()轮询任务表tasksArr[]
当有end_device_bind_req到来时,将会调用其中的ZDApp_event_loop()事件循环处理函数(因为绑定请求设定了任务为ZDP_TransID)
-- ZDApp_event_loop()
若产生SYS_EVENT_MSG事件,调用函数ZDApp_ProcessOSALMsg()对OSAL的消息进行处理。
-- ZDApp_ProcessOSALMsg()
若消息的触发事件为AF_INCOMING_MSG_CMD,调用ZDP_IncomingData()
-- ZDP_IncomingData()
在该函数中首先调用ZDO_SendMsgCBs()函数查看该消息是否注册过,若是在消息中触发ZDO_CB_MSG事件,并发送到注册过该消息的任务中,这样就调用osal_msg_send(),又会触发事件SYS_EVENT_MSG。
因为这里的end_device_bind_req注册过(ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );),所以就回到函数ZDApp_event_loop()中,再执行ZDApp_ProcessOSALMsg()函数,这时的消息事件为ZDO_CB_MSG,则会调用注册消息处理函数ZDApp_ProcessMsgCBs()
-- ZDApp_ProcessMsgCBs()
此函数是对注册过得消息进行处理,
switch ( inMsg->clusterID )
case End_Device_Bind_req:
if (ZG_DEVICE_COORDINATOR_TYPE) //只有协调器才接收End_Device_Bind_req请求
{
ZDEndDeviceBind_t bindReq;
ZDO_ParseEndDeviceBindReq( inMsg, &bindReq );
ZDO_MatchEndDeviceBind( &bindReq );
--ZDO_MatchEndDeviceBind()
处理绑定请求,若成功后会给两个终端B和C发送End_Device_Bind_rsp响应
(3)终端B接收处理绑定响应
接收End_Device_Bind_rsp响应的流程和(2)基本一样,不同之处是在ZDO_SendMsgCBs()函数中,在该函数中是将响应End_Device_Bind_rsp发送到注册该响应的任务中
osal_msg_send( pList->taskID, (uint8 *)msgPtr );
这里pList指向注册的消息列表, End_Device_Bind_rsp注册到GenericApp_TaskID任务中,所以在GenericApp_ProcessEvent()中接收处理。
当协调器接收到第一个绑定请求时,他会在一定的时限内保留这一请求并等待第二个请求的出现。(默认的最长时间间隔是16秒)。
一旦协调器接收到两个需要匹配的终端设备绑定请求时,它就会启动绑定过程,为发出请求的设备建立源绑定条目。假设在ZDO终端设备绑定请求中找到匹配,协调器将采取以下步骤:
1. 协调器发送一个ZDO解除绑定请求给第一个设备。终端设备绑定是一个切换过程,所以解除绑定请求需要发送给第一个设备,以便移除一个已有的绑定条目。
2. 等待ZDO解除绑定的应答,如果返回的状态是ZDP_NO_ENTRY,协调器可以发送一个ZDO绑定请求,在源设备(ZDP_EndDeviceBindReq()第一个参数指定的地址)中建立绑定条目。假如此时返回的状态是ZDP_SUCCESS,可继续处理第一个设备的簇标识符(解除绑定指令已经移除了绑定条目,即已经切换完成)。
3. 等待ZDO绑定应答。收到以后,继续处理第一个设备的下一个簇标识符。
4. 等第一个设备完成了以后,在第二个设备上实行同样的过程。
5. 等第二个设备也完成了,协调器向两个设备发送ZDO终端设备绑定应答消息。
注意打开编译选项:REFLECTOR和ZDO_COORDINATOR
4)实现函数
1) EndDevice--ZDP_EndDeviceBindReq【ZDProfile.c】
功能:
* @brief This builds and sends a End_Device_Bind_req message.
* This function sends a unicast message.
该函数一般在EndDevice的应用层中被调用,如在按键处理子程序zclSampleLight_HandleKeys()【zclSampleLight.c】
afStatus_t ZDP_EndDeviceBindReq( zAddrType_t *dstAddr,
uint16 LocalCoordinator,
byte endPoint,
uint16 ProfileID,
byte NumInClusters, cId_t *InClusterList,
byte NumOutClusters, cId_t *OutClusterList,
byte SecurityEnable )
参数及返回值
* @param dstAddr - destination address
* @param LocalCoordinator - short address of local coordinator
* @param epIntf - Endpoint/Interface of Simple Desc
* @param ProfileID - Profile ID
*
* The Input cluster list is the opposite of what you would think.
* This is the output cluster list of this device
* @param NumInClusters - number of input clusters
* @param InClusterList - input cluster ID list
*
* The Output cluster list is the opposite of what you would think.
* This is the input cluster list of this device
* @param NumOutClusters - number of output clusters
* @param OutClusterList - output cluster ID list
*
* @param SecurityEnable - Security Options
*
* @return afStatus_t
终端设备发起end_device_bind_re q的流程为:
1)zclSampleLight_event_loop()【zcl_sampleLight.c】Event Loop Processor for zclGeneral.
2)收到KEY_CHANGE事件时调用下面函数
zclSampleLight_HandleKeys()【zcl_sampleLight.c】
3)若判断为按按键2—》ZDP_EndDeviceBindReq()【ZDProfile.c】
4)-》fillAndSend()汇总发送
5)-》AF_DataRequest发送请求
2)Coordinator对接收到的绑定请求会执行以下函数
1)int main( void )【ZMain.c】
2)osal_start_system【OSAL.c】
在该函数中会执行在函数句柄数组tasksArr[]【OSAL_SampleLight.c】中包含的ZDO任务循环处理函数ZDApp_event_loop()
// The order in this table must be identical to the task initialization calls below in osalInitTask.
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
zcl_event_loop,
zclSampleLight_event_loop
};
以下是ZDO层的应用
3)ZDApp_event_loop()【ZDApp.c】
* @brief Main event loop for Zigbee device objects task. This function
* should be called at periodic intervals.
uint8 *msg_ptr;
。。。
if ( events & SYS_EVENT_MSG )
{
while ( (msg_ptr = osal_msg_receive( ZDAppTaskID )) )
{
ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );
// Release the memory
osal_msg_deallocate( msg_ptr );
}
zigbee绑定流程(三)
该函数在收到消息SYS_EVENT_MSG后执行下面的函数:
4)ZDApp_ProcessOSALMsg()【ZDApp.c】处理接收到的任务消息
….
switch ( msgPtr->event )
{
// Incoming ZDO Message
case AF_INCOMING_MSG_CMD:
ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr );
break;
case ZDO_CB_MSG:
ZDApp_ProcessMsgCBs( (zdoIncomingMsg_t *)msgPtr );
break;
该函数根据接收到的ZDO消息类型分别调用以下两个函数:
5-1)ZDP_IncomingData() 【ZDProfile.c】 //接收信息
* @brief This function indicates the transfer of a data PDU (ASDU)
* from the APS sub-layer to the ZDO.
该函数通过调用ZDO_SendMsgCBs(zdoIncomingMsg_t *inMsg)【ZDProfile.c】函数向ZDO发送消息ZDO_CB_MSG
5-1)ZDApp_ProcessMsgCBs()【ZDApp.c】
该函数根据请求或响应消息的类型对其分别进行处理,如
void ZDApp_ProcessMsgCBs( zdoIncomingMsg_t *inMsg )
{
switch ( inMsg->clusterID )
{
case NWK_addr_rsp:
case IEEE_addr_rsp:
…
case Bind_req:
case Unbind_req:
…
case Bind_rsp:
case Unbind_rsp:
…
case End_Device_Bind_req: //节点发送的绑定请求
if (ZG_DEVICE_COORDINATOR_TYPE) //必须为协调器接收
{
ZDEndDeviceBind_t bindReq;
ZDO_ParseEndDeviceBindReq( inMsg, &bindReq ); //绑定请求消息的解析
ZDO_MatchEndDeviceBind( &bindReq );
。。。
}
….
注意需要提前注册End_Device_Bind_req消息,在ZDApp_RegisterCBs函数中实现【ZDApp.c】
当接收到节点发来的End_Device_Bind_req绑定请求后,该函数调用以下两个函数对信息进行处理
6-1)ZDO_ParseEndDeviceBindReq()【ZDObject.c】//解析绑定请求消息
6-2)ZDO_MatchEndDeviceBind() 【ZDObject.c】//Called to match end device binding requests
函数ZDO_MatchEndDeviceBind()主要实现两个节点设备的绑定,其主要流程为:
首先,查看收到的绑定请求是否为第一次(对应第一个节点)
若是第一次,将第一个请求的信息保存到end1中,并且若成功接收了第一个请求后,会设定超时时间16s;
若不是第一个绑定请求,则分别以第一个和第二个绑定请求为原绑定,进行比较匹配,如果匹配成功则发送匹配成功的信息end_device_bind_rsp给两个请求终端(通过调用函数ZDMatchSendState中的ZDP_EndDeviceBindRsp函数实现),并会返回ZDP_SUCCESS状态。
若匹配不成功,也发送rsp响应(直接调用函数ZDP_EndDeviceBindRsp),该响应包含匹配不成功的状态(ZDP_NO_ENTRY、ZDP_NO_MATCH)
最后
以上就是超级黑米为你收集整理的Zigbee绑定流程的全部内容,希望文章能够帮你解决Zigbee绑定流程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复