ZStack建立绑定关系之二终端绑定请求方式感谢frank的精辟讲解.docx
- 文档编号:10948108
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:21
- 大小:86.74KB
ZStack建立绑定关系之二终端绑定请求方式感谢frank的精辟讲解.docx
《ZStack建立绑定关系之二终端绑定请求方式感谢frank的精辟讲解.docx》由会员分享,可在线阅读,更多相关《ZStack建立绑定关系之二终端绑定请求方式感谢frank的精辟讲解.docx(21页珍藏版)》请在冰豆网上搜索。
ZStack建立绑定关系之二终端绑定请求方式感谢frank的精辟讲解
【Z-Stack建立绑定关系之二------终端绑定请求方式】感谢frank的精辟讲解!
2010-12-2809:
33:
29| 分类:
ZigBee技术 | 标签:
绑定 matched inmsg 请求 dstaddr |字号 订阅
ZDO终端设备绑定请求:
设备能告诉协调器他们想建立绑定表格报告。
该协调器将使协调并在这两个设备上创建绑定表格条目。
在这里是以SerialApp例子为例。
voidSerialApp_HandleKeys(uint8shift,uint8keys)
{
zAddrType_tdstAddr;
if(shift)
{
if(keys&HAL_KEY_SW_1)
{
}
if(keys&HAL_KEY_SW_2)
{
}
if(keys&HAL_KEY_SW_3)
{
}
if(keys&HAL_KEY_SW_4)
{
}
}
else
{
if(keys&HAL_KEY_SW_1)
{
}
if(keys&HAL_KEY_SW_2)
{
HalLedSet(HAL_LED_4,HAL_LED_MODE_OFF);
//终端设备绑定请求
//InitiateanEndDeviceBindRequestforthemandatoryendpoint
dstAddr.addrMode=Addr16Bit;
dstAddr.addr.shortAddr=0x0000; //Coordinator
ZDP_EndDeviceBindReq(&dstAddr,NLME_GetShortAddr(),
SerialApp_epDesc.endPoint,
SERIALAPP_PROFID,
SERIALAPP_MAX_CLUSTERS,
(cId_t*)SerialApp_ClusterList,
SERIALAPP_MAX_CLUSTERS,
(cId_t*)SerialApp_ClusterList,
FALSE);
}
if(keys&HAL_KEY_SW_3)
{
}
if(keys&HAL_KEY_SW_4)
{
HalLedSet(HAL_LED_4,HAL_LED_MODE_OFF);
//描述符匹配请求这也是两不同匹配方式,使用的按键不同
//InitiateaMatchDescriptionRequest(ServiceDiscovery)
dstAddr.addrMode=AddrBroadcast; //广播地址
dstAddr.addr.shortAddr=NWK_BROADCAST_SHORTADDR;
ZDP_MatchDescReq(&dstAddr,NWK_BROADCAST_SHORTADDR,
SERIALAPP_PROFID,
SERIALAPP_MAX_CLUSTERS,
(cId_t*)SerialApp_ClusterList,
SERIALAPP_MAX_CLUSTERS,
(cId_t*)SerialApp_ClusterList,
FALSE);
}
}
}
说明:
从上面可以看到,SW2是发送终端设备绑定请求方式,SW4是发送描述符匹配请求方式。
如果按下SW1的话,使用终端设备绑定请求方式,这里是要通过终端告诉协调器他们想要建立绑定表格,协调器将协调这两个请求的设备,在两个设备上建立绑定表格条目。
(1)终端设备向协调器发送终端设备绑定请求
调用ZDP_EndDeviceBindReq()函数发送绑定请求。
ZDP_EndDeviceBindReq(&dstAddr, //目的地址设为0x0000;
NLME_GetShortAddr(),
SerialApp_epDesc.endPoint, //EP号
SERIALAPP_PROFID,//ProfileID
SERIALAPP_MAX_CLUSTERS, //输入簇的数目
(cId_t*)SerialApp_ClusterList, //输入簇列表
SERIALAPP_MAX_CLUSTERS, //输出簇数目
(cId_t*)SerialApp_ClusterList,//输出簇列表
FALSE);
该函数实际调用无线发送函数将绑定请求发送给协调器节点:
默认clusterID为End_Device_Bind_req,最后通过AF_DataRequest()发送出去.
fillAndSend(&ZDP_TransID,dstAddr,End_Device_Bind_req,len);
最后通过AF_DataRequest()发送出去.
AF_DataRequest(&afAddr,&ZDApp_epDesc,clusterID,
(uint16)(len+1),(uint8*)(ZDP_TmpBuf-1),
transSeq,ZDP_TxOptions, AF_DEFAULT_RADIUS);
(2)协调器收到终端设备绑定请求End_Device_Bind_req
这个信息会传送到ZDO层,在ZDO层的事件处理函数中,调用ZDApp_ProcessOSALMsg((osal_event_hdr_t*)msg_ptr);
UINT16ZDApp_event_loop(bytetask_id,UINT16events)
{
uint8*msg_ptr;
if(events&SYS_EVENT_MSG)
{
while((msg_ptr=osal_msg_receive(ZDAppTaskID)))
{
ZDApp_ProcessOSALMsg((osal_event_hdr_t*)msg_ptr);
//Releasethememory
osal_msg_deallocate(msg_ptr);
}
//Returnunprocessedevents
return(events^SYS_EVENT_MSG);
.....................
}
voidZDApp_ProcessOSALMsg(osal_event_hdr_t*msgPtr)
{
//DataConfirmationmessagefields
bytesentEP; //Thisshouldalwaysbe0
bytesentStatus;
afDataConfirm_t*afDataConfirm;
switch(msgPtr->event)
{
//IncomingZDOMessage
caseAF_INCOMING_MSG_CMD:
ZDP_IncomingData((afIncomingMSGPacket_t*)msgPtr);
break;
................................
}
在ZDP_IncomingData((afIncomingMSGPacket_t*)msgPtr);函数中
voidZDP_IncomingData(afIncomingMSGPacket_t*pData)
{
uint8x=0;
uint8handled;
zdoIncomingMsg_tinMsg;
inMsg.srcAddr.addrMode=Addr16Bit;
inMsg.srcAddr.addr.shortAddr=pData->srcAddr.addr.shortAddr;
inMsg.wasBroadcast=pData->wasBroadcast;
inMsg.clusterID=pData->clusterId;
inMsg.SecurityUse=pData->SecurityUse;
inMsg.asduLen=pData->cmd.DataLength-1;
inMsg.asdu=pData->cmd.Data+1;
inMsg.TransSeq=pData->cmd.Data[0];
handled=ZDO_SendMsgCBs(&inMsg);
#ifdefined(MT_ZDO_FUNC)
MT_ZdoRsp(&inMsg);
#endif
while(zdpMsgProcs[x].clusterID!
=0xFFFF)
{
if(zdpMsgProcs[x].clusterID==inMsg.clusterID)
{
zdpMsgProcs[x].pFn(&inMsg);
return;
}
x++;
}
//Handleunhandledmessages
if(!
handled)
ZDApp_InMsgCB(&inMsg);
}
因为ZDO信息处理表zdpMsgProcs[]没有对应的End_Device_Bind_req簇,因此没有调用ZDO信息处理表中的处理函数,但是前面的ZDO_SendMsgCBs()会把这个终端设备绑定请求发送到登记过这个ZDO信息的任务中去。
那这个登记注册的程序在哪里呢?
对于协调器来说,由于在voidZDApp_Init(bytetask_id)函数中调用了ZDApp_RegisterCBs();面的函数。
进行注册了终端绑定请求信息。
voidZDApp_RegisterCBs(void)
{
#ifdefined(ZDO_IEEEADDR_REQUEST)||defined(REFLECTOR)
ZDO_RegisterForZDOMsg(ZDAppTaskID,IEEE_addr_rsp);
#endif
#ifdefined(ZDO_NWKADDR_REQUEST)||defined(REFLECTOR)
ZDO_RegisterForZDOMsg(ZDAppTaskID,NWK_addr_rsp);
#endif
#ifdefined(ZDO_COORDINATOR)
ZDO_RegisterForZDOMsg(ZDAppTaskID,Bind_rsp);
ZDO_RegisterForZDOMsg(ZDAppTaskID,Unbind_rsp);
ZDO_RegisterForZDOMsg(ZDAppTaskID,End_Device_Bind_req);
#endif
#ifdefined(REFLECTOR)
ZDO_RegisterForZDOMsg(ZDAppTaskID,Bind_req);
ZDO_RegisterForZDOMsg(ZDAppTaskID,Unbind_req);
#endif
}
因此,协调器节点的ZDApp接收到外界输入的数据后,由于注册了ZDO反馈消息,即ZDO_CB_MSG,ZDApp层任务事件处理函数将进行处理:
也就是调用下面的程序。
UINT16ZDApp_event_loop(bytetask_id,UINT16events)
{
uint8*msg_ptr;
if(events&SYS_EVENT_MSG)
{
while((msg_ptr=osal_msg_receive(ZDAppTaskID)))
{
ZDApp_ProcessOSALMsg((osal_event_hdr_t*)msg_ptr);
//Releasethememory
osal_msg_deallocate(msg_ptr);
}
//Returnunprocessedevents
return(events^SYS_EVENT_MSG);
..............................
}
在这里调用函数ZDApp_ProcessOSALMsg((osal_event_hdr_t*)msg_ptr);在这个函数中我们可以看到对ZDO_CB_MSG事件的处理
voidZDApp_ProcessOSALMsg(osal_event_hdr_t*msgPtr)
{
//DataConfirmationmessagefields
bytesentEP; //Thisshouldalwaysbe0
bytesentStatus;
afDataConfirm_t*afDataConfirm;
switch(msgPtr->event)
{
//IncomingZDOMessage
caseAF_INCOMING_MSG_CMD:
ZDP_IncomingData((afIncomingMSGPacket_t*)msgPtr);
break;
caseZDO_CB_MSG:
ZDApp_ProcessMsgCBs((zdoIncomingMsg_t*)msgPtr);
break;
....................................
}
调用ZDApp_ProcessMsgCBs()函数。
在这个函数中根据ClusterID(这里是End_Device_Bind_req)选择相对应的匹配描述符处理函数,
voidZDApp_ProcessMsgCBs(zdoIncomingMsg_t*inMsg)
{
switch(inMsg->clusterID)
{
#ifdefined(ZDO_NWKADDR_REQUEST)||defined(ZDO_IEEEADDR_REQUEST)||defined(REFLECTOR)
caseNWK_addr_rsp:
caseIEEE_addr_rsp:
{
ZDO_NwkIEEEAddrResp_t*pAddrRsp;
pAddrRsp=ZDO_ParseAddrRsp(inMsg);
if(pAddrRsp)
{
if(pAddrRsp->status==ZSuccess)
{
ZDO_UpdateAddrManager(pAddrRsp->nwkAddr,pAddrRsp->extAddr);
}
osal_mem_free(pAddrRsp);
}
}
break;
#endif
#ifdefined(REFLECTOR)
caseBind_req:
caseUnbind_req:
{
ZDO_BindUnbindReq_tbindReq;
ZDO_ParseBindUnbindReq(inMsg,&bindReq);
ZDO_ProcessBindUnbindReq(inMsg,&bindReq);
}
break;
#endif
#ifdefined(ZDO_COORDINATOR)
caseBind_rsp:
caseUnbind_rsp:
if(matchED)
{
ZDMatchSendState(
(uint8)((inMsg->clusterID==Bind_rsp)?
ZDMATCH_REASON_BIND_RSP:
ZDMATCH_REASON_UNBIND_RSP),
ZDO_ParseBindRsp(inMsg),inMsg->TransSeq);
}
break;
caseEnd_Device_Bind_req:
{
ZDEndDeviceBind_tbindReq;
ZDO_ParseEndDeviceBindReq(inMsg,&bindReq);//解析绑定请求信息
//然后向发送绑定请求的节点发送绑定响应消息:
ZDO_MatchEndDeviceBind(&bindReq);
//Freeingtheclusterlists-ifallocated.
if(bindReq.numInClusters)
osal_mem_free(bindReq.inClusters);
if(bindReq.numOutClusters)
osal_mem_free(bindReq.outClusters);
}
break;
#endif
}
}
下面是ZDO_MatchEndDeviceBind()函数的源代码
voidZDO_MatchEndDeviceBind(ZDEndDeviceBind_t*bindReq)
{
zAddrType_tdstAddr;
uint8sendRsp=FALSE;
uint8status;
//Isthisthefirstrequest?
接收到的是第一个绑定请求
if(matchED==NULL)
{
//Creatematchinfostructure创建匹配信息结构体
matchED=(ZDMatchEndDeviceBind_t*)osal_mem_alloc(sizeof(ZDMatchEndDeviceBind_t)); //分配空间
if(matchED)
{
//Clearthestructure先进行清除操作
osal_memset((uint8*)matchED,0,sizeof(ZDMatchEndDeviceBind_t));
//Copythefirstrequest'sinformation复制第一个请求信息
if(!
ZDO_CopyMatchInfo(&(matchED->ed1),bindReq)) //复制不成功后
{
status=ZDP_NO_ENTRY;
sendRsp=TRUE;
}
}
else //分配空间不成功
{
status=ZDP_NO_ENTRY;
sendRsp=TRUE;
}
if(!
sendRsp) //分配空间成功,复制数据结构成功
{
//Setintothecorrectstate设置正确的设备状态
matchED->state=ZDMATCH_WAIT_REQ;
//Setupthetimeout 设置计时时间APS_SetEndDeviceBindTimeout(AIB_MaxBindingTime,
ZDO_EndDeviceBindMatchTimeoutCB);
}
}
else //接收到的不是第一个绑定请求
{
matchED->state=ZDMATCH_SENDING_BINDS; //状态为绑定中
//Copythe2ndrequest'sinformation拷贝第2个请求信息结构
if(!
ZDO_CopyMatchInfo(&(matchED->ed2),bindReq)) //拷贝不成功
{
sta
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ZStack 建立 绑定 关系 终端 请求 方式 感谢 frank 精辟 讲解