z-stack組網過程


z-stack組網分:協調器建立網絡、路由器和終端加入網絡

暫時只記錄第一次上電建立網絡的過程,至於開啟NV_RESTORE后,恢復原有的網絡則暫時不分析。

 

一、協調器建立網絡:

1、ZDO層的ZDApp_Init中有如下函數:

  if ( devState != DEV_HOLD )     // 如果不希望自動啟動,則可以在這個函數調用前,把devState設置為DEV_HOLD,然后在需要啟動的時候設置為DEV_INIT
{ ZDOInitDevice(
0 ); // 啟動設備,里面就包含了組網 } else { // Blink LED to indicate HOLD_START HalLedBlink ( HAL_LED_4, 0, 50, 500 ); }

2、ZDOInitDevice()中如果定義了NV_RESTORD,則可以通過按鍵選擇是新建一個網絡,或者是讀取NV中的網絡進行恢復,我們這里假設NV_RESTORE沒有定義,直接新建一個網絡。

  if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE )   // 判斷是新建一個網絡
  {
    ZDAppDetermineDeviceType();    // 確定當前設備類型為NODETYPE_COORDINATOR協調器,設備啟動模式為MODE_HARD

    // Only delay if joining network - not restoring network state
    extendedDelay = (uint16)((NWK_START_DELAY + startDelay)
              + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK));
  }

  // Initialize the security for type of device
  ZDApp_SecInit( networkStateNV );

  // Trigger the network start
  ZDApp_NetworkInit( extendedDelay );    // 開始網絡初始化,我們這里協調器開始建立網絡

  // set broadcast address mask to support broadcast filtering
  NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags );

3、ZDApp_NetworkInit()函數,設置了一個事件定時器,當事件達到,觸發ZDO_NETWORK_INIT事件

void ZDApp_NetworkInit( uint16 delay )
{
  if ( delay )
  {
    // Wait awhile before starting the device
    osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );
  }
  else
  {
    osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
  }
}

4、ZDApp_event_loop則檢測ZDO層的任務,當發現ZDO_NETWORK_INIT事件后,會執行如下:

  if ( events & ZDO_NETWORK_INIT )
  {
    // Initialize apps and start the network
    devState = DEV_INIT;
     
// 以前面確定的節點類型NODETYPE_COORDINATOR(協調器),啟動方式MODE_HARD啟動設備 ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode, DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );
// Return unprocessed events return (events ^ ZDO_NETWORK_INIT); }

5、ZDO_StartDevice()函數調用如下函數開始形成網絡:

  if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )
  {
    if ( startMode == MODE_HARD )
    {
      devState = DEV_COORD_STARTING;    // 把設備狀態更改為協調器啟動中,並且開始建立網絡
// 調用網絡形成函數開始建立網絡,需要的信息需要我們設置的主要包括PANID,信道 ret
= NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList, zgDefaultStartingScanDuration, beaconOrder, superframeOrder, false ); }

6、NLME_NetworkFormationRequest()函數是通過網絡層像空間發送建立網絡請求,其中通過抓包軟件發現,他會想空間發送一個BEACON信號,來獲取空間中的網絡情況,然后建立自己的網絡,如果自己的網絡和空間中的網絡的PANID相同,則會在此PANID上+1,
7、NLME_NetworkFormationRequest()函數發出request請求后會得到一個confirm,這個confirm函數為ZDO_NetworkFormationConfirmCB(),如果status的值為ZSUCCESS,則此網絡成功建立,網絡建立成功或者失敗,都需要告知ZDO層,ZDO層好根據情況作出相應的合適的處理。

/*********************************************************************
 * @fn          ZDO_NetworkFormationConfirmCB
 *
 * @brief       This function reports the results of the request to
 *              initialize a coordinator in a network.
 *
 * @param       Status - Result of NLME_NetworkFormationRequest()
 *
 * @return      none
 */
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )
{
  nwkStatus = (byte)Status;

  if ( Status == ZSUCCESS )
  {
    // LED on shows Coordinator started
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );

    // LED off forgets HOLD_AUTO_START
    HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);

#if defined ( ZBIT )
    SIM_SetColor(0xd0ffd0);
#endif

    if ( devState == DEV_HOLD )
    {
      // Began with HOLD_AUTO_START
      devState = DEV_COORD_STARTING;
    }
  }
#if defined(BLINK_LEDS)
  else
  {
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH );  // Flash LED to show failure
  }
#endif

  osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );   // 通知ZDO層,設置一個ZDO_NETWORK_START事件
}

8、ZDApp_event_loop處理上面觸發的ZDO_NETWORK_START事件

    if ( events & ZDO_NETWORK_START )
    {
      ZDApp_NetworkStartEvt();

      // Return unprocessed events
      return (events ^ ZDO_NETWORK_START);
    }

9、ZDO_NETWORK_START事件調用了ZDApp_NetworkStartEvt()函數,如果之前網絡已經建立成功則設置ZDO_STATE_CHANGE_EVT事件,否則增大發射功率再次設置ZDO_NETWORK_INIT事件,重新開始建立網絡,具體函數如下:

void ZDApp_NetworkStartEvt( void )
{
  if ( nwkStatus == ZSuccess )
  {
    // Successfully started a ZigBee network
    if ( devState == DEV_COORD_STARTING )
    {
      devState = DEV_ZB_COORD;
    }

    osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
    osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
  }
  else
  {
    // Try again with a higher energy threshold !!
    if ( ( NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT ) < 0xff )
    {
      NLME_SetEnergyThreshold( (uint8)(NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT) );
      osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
    }
    else
    {
      // Failed to start network. Enter a dormant state (until user intervenes)
      devState = DEV_INIT;
      osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
    }
  }
}

10、ZDO_STATE_CHANGE_EVT事件調用函數ZDO_UpdateNwkStatue()函數,此函數會把該網絡變化情況通知給所有的應用層端點,以便用戶根據此通知做相應處理,具體函數如下:

void ZDO_UpdateNwkStatus(devStates_t state)
{
  epList_t *pItem = epList;

  while (pItem != NULL)
  {
    if (pItem->epDesc->endPoint != ZDO_EP)
    {
      // 發送消息給所有的應用層任務和端點
      zdoSendStateChangeMsg(state, *(pItem->epDesc->task_id));
    }

    pItem = pItem->nextDesc;
  }
#if defined MT_ZDO_CB_FUNC
  zdoSendStateChangeMsg(state, MT_TaskID);
#endif

  ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
  (void)NLME_GetExtAddr();  // Load the saveExtAddr pointer.
}

11、至此協調器成功建立網絡並且告知應用層。路由器和終端加入網絡的過程在下一節繼續分析。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM