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、至此协调器成功建立网络并且告知应用层。路由器和终端加入网络的过程在下一节继续分析。

posted @ 2016-08-15 18:37  小健V5  阅读(4339)  评论(0编辑  收藏  举报