首页 > 代码库 > Z-Stack中SimpleApp开关结点加入网络流程

Z-Stack中SimpleApp开关结点加入网络流程

1)开关结点初始化

    这时选择的节点类型是终端节点,所以使用f8wEndev.cfg文件,所以在Zglobals.h文件中,我们可以得到下面的定义

#define ZG_DEVICETYPE_ENDDEVICE        0x02

#define DEVICE_LOGICAL_TYPE   ZG_DEVICETYPE_ENDDEVICE

uint8 zgDeviceLogicalType = DEVICE_LOGICAL_TYPE;

开关节点的 IAR 工程配置选项中定义了阻止自定义启动,即 HOLD_AUTO_START,因此在ZDApp.c 文件中定义了设备初始状态和启动模式:

devState = DEV_HOLD  //不会自动启动

devStartMode = MODE_JOIN  //加入

#if defined( HOLD_AUTO_START )

  devStates_t devState = DEV_HOLD;

#else

  devStates_t devState = DEV_INIT;

#endif

 

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

  // Set the default to coodinator

  devStartModes_t devStartMode = MODE_HARD;

#else

  devStartModes_t devStartMode = MODE_JOIN;     // Assume joining

  //devStartModes_t devStartMode = MODE_RESUME; // if already "directly joined"

                        // to parent. Set to make the device do an Orphan scan.

#endif

  在开关节点的NV 中,默认状态下没有设置启动模式,即

ZCD_NV_STARTUP_OPTION=0  

因此,初次使用开关节点时不会自定启动该节点。

另外,对应开关节点的 SimpleSwitch.c定义了应用层的状态:

myAppState = APP_INIT

2)加入网络

    当开关节点上电后,首先经历一系列的初始化工作,最终在 sapi 层设置进入事件,然后通过任务事件处理函数对该事件进行处理,当读取 NV 的启动模式选项时,在SAPI_ProcessEvent()函数中 if ( events & ZB_ENTRY_EVENT ) { }判断中;

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

判断为非自动启动,因此看到开关节点的LED_2 闪烁,

HalLedBlink(HAL_LED_2, 0, 50, 500);

操作系统等待其他事件发生。

  当按下按键S1 后,由于在 sapi 层注册了按键事件,因此会发送 KEY_CHANGE 消息至sapi层,当收到 KEY_CHANGE 消息后,sapi 层的任务事件处理函数调用: SAPI_ProcessEvent()函数中的if ( events & SYS_EVENT_MSG ){ }判断中。

zb_HandleKeys( ((keyChange_t *)pMsg)->state, ((keyChange_t *)pMsg)->keys );

然后将设备逻辑类型(终端设备)写入到NV,并将自动启动模式写入到 NV SimpleSwitch.c文件中。

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

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

最后重新启动: zb_HandleKeys()函数中

zb_SystemReset();

重新启动后,依然进入通过任务事件处理函数对进入事件进行处理,当读取 NV 的启动模

式选项时,判断为自动启动,然后调用: SAPI_ProcessEvent()函数

zb_StartRequest();

紧接着在zb_StartRequest(); 函数中调用 ZDO层的初始化设备函数: ZDApp.c文件中

  ZDOInitDevice(zgStartDelay);

在该函数中设置了 NV 网络状态,并修改了当前设备状态:

networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;

devState = DEV_INIT;

最终触发网络初始化函数:

ZDApp_NetworkInit( extendedDelay );

设置网络初始化事件:

osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );

ZDO 层的任务事件处理函数对网络初始化事件进行处理,即启动该设备:在ZDObject.c文件中

ZDO_StartDevice((uint8)ZDO_Config_Node_Descriptor.LogicalType,devStartMode, EFAULT_BEACON_ORDER,DEFAULT_SUPERFRAME_ORDER );

此时将改变设备状态为设备发现网络: 到这里前面建立网络的步骤相同,这里设备的状态不发生了改变。

devState = DEV_NWK_DISC;

并调用请求发现网络函数: 这个函数是不开源的

NLME_NetworkDiscoveryRequest(zgDefaultChannelList,zgDefaultStarting ScanDuration );

其中,通道号为协调器所在通道。

    当 NWK 层通过调用 MAC  PHY 层相关功能函数执行一些列发现网络动作后,NWK 层将接收到发现网络反馈,即: 始终没有发现调用该函数的地方在那里,可能在不开源的网络层中调用了。

ZDO_NetworkDiscoveryConfirmCB( uint8 ResultCount, networkDesc_t *NetworkList )

    其中,网络参数列表为该网络详细的网络参数。并将其中的个域网 ID、逻辑通道、版本号和扩展个域网 ID号组成网络发现确认消息发送至ZDO层:

ZDApp_SendMsg(ZDAppTaskID,ZDO_NWK_DISC_CNF,

sizeof(ZDO_NetworkDiscoveryCfm_t), (byte*)&msg )

ZDApp_SendMsg()函数中调用osal_set_event() 函数设置SYS_EVENT_MSG事件然后在事件处理函数ZDApp_event_loop()中调用下面的函数,

ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );

并在此时将改变设备状态为正在加入网络:

devState = DEV_NWK_JOINING;

ZDO 层接收到该消息后,任务事件处理函数将执行请求加入网络事件: ZDApp.c

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 );

NWK层通过调用MACPHY层相关功能函数执行一些列请求加入网络动作后, NWK层将接收到请求加入网络反馈,即: 这里也没有发现在那里调用的。

ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )

发送加入网络指示消息至 ZDO 层。

ZDApp_SendMsg(ZDAppTaskID,ZDO_NWK_JOIN_IND,sizeof(osal_event_hdr_t),(byte*)NULL );

ZDO 层接收到该消息后,任务事件处理函数将执行处理加入网络函数: ZDApp_ProcessOSALMsg函数中

case ZDO_NWK_JOIN_IND:

      ZDApp_ProcessNetworkJoin();

  break;

设置 ZDO状态改变事件:

osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );

如果 IAR 设置了节点选项,所以采用电池供电:

  #if defined ( POWER_SAVING )

      osal_pwrmgr_device( PWRMGR_BATTERY );

#endif

ZDO 层任务事件处理函数将执行 ZDO更新网络状态事件处理:

ZDO_UpdateNwkStatus( devState );

此时搜索端点列表,寻找曾经在 sapi 层注册过的端点号,并且将 ZDO 状态改变消息发送给这些端点:

而且确定开关节点(此时为终端设备)的 16 位网络地址和 64 IEEE 地址: ZDO_UpdateNwkStatus函数中。

ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();

  (void)NLME_GetExtAddr();  // Load the saveExtAddr pointer. 

 sapi 层接收到ZDO状态改变消息后,sapi层的任务事件处理函数将进行处理:

SAPI_StartConfirm( ZB_SUCCESS );

最终将改变设备的应用状态为启动状态:zb_StartConfirm()函数中改变其状态

  myAppState = APP_START;

至此,终端设备就加入了网络,状态也已改变成了启动状态。下面的过程就是绑定的过程了。