zigbee bind, ZDO_RegisterForZDOMsg, zcl_registerForMsg
绑定方法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会下图是具体流程:
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;
{
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