zigbee bind, ZDO_RegisterForZDOMsg, zcl_registerForMsg

来源:互联网 发布:linux退出vi编辑 编辑:程序博客网 时间:2024/06/05 08:41

绑定方法1:

1.设备A先允许绑定

 zb_AllowBind( myAllowBindTimeout );

* @param       timeout - The number of seconds toremain in the allow binding

 *                        mode.  Valid values range from 1 through 65.

 *                        If 0, the Allow Bindmode will be set false without TO

 *                        If greater than 64, theAllow Bind mode will be true

 

此函数会调用afSetMatch以便允许匹配端点描述符

 

 

2.设备B使用地址参数为NULL的函数去请求绑定

zb_BindDevice(TRUE, TOGGLE_LIGHT_CMD_ID,NULL);

此函数里面会判断,

如果给出有效扩展地址,此函数调用APSME_BindRequest直接和目的扩展地址的设备建立绑定。绑定成功就请求对方的网络地址。设备A之前就不用执行zb_AllowBind


如果地址为NULL,则会使用ZDP_MatchDescReq和允许匹配的设备建立匹配。ZDP_MatchDescReq中会想空中发送一个clustid=Match_Desc_req的数据包

 

 

3.设备A的ZDO接收消息Match_Desc_req之后,会调用ZDO_ProcessMatchDescReq函数,

  {Match_Desc_req,                  ZDO_ProcessMatchDescReq },

在ZDO_ProcessMatchDescReq函数中,处理匹配请求并调用ZDP_MatchDescRsp向设备B发送回应。回复的clustid=Match_Desc_rsp.

同时向上层发送一个匹配响应已发送的事件,ZDO_MATCH_DESC_RSP_SENT

上层以闪灯处理这个事件以指示有个设备试图与本设备进行绑定

 

 

4.设备B会收到一个ZDO_CB_MSG消息-----为什么会是这个消息???,调用SAPI_ProcessZDOMsgs函数去处理。在此消息中判断如果clustid= Match_Desc_rsp,就调用相关函数以指示匹配结果是否成功,如果成功就调用APSME_BindRequest函数使用对方返回的的网络短地址建立绑定

 

注:.设备B会收到一个ZDO_CB_MSG消息-----为什么会是这个消息???

答:设备B收到空中消息后触发aps层函数afIncomingData,此函数调用afBuildMSGIncoming,此函数构造事件为AF_INCOMING_MSG_CMD的消息,发送到task_id是epDesc->task_id(epDesc->task_id是接收到的消息中提取的,是zdapp,所以要将这个消息发到自己的zdapp任务中去)....详细阅读下面的 关于ZDO_RegisterForZDOMsg

ZDO_RegisterForZDOMsg

 


综上,两种绑定机制,
第一种(已知扩展地址的绑定根据扩展地址直接调用APSME_BindRequest()创建绑定条目实现绑定,再得到其短地址;
第二种(未知扩展地址的绑定因地址未知,须先经过一个描述符匹配过程得到相匹配设备的16位短地址,然后根据短地址调用APSME_BindRequest()( 在 case Match_Desc_rsp)创建绑定条目实现绑定,再得到其扩展地址.

APSME_BindRequest的参数可以使短地址也可以是长地址

绑定方法2




关于ZDO_RegisterForZDOMsg,以Match_Desc_rsp 和Match_Desc_req为例分析:

比如在sapi.c的SAPI_Init里有一句  ZDO_RegisterForZDOMsg( sapi_TaskID, Match_Desc_rsp );即表明sapi任务注册了zdapp层(zdo)的簇消息Match_Desc_rsp。这样当zdo层收到消息,发现簇是Match_Desc_rsp,zdo会转发给sapi任务处理。
下图是具体流程:

1.B在sapi_init里注册了 ZDO_RegisterForZDOMsg( sapi_TaskID, Match_Desc_rsp );(当然A也注册了,但是没用到)
2.B在zb_BindDevice函数里调用ZDP_MatchDescReq函数而向空气中广播发出簇为Match_Desc_req的消息。而这个簇为Match_Desc_req消息的具体发出过程是zdapp任务使用 fillAndSend( &ZDP_TransID, dstAddr,Match_Desc_req, len )-----> AF_DataRequest( &afAddr, &ZDApp_epDesc,clusterID...)发出的。可以看在sapi任务的Match_Desc_req请求,
fillAndSend()  发送到的目的端点是0号,
其署名的zdo端点也是ZDApp_epDesc(0号端点描述符),而不是sapi_epDesc。
而这种结构体里包含了simpleDesc字段,而simpleDesc中包含了profileid
而如果端点描述符没有简单描述符,在AF_DataRequest中会直接赋值  req.profileID = ZDO_PROFILE_ID;

typedef struct
{
  byte endPoint;
  byte *task_id;  // Pointer to location of the Application task ID.
  SimpleDescriptionFormat_t *simpleDesc;
  afNetworkLatencyReq_t latencyReq;
} endPointDesc_t;
所以相当于profileid署名也是zdo的profileid
3,在接收侧 A,
a .在af.c的afIncomingData()

//#define ZDO_EP 0   // Endpoint of ZDO
//#define ZDO_PROFILE_ID 0
////如果目的端点的模式和源端点的模式相同,或者 目的端点是zdo端点和目的模式是zdo模式
 if ( (aff->ProfileID == epProfileID) ||  ((epDesc->endPoint == ZDO_EP) && (aff->ProfileID ==ZDO_PROFILE_ID)) )
            afBuildMSGIncoming( aff, epDesc, SrcAddress, SrcPanId, sig, SecurityUse,timestamp );

b.在af.c的afBuildMSGIncoming()
 MSGpkt->hdr.event = AF_INCOMING_MSG_CMD;
  {
   osal_msg_send( *(epDesc->task_id), (uint8 *)MSGpkt );//epDesc->task_id是zdapp任务
  }

所以会发到zdapp任务中去,
c. 在zdapp任务的AF_INCOMING_MSG_CMD事件中
其调用ZDP_IncomingData(),其前半部调用ZDO_SendMsgCBs(),此函数将这个消息发送到所有注册了此clusterID的任务中(当然包括sapi任务,也包括zdapp任务本身)
uint8 ZDO_SendMsgCBs( zdoIncomingMsg_t *inMsg )
{
  uint8 ret = FALSE;
  ZDO_MsgCB_t *pList = zdoMsgCBs;
  while ( pList )
  {
    if ( pList->clusterID == inMsg->clusterID )
    {
        msgPtr->hdr.event = ZDO_CB_MSG;
        osal_msg_send( pList->taskID, (uint8 *)msgPtr );
        ret = TRUE;
    }
    pList = (ZDO_MsgCB_t *)pList->next;
  }
  return ( ret );
}
d. 然后还要使用簇预定义数组函数处理之,(在ZDP_IncomingData()后半部)
 while ( zdpMsgProcs[x].clusterID != 0xFFFF )
  {
    if ( zdpMsgProcs[x].clusterID == inMsg.clusterID )
    {
      zdpMsgProcs[x].pFn( &inMsg );
      return;
    }
    x++;
  }
4.在A,由于sapi没有注册此req(Match_Desc_req),(B也没注册),所以直接由zdpMsgProcs数组里的簇处理函数ZDO_ProcessMatchDescReq处理了这个req,而ZDO_ProcessMatchDescReq函数会自动回复一个rsp消息(Match_Desc_rsp )
5. B的af层接收到rsp时(Match_Desc_rsp ),处理步骤同3一样,即如果上层(sapi)使用ZDP_MatchDescReq注册了此簇处理函数,就会发送给sapi;如果zdapp本身注册了此簇处理函数,也会发给zdapp;同样,如果簇预定义数组函数中定义了对应的处理函数,其也会调用之。而实际上,zdapp没有注册Match_Desc_rsp 簇消息,预定义数组中也没定义Match_Desc_rsp 处理函数,只有sapi任务注册了Match_Desc_rsp 簇消息,所以交由sapi的处理之(case ZDO_CB_MSG: SAPI_ProcessZDOMsgs)



关于zcl_registerForMsg, 

相比之下,这两个函数更重要,
zcl_registerAttrList
zclGeneral_RegisterCmdCallbacks

http://blog.csdn.net/songqqnew/article/details/8682826

原创粉丝点击