// 以下为 检查网络描述符中的各项参数 stackProfilePro = FALSE; selected = FALSE;
for ( stackProfile = 0; stackProfile < STACK_PROFILE_MAX; stackProfile++ ) {
pNwkDesc = NetworkList;
for ( i = 0; i < ResultCount; i++, pNwkDesc = pNwkDesc->nextDesc ) {
if ( zgConfigPANID != 0xFFFF ) {
// PAN Id is preconfigured. check if it matches if ( pNwkDesc->panId != zgConfigPANID ) continue; }
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 ) {
if ( !pNwkDesc->routerCapacity ) {
continue; } } else {
if ( !pNwkDesc->deviceCapacity ) {
continue; } } }
else if ( ZSTACK_END_DEVICE_BUILD ) {
if ( !pNwkDesc->deviceCapacity ) {
continue; } }
// check version of zigbee protocol
if ( pNwkDesc->version != _NIB.nwkProtocolVersion ) continue;
// check version of stack profile
if ( pNwkDesc->stackProfile != zgStackProfile ) {
if ( ((zgStackProfile == HOME_CONTROLS) && (pNwkDesc->stackProfile == ZIGBEEPRO_PROFILE))
|| ((zgStackProfile == ZIGBEEPRO_PROFILE) && (pNwkDesc->stackProfile == HOME_CONTROLS)) )
stackProfilePro = TRUE;
if ( stackProfile == 0 ) {
continue; } } break; }
if (i < ResultCount) {
selected = TRUE; break; }
// break if selected or stack profile pro wasn't found if ( (selected == TRUE) || (stackProfilePro == FALSE) ) {
break; } }
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 ); } ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_DISC_CNF, sizeof(ZDO_NetworkDiscoveryCfm_t), (uint8 *)&msg );//向ZDO层发送一个ZDO_NWK_DISC_CNF消息 return (ZSuccess);
} // ZDO_NetworkDiscoveryConfirmCB
那么接下来看看ZDApp是怎么处理ZDO_NWK_DISC_CNF消息的。在ZDO层找到处理消息的函数ZDApp_ProcessOSALMsg 源代码如下:
case ZDO_NWK_DISC_CNF:
if (devState != DEV_NWK_DISC) break;
if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE ) //条件成立 {
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);//根据发现的网络信息进行一些节点的配置操作
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))) ); } }
网络层加入完网络后,会发送一个加入确认到ZDO层,利用ZDO_JoinConfirmCB函数,对确认信息进行处理,下面看下源代码:
void ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )
{
(void)PanId; // remove if this parameter is used.
nwkStatus = (byte)Status; //更新网络状态 if ( Status == ZSUCCESS ) {
// LED on shows device joined
HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON ); //打开LED_3 // LED off forgets HOLD_AUTO_START
HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF);//关闭LED_4 if ( (devState == DEV_HOLD) ) {
// Began with HOLD_AUTO_START devState = DEV_NWK_JOINING; }
if ( !ZG_SECURE_ENABLED ) {
// Notify to save info into NV ZDApp_NVUpdate(); } } else {
#if defined(BLINK_LEDS)
HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH ); // Flash LED to show failure #endif }
// Notify ZDApp
ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_JOIN_IND, sizeof(osal_event_hdr_t), (byte*)NULL );//向ZDO层发送一个ZDO_NWK_JOIN_IND消息。 }
我们看是ZDO如何处理这个消息的,在 ZDApp_ProcessOSALMsg中看下源代码: case ZDO_NWK_JOIN_IND:
if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE ) {
ZDApp_ProcessNetworkJoin(); }
break;
进入此函数中看下主要进行什么操作:
void ZDApp_ProcessNetworkJoin( void ) {
if ( (devState == DEV_NWK_JOINING) ||
((devState == DEV_NWK_ORPHAN) &&
(ZDO_Config_Node_Descriptor.LogicalType == NODETYPE_ROUTER)) ) {
// Result of a Join attempt by this device. if ( nwkStatus == ZSuccess ) {
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );//设置状态改变事件 #if defined ( POWER_SAVING )
osal_pwrmgr_device( PWRMGR_BATTERY ); #endif
if ( ZG_SECURE_ENABLED && ( ZDApp_RestoreNwkKey() == false ) ) {
// wait for auth from trust center!!
devState = DEV_END_DEVICE_UNAUTH; // Start the reset timer for MAX UNAUTH time
ZDApp_ResetTimerStart( 10000 );//MAX_DEVICE_UNAUTH_TIMEOUT ); } else {
if ( ZSTACK_ROUTER_BUILD ) {
if ( devState == DEV_NWK_ORPHAN
&& ZDO_Config_Node_Descriptor.LogicalType != NODETYPE_DEVICE ) {
// Change NIB state to router for restore _NIB.nwkState = NWK_ROUTER; } }
if ( devState == DEV_NWK_JOINING ) {
ZDApp_AnnounceNewAddress(); }
devState = DEV_END_DEVICE; if ( ZSTACK_ROUTER_BUILD ) {
// NOTE: first two parameters are not used, see NLMEDE.h for details
if ( ZDO_Config_Node_Descriptor.LogicalType != NODETYPE_DEVICE ) {
NLME_StartRouterRequest( 0, 0, false ); } } }