SimpleApp例子中网络的形成过程

来源:互联网 发布:java ssh框架面试题 编辑:程序博客网 时间:2024/05/01 18:09

SimpleApp例子中网络的形成过程

   每个设备都有一组被配置的参数,整个配置参数在代码中已经定义了默认值(在f8wConfig.cfg)中,在同个网络中,所有设备的“网络细节”配置参数(如PANID,Channel等)应该被设置成一样的值。每个设备的“设备细节”配置参数(Coordinator,RouterEndDevice等)可能配置为不同的值。

   但是,ZCD_NV_LOGICAL_TYPE必须被设置,确保①有正确的一个设备作为协调器被配置②所有电池供电的设备作为终端设备被配置。一旦这些工作都完成,这个设备就可以以任意方式启动,协调器设备将建立网络,其他设备将发现和加入这个网络。

   协调器将扫描所有被ZCD_NV_CHANLIST参数制定的通道和选择1个最小能量的通道,如果有2个以上的最小能量通道,则协调器选择在ZigBee网络中存在的序号最小的通道,协调器将选择用ZCD_NV_PANID参数指定的网络ID,路由器和终端设备将扫描用ZCD_NV_CHANLIST配置参数指定的通道和试图发现ID为ZCD_NV_PANID参数指定的网络。

(1) 协调器格式化网络

   协调器将扫描DEFAULT_CHANLIST指定的通道,最后在其中之一上形成网络,在f8wConfig.cfg文件中,可以看到其定义如下:

-DDEFAULT_CHANLIST=0x00000800  // 11 -0x0B

还可以查看到PANID的定义:

-DZDAPP_CONFIG_PAN_ID=0xFFFF

    如果ZDAPP_CONFIG_PAN_ID被定义为0xFFFF,那么协调器将根据自身的IEEE地址建立一个随机的PANID,如果ZDAPP_CONFIG_PAN_ID没有被定义为0xFFFF,那么协调器建立网络的PANID将由ZDAPP_CONFIG_PAN_ID指定。

可以在下面的函数发现PID的判断

ZStatus_t ZDO_NetworkDiscoveryConfirmCB( byteResultCount,

                                        networkDesc_t *NetworkList )

{

...................

for ( i = 0; i < ResultCount; i++,pNwkDesc = pNwkDesc->nextDesc )

   {

     if ( zgConfigPANID != 0xFFFF )

     {

       // PAN Id is preconfigured. check if it matches

       // only 14 bits of pan id is used

       if ( pNwkDesc->panId != ( zgConfigPANID& 0x3FFF ) )

         continue;

     }

.......................

}

当所有的参数配置好后,可以调用下面的函数来格式化网络。

ZStatus_t NLME_NetworkFormationRequest( uint16 PanId,uint32 ScanChannels,

                                     byte ScanDuration, byte BeaconOrder,

                                     byte SuperframeOrder,

byte BatteryLifeExtension );

(2) 路由器和终端设备加入网络

   路由器和终端设备启动后,将扫描DEFAULT_CHANLIST指定的频道,如果ZDAPP_CONFIG_PAN_ID没有被定义为0xFFFF,则路由器将强制加入ZDAPP_CONFIG_PAN_ID定义的网络。

发现一个网络可以调用下面的函数

ZStatus_t NLME_NetworkDiscoveryRequest( uint32ScanChannels, byte scanDuration);

    该函数要求网络层去发现邻居路由器节点,并且应该在进行网络扫描之前调用,扫描的结果由ZDO_NetworkDiscoveryConfirmCB()函数返回。其中:

ScanChannels-----准备扫描的信道号(信道号的范围为11~26,也就是2.4GHz频段有效)

scanDuration--------规定了在新的网开始建立之前,其他网络可能扫描每个信道的时间其长度。

发现网络存在后,就调用下面的函数加入网络

ZStatus_t NLME_OrphanJoinRequest( uint32 ScanChannels,byte ScanDuration );

该函数要求网络层以孤节点的形式加入网络,函数调用的结果由ZDO_JoinIndicationCB返回。其中:

ScanChannels------准备扫描的信道号

scanDuration--------规定了在新的网开始建立之前,其他网络可能扫描每个信道的时间其长度。

(3) 实际上,ZigBee设备启动时不直接调用上面的三个函数,而是通过调用ZDO_StartDevice()函数来启动设备。当sapi_Init()函数的最后,调用osal_set_event(task_id,ZB_ENTRY_EVENT);函数,触发ZB_ENTRY_EVENT事件后,ZCD_NV_STARTUP_OPTION被设置为ZCD_STARTOPT_AUTO_START后,在zb_HandleKeys()函数中,也就是按下SW1键后。会在SAPI_ProcessEvent(byte task_id, UINT16 events )函数中执行下面的语句。

if ( events & ZB_ENTRY_EVENT)

  {

   uint8 startOptions;

   // Give indication to application of device startup

   zb_HandleOsalEvent( ZB_ENTRY_EVENT );

   // LED off cancels HOLD_AUTO_START blink set in thestack

   HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);

   zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8),&startOptions );

   if ( startOptions & ZCD_STARTOPT_AUTO_START)

   {

     zb_StartRequest();

   }

   else

   {

     // blink leds and wait for external input to config andrestart

     HalLedBlink(HAL_LED_2, 0, 50, 500);

   }

   return (events ^ ZB_ENTRY_EVENT );

  }

下面是zb_StartRequest();函数的源代码

void zb_StartRequest()

{

  uint8 logicalType;

  // Start the device

  // start delay = min(NWK_START_DELAY,zgStartDelay) + rand() - only for fresh start, notrestore

  if ( zgStartDelay <NWK_START_DELAY )

   zgStartDelay = 0;

  else

   zgStartDelay -= NWK_START_DELAY;

  // check that bad combinations ofcompile flag definitions and device type

  //读取设备的逻辑设备

  zb_ReadConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);

   if(  ( logicalType >ZG_DEVICETYPE_ENDDEVICE ) ||...... )//判断设备配置是否正确

   {

    SAPI_SendCback( SAPICB_START_CNF, ZInvalidParameter, 0);//配置错误

   }

   else

   {

    ZDOInitDevice(zgStartDelay);

   }

  return;

}

   设备打开电源之后,由于还没有形成网络,所以经过设备逻辑类型的判断后,程序会跳转到ZDOInitDevice(zgStartDelay);下面是ZDOInitDevice(zgStartDelay);的程序定义。

uint8 ZDOInitDevice( uint16 startDelay )

{

...................................

#if defined ( NV_RESTORE )

  // Get Keypad directly to see if a reset nvis needed.

  // Hold down the SW_BYPASS_NV key (defined inOnBoard.h)

  // while booting to skip past NV Restore.

  if ( HalKeyRead() == SW_BYPASS_NV )

   networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;

  else

  {

    //Determine if NV should be restored 决定NV是否应该被重新载入

   networkStateNV = ZDApp_ReadNetworkRestoreState();

  }

  if ( networkStateNV ==ZDO_INITDEV_RESTORED_NETWORK_STATE )

  {

   networkStateNV = ZDApp_RestoreNetworkState();

  }

  else

  {

    // Wipeout the network state in NV

   NLME_InitNV();//清除NV中的网络状态

   NLME_SetDefaultNV();

  }

#endif

  if ( networkStateNV ==ZDO_INITDEV_NEW_NETWORK_STATE )

  {

   ZDAppDetermineDeviceType();

   //加入网络的时延

   extendedDelay = (uint16)((NWK_START_DELAY + startDelay)

             + (osal_rand() &EXTENDED_JOINING_RANDOM_MASK));

  }

  // Initialize device security初始化设备的安全属性

  ZDApp_SecInit( networkStateNV );

  // Trigger the network start开始网络的形成

  ZDApp_NetworkInit( extendedDelay );

  return ( networkStateNV );

}

   其中,ZDApp_NetworkInit(extendedDelay );函数会触发ZDO_NETWORK_INIT事件,其源代码如下:

void ZDApp_NetworkInit( uint16 delay )

{

  if ( delay )

  {

    // Waitawhile before starting the device一一段时间后启动设备。

   osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );

  }

  else

  {

   osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );

  }

}

   而ZDO_NETWORK_INIT事件的处理函数位于Z-Stack应用层的任务事件处理函数ZDApp_event_loop()中,其代码如下:

UINT16 ZDApp_event_loop( byte task_id, UINT16 events )

{

.......................................

  if ( events &ZDO_NETWORK_INIT )

  {

// Initialize apps and start the network 初始化网络应用程序并启动网络

    devState= DEV_INIT;

   ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType,devStartMode,

                    DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );

  // Return unprocessed events 返回没有处理的事件

    return(events ^ ZDO_NETWORK_INIT);

  }

.........................................

  return 0;

}

   其实在ZDO_StartDevice()函数中,分别调用了NLME_NetworkFormationRequest(),NLME_NetworkDiscoveryRequest和NLME_OrphanJoinRequest函数。所以它会自动启动设备,并根据类型的不同做相应的工作,用户可以完全不用关心这些工作,而全部交给Z-Stack来完成。

void ZDO_StartDevice( byte logicalType, //设备逻辑类型

                                 devStartModes_t startMode,//启动模式

                                 byte beaconOrder, //信标的时间

byte superframeOrder )//超帧长度

{

  ZStatus_t ret;

  ret = ZUnsupportedMode;

#if defined(ZDO_COORDINATOR)

  if ( logicalType == NODETYPE_COORDINATOR)

  {

    if (startMode == MODE_HARD )

    {

     devState = DEV_COORD_STARTING;

     ret = NLME_NetworkFormationRequest( zgConfigPANID,zgDefaultChannelList,

                                         zgDefaultStartingScanDuration, beaconOrder,

                                         superframeOrder, false );

    }

...................................

#if !defined ( ZDO_COORDINATOR ) || defined( SOFT_START )

  if ( logicalType == NODETYPE_ROUTER ||logicalType == NODETYPE_DEVICE )

  {

    if ((startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )

    {

     devState = DEV_NWK_DISC;//设置设备的属性

  #if defined( MANAGED_SCAN )

     ZDOManagedScan_Next();

     ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask,BEACON_ORDER_15_MSEC );

  #else

     ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList,zgDefaultStartingScanDuration );

  #endif

    }

    else if (startMode == MODE_RESUME )

    {

     if ( logicalType == NODETYPE_ROUTER )

     {

       ZMacScanCnf_t scanCnf;

       devState = DEV_NWK_ORPHAN;

       

       scanCnf.hdr.Status = ZSUCCESS;

       scanCnf.ScanType = ZMAC_ORPHAN_SCAN;

       scanCnf.UnscannedChannels = 0;

       scanCnf.ResultListSize = 0;

       nwk_ScanJoiningOrphan(&scanCnf);

       ret = ZSuccess;

     }

     else

     {

       devState = DEV_NWK_ORPHAN;

       ret = NLME_OrphanJoinRequest( zgDefaultChannelList,

                                     zgDefaultStartingScanDuration );

     }

    }

    else

    {

#if defined( LCD_SUPPORTED )

     HalLcdWriteScreen( "StartDeviceERR", "MODEunknown" );

#endif

    }

  }

#endif  //!ZDO COORDINATOR || SOFT_START

  if ( ret != ZSuccess )

   osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY);

}

0 0
原创粉丝点击