Zigbee绑定流程

来源:互联网 发布:时时彩软件平刷王 编辑:程序博客网 时间:2024/05/16 12:22

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文件中未找到?(ZDP_BindRsp()??)

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层对该消息进行响应处理了:



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)

0 0
原创粉丝点击