我是靠谱客的博主 听话翅膀,最近开发中收集的这篇文章主要介绍ZigBee ZDO_NetworkDiscoveryConfirmCB方法 及 ZDO_NWK_DISC_CNF事件源码分析,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
当模块调用NLME_NetworkDiscoveryRequest()搜索周边路由节点或协调器节点时,当底层发现其他模块时,会调用ZDO层的ZDO_NetworkDiscoveryConfirmCB( uint8 ResultCount, networkDesc_t *NetworkList ) 方法。我现在对这个方法的理解也是一知半解,在这里先记录一下,以后有时间再回来慢慢理解。
#define STACK_PROFILE_MAX 2
//NetworkList是一个链表,可能包括多个设备,ResultCount其实返回的是链表的节点个数
ZStatus_t ZDO_NetworkDiscoveryConfirmCB( uint8 ResultCount,
networkDesc_t *NetworkList )
{
networkDesc_t *pNwkDesc = NetworkList;
ZDO_NetworkDiscoveryCfm_t msg;
uint8 i = ResultCount;
uint8 stackProfile;
uint8 stackProfilePro;
uint8 selected;
#if defined ( ZDO_MGMT_NWKDISC_RESPONSE )
if ( zdappMgmtNwkDiscReqInProgress )
{
zdappMgmtNwkDiscReqInProgress = false;
ZDO_FinishProcessingMgmtNwkDiscReq( ResultCount, NetworkList );
return ( ZSuccess );
}
#endif
// process discovery results
stackProfilePro = FALSE;
selected = FALSE;
//用来循环不同的协议版本,不知道为什么要对协议版本进行循环
for ( stackProfile = 0; stackProfile < STACK_PROFILE_MAX; stackProfile++ )
{
//所发现的网络不论属于那个协议栈,都是加在同一个链表里NetworkList,
//故针对新一个协议版本,都得重新开查找所有网络
pNwkDesc = NetworkList;
for ( i = 0; i < ResultCount; i++, pNwkDesc = pNwkDesc->nextDesc )
{
//printf("find count:%d padId:%X rn",ResultCount,pNwkDesc->panId);
/*
zgConfigPANID其实就是f8wConfig.cfg中的ZDAPP_CONFIG_PAN_ID,
一般为0XFFFF,如果 ZDAPP_CONFIG_PAN_ID被定义为0xFFFF,
那么协调器将根据自身的IEEE地址建立一个随机的PAN ID,
如果ZDAPP_CONFIG_PAN_ID 没有被定义为0xFFFF,
那么协调器建立网络的PAN ID将由ZDAPP_CONFIG_PAN_ID指定
*/
if ( zgConfigPANID != 0xFFFF )
{
// PAN Id is preconfigured. check if it matches
/*检查發現网络的PAN ID与
配置文件指定所需要的PAN ID是否匹配,
不如不匹配后面的事件都不用做了
*/
if ( pNwkDesc->panId != zgConfigPANID )
continue;
}
/*
// The extended PanID used in ZDO layer for rejoin.
uint8 ZDO_UseExtendedPANID[Z_EXTADDR_LEN];
重新加入时,才会在事件处理函数去设置数组ZDO_UseExtendedPANID的值
nwk_ExtPANIDValid为底层方法,初值加入这个方法应该返回的false
*/
if ( nwk_ExtPANIDValid( ZDO_UseExtendedPANID) == true )
{
// If the extended Pan ID is commissioned to a non zero value
// Only join the Pan that has match EPID
if ( osal_ExtAddrEqual( ZDO_UseExtendedPANID, pNwkDesc->extendedPANID) == false )
continue;
}
// check that network is allowing joining
if ( ZSTACK_ROUTER_BUILD )
{
if ( stackProfilePro == FALSE )
{
/*
每一个网络的容量是有限制的,
pNwkDesc->routerCapacity 指本网络还允许添加多少个路由器,
pNwkDesc->deviceCapacity 指本网络还允许添加多个终端设备。
byte routerCapacity;
byte deviceCapacity;
*/
if ( !pNwkDesc->routerCapacity )
{
continue;
}
}
else
{
if ( !pNwkDesc->deviceCapacity )
{
continue;
}
}
}
else if ( ZSTACK_END_DEVICE_BUILD )//device
{
if ( !pNwkDesc->deviceCapacity )
{
continue;
}
}
// check version of zigbee protocol
//检查发现网络的协议的版本是不是与本模块的协议版本一样
if ( pNwkDesc->version != _NIB.nwkProtocolVersion )
continue;
// check version of stack profile
//检查协议栈规范的ID
if ( pNwkDesc->stackProfile != zgStackProfile )
{
/*
参考:http://blog.sina.com.cn/s/blog_69c29fb30101fka8.html
#define NETWORK_SPECIFIC 0 //“特定网络”
#define HOME_CONTROLS 1 //ZigBee协议栈规范的ID
#define ZIGBEEPRO_PROFILE 2 //ZigBeePRO协议栈规范的ID
#define GENERIC_STAR 3
#define GENERIC_TREE 4
*/
if ( ((zgStackProfile == HOME_CONTROLS) && (pNwkDesc->stackProfile == ZIGBEEPRO_PROFILE))
|| ((zgStackProfile == ZIGBEEPRO_PROFILE) && (pNwkDesc->stackProfile == HOME_CONTROLS)) )
stackProfilePro = TRUE;
if ( stackProfile == 0 )
{
continue;
}
}
// check if beacon order is the right value..
// if ( pNwkDesc->beaconOrder < ZDO_CONFIG_MAX_BO )
// continue;
// choose this pan for joining
break;
}
if (i < ResultCount)
{
selected = TRUE;
break;
}
// break if selected or stack profile pro wasn't found
if ( (selected == TRUE) || (stackProfilePro == FALSE) )
{
break;
}
}
//内层的for循环遍历完了 i 才会等于 ResultCount
//说明没有到可以加入的网络
if ( i == ResultCount )
{
msg.hdr.status = ZDO_FAIL; // couldn't find appropriate PAN to join !
}
else //已经找到网络
{
msg.hdr.status = ZDO_SUCCESS;
msg.panIdLSB = LO_UINT16( pNwkDesc->panId );
msg.panIdMSB = HI_UINT16( pNwkDesc->panId );
msg.logicalChannel = pNwkDesc->logicalChannel;
msg.version = pNwkDesc->version;
osal_cpyExtAddr( msg.extendedPANID, pNwkDesc->extendedPANID );
}
//发送消息到ZDO层,
//请到ZDO任务事件处理函数里查看ZDO_NWK_DISC_CNF这一事件的处理方式。
ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_DISC_CNF, sizeof(ZDO_NetworkDiscoveryCfm_t), (uint8 *)&msg );
return (ZSuccess);
} // ZDO_NetworkDiscoveryConfirmCB
最终会进入ZDO任务事件处理函数中的ZDApp_ProcessOSALMsg方法:
void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )
{
// Data Confirmation message fields
uint8 sentEP; // This should always be 0
uint8 sentStatus;
afDataConfirm_t *afDataConfirm;
uint8 tmp;
switch ( msgPtr->event )
{
.....
case ZDO_NWK_DISC_CNF:
if (devState != DEV_NWK_DISC)
break;
if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
{
//如果发现了设备,并且扫描的次数大于2 (NUM_DISC_ATTEMPTS)
if ( (((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->hdr.status == ZDO_SUCCESS) && (zdoDiscCounter > NUM_DISC_ATTEMPTS) )
{
//如是是首次加入,这里会加入一个新的网络
if ( devStartMode == MODE_JOIN )
{
devState = DEV_NWK_JOINING;
ZDApp_NodeProfileSync((ZDO_NetworkDiscoveryCfm_t *)msgPtr);
//申请加入父设备
//向父设备发送Associate Request请求分配设备地址。
//分配成功后,回调ZDO_JoinConfirmCB方法
if ( NLME_JoinRequest( ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->extendedPANID,
BUILD_UINT16( ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->panIdLSB, ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->panIdMSB ),
((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->logicalChannel,
ZDO_Config_Node_Descriptor.CapabilityFlags ) != ZSuccess )
{
//延迟一小会,重新初始化网络 ;这个方法最终会执行设备扫描
ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
+ ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
}
}
//如果是重新加入,注意这个网络一定是以前加入过
else if ( devStartMode == MODE_REJOIN )
{
devState = DEV_NWK_REJOIN;
// Before trying to do rejoin, check if the device has a valid short address
// If not, generate a random short address for itself
//在重新加入之前,检测设备的网络短地址是否合法
//如果不合法,则随机生成一个网络短地址
if ( _NIB.nwkDevAddress == INVALID_NODE_ADDR )
{
_NIB.nwkDevAddress = osal_rand();
ZMacSetReq( ZMacShortAddress, (byte*)&_NIB.nwkDevAddress );
}
//ZG_SECURE_ENABLED是否可用
if ( ZG_SECURE_ENABLED )
{
ZDApp_RestoreNwkKey();
}
// Check if the device has a valid PanID, if not, set it to the discovered Pan
//检测当前网络的panid是否合法,如果不合法,则将扫描出来的padid设置给当前设备
if ( _NIB.nwkPanId == INVALID_PAN_ID )
{
_NIB.nwkPanId = BUILD_UINT16( ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->panIdLSB, ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->panIdMSB );
ZMacSetReq( ZMacPanId, (byte*)&(_NIB.nwkPanId) );
}
tmp = true;
//如果tmp设置为true,Rx 的状态会一直ON,可能会影响功率
ZMacSetReq( ZMacRxOnIdle, &tmp ); // Set receiver always on during rejoin
//发起重新连接的请求
//这个函数底层会根据ZDO_UseExtendedPANID,会和之前保存的PANID做比较,确定是不是需要rejoin的那个。
if ( NLME_ReJoinRequest( ZDO_UseExtendedPANID, ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->logicalChannel) != ZSuccess )
{
//过一会再重新尝试
ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
+ ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
}
}
//暂时搞不明白啥意思
if ( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE )
{
// The receiver is on, turn network layer polling off.
//设置/改变网络检测速率,仅终端设备可用
NLME_SetPollRate( 0 );
//设置/改变队列检测速率,仅终端设备可用
NLME_SetQueuedPollRate( 0 );
//回复数据的速率??
NLME_SetResponseRate( 0 );
}
else
{
if ( (ZG_SECURE_ENABLED) && (devStartMode == MODE_JOIN) )
{
ZDApp_SavedPollRate = zgPollRate;
NLME_SetPollRate( zgRejoinPollRate );
}
}
}
else
{
if ( continueJoining )
{
#if defined ( MANAGED_SCAN )
ZDApp_NetworkInit( MANAGEDSCAN_DELAY_BETWEEN_SCANS );
#else
zdoDiscCounter++;
ZDApp_NetworkInit( (uint16)(BEACON_REQUEST_DELAY
+ ((uint16)(osal_rand()& BEACON_REQ_DELAY_MASK))) );
#endif
}
}
}
break;
......
default:
if ( ZG_SECURE_ENABLED )
ZDApp_ProcessSecMsg( msgPtr );
break;
}
}
本人也是刚接触ZigBee,以上只是个人理解,欢迎高手指点。
最后
以上就是听话翅膀为你收集整理的ZigBee ZDO_NetworkDiscoveryConfirmCB方法 及 ZDO_NWK_DISC_CNF事件源码分析的全部内容,希望文章能够帮你解决ZigBee ZDO_NetworkDiscoveryConfirmCB方法 及 ZDO_NWK_DISC_CNF事件源码分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复