2024年1月14日发(作者:)

1.

void ZDApp_Init( byte task_id )

{

uint8 capabilities;

// Save the task ID

ZDAppTaskID = task_id;

//设置任务id

// Initialize the ZDO global device short address storage

de = Addr16Bit;

ddr = INVALID_NODE_ADDR;

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

//函数的作用是返回指向64bitIEEE地址的指针,但这里有点奇怪,它好像没有接收这个指针

// Check for manual "Hold Auto Start"

ZDAppCheckForHoldKey();

//该函数的作用是如果HAL_KEY_SW_1键被按下,则not started automatically,如果不是自启动,则在自己的应用程序中要添加函数ZDOInitDevice( 0 )来启动建网过程,见Sample例子的应用程序

// Initialize ZDO items and setup the device - type of device to create.

ZDO_Init();

// Register the endpoint description with the AF

// This task doesn't have a Simple description, but we still need

// to register the endpoint.

afRegister( (endPointDesc_t *)&ZDApp_epDesc );

//注册端点

#if defined( ZDO_USERDESC_RESPONSE )

ZDApp_InitUserDesc();

#endif // ZDO_USERDESC_RESPONSE

// set broadcast address mask to support broadcast filtering

NLME_GetRequest(nwkCapabilityInfo, 0, &capabilities);

//This function allows the next higher layer to get the value of a NIB (network information base)

attribute

NLME_SetBroadcastFilter( capabilities );

//This function sets a bit mask based on the capabilities of the device. It will be used to process

valid broadcast addresses

// Start the device?

if ( devState != DEV_HOLD )

{

ZDOInitDevice( 0 );

}

else

{

// Blink LED to indicate HOLD_START

HalLedBlink ( HAL_LED_4, 0, 50, 500 );

}

ZDApp_RegisterCBs();

} /* ZDO_Init() */

2.

void ZDApp_RegisterCBs( void )

{

#if defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )

ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );

#endif

#if defined ( ZDO_NWKADDR_REQUEST ) || defined ( REFLECTOR )

ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );

#endif

#if defined ( ZDO_COORDINATOR )

ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp );

ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp );

ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );

#endif

#if defined ( REFLECTOR )

ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req );

ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );

#endif

}

3.

ZStatus_t ZDO_RegisterForZDOMsg( uint8 taskID, uint16 clusterID )

{

ZDO_MsgCB_t *pList;

ZDO_MsgCB_t *pLast;

ZDO_MsgCB_t *pNew;

// Look for duplicate

pList = zdoMsgCBs;

while ( pList )

{

if ( pList->taskID == taskID && pList->clusterID == clusterID )

return ( ZSuccess );

pLast = pList;

pList = (ZDO_MsgCB_t *)pList->next;

}

// Add to the list

pNew = (ZDO_MsgCB_t *)osal_mem_alloc( sizeof ( ZDO_MsgCB_t ) );

if ( pNew )

{

pNew->taskID = taskID;

pNew->clusterID = clusterID;

pNew->next = NULL;

if ( zdoMsgCBs )

{

pLast->next = pNew;

}

else

zdoMsgCBs = pNew;

return ( ZSuccess );

}

else

return ( ZMemError );

}

该函数的作用是把新的ZDOMsg加入到这张表中。

4.

uint8 ZDOInitDevice( uint16 startDelay )

{

uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;

uint16 extendedDelay = 0;

devState = DEV_INIT; // Remove the Hold state

// Initialize leave control logic

ZDApp_LeaveCtrlInit();

// Check leave control reset settings

ZDApp_LeaveCtrlStartup( &devState, &startDelay );

// Leave may make the hold state come back

if ( devState == DEV_HOLD )

return ( ZDO_INITDEV_LEAVE_NOT_STARTED ); // Don't join - (one time).

#if defined ( NV_RESTORE )

// Get Keypad directly to see if a reset nv is needed.

// Hold down the SW_BYPASS_NV key (defined in OnBoard.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

networkStateNV = ZDApp_ReadNetworkRestoreState();

}

if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )

{

networkStateNV = ZDApp_RestoreNetworkState();

}

else

{

// Wipe out the network state in NV

NLME_InitNV();

NLME_SetDefaultNV();

}

#endif

if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE )

{

ZDAppDetermineDeviceType();

// Only delay if joining network - not restoring network state

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

}

5.

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

}

}

6.

UINT16 ZDApp_event_loop( byte task_id, UINT16 events )

{

uint8 *msg_ptr;

if ( events & SYS_EVENT_MSG )

{

while ( (msg_ptr = osal_msg_receive( ZDAppTaskID )) )

{

ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );

// Release the memory

osal_msg_deallocate( msg_ptr );

}

// Return unprocessed events

return (events ^ SYS_EVENT_MSG);

}

if ( events & ZDO_STATE_CHANGE_EVT )

{

ZDO_UpdateNwkStatus( devState );

// Return unprocessed events

return (events ^ ZDO_STATE_CHANGE_EVT);

}

if ( events & ZDO_NETWORK_INIT )

{

// Initialize apps and start the network

devState = DEV_INIT;

ZDO_StartDevice( (uint8)ZDO_Config_Node_lType, devStartMode,

DEFAULT_BEACON_ORDER,

DEFAULT_SUPERFRAME_ORDER );

// Return unprocessed events

return (events ^ ZDO_NETWORK_INIT);

}

#if defined (RTR_NWK)

if ( events & ZDO_NETWORK_START )

{

ZDApp_NetworkStartEvt();

// Return unprocessed events

return (events ^ ZDO_NETWORK_START);

}

#endif //RTR_NWK

#if defined ( RTR_NWK )

if ( events & ZDO_ROUTER_START )

{

if ( nwkStatus == ZSuccess )

{

if ( devState == DEV_END_DEVICE )

devState = DEV_ROUTER;

osal_pwrmgr_device( PWRMGR_ALWAYS_ON );

}

else

{

// remain as end device!!

}

osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );

// Return unprocessed events

return (events ^ ZDO_ROUTER_START);

}

#endif // RTR

if ( events & ZDO_COMMAND_CNF )

{

// User defined logic

// Return unprocessed events

return (events ^ ZDO_COMMAND_CNF);

}

#if defined( ZDSECMGR_SECURE ) && defined( RTR_NWK )

if ( events & ZDO_NEW_DEVICE )

{

// process the new device event

if ( ZDSecMgrNewDeviceEvent() == TRUE )

{

osal_start_timerEx( ZDAppTaskID, ZDO_NEW_DEVICE, 1000 );

}

// Return unprocessed events

return (events ^ ZDO_NEW_DEVICE);

}

#endif // ZDSECMGR_SECURE && RTR

#if defined ( ZDSECMGR_COMMERCIAL )

if ( events & ZDO_SECMGR_EVENT )

{

ZDSecMgrEvent();

// Return unprocessed events

return (events ^ ZDO_SECMGR_EVENT);

}

#endif // defined( ZDSECMGR_COMMERCIAL )

#if ( SECURE != 0 )

if ( events & ZDO_DEVICE_AUTH )

{

ZDApp_DeviceAuthEvt();

// Return unprocessed events

return (events ^ ZDO_DEVICE_AUTH);

}

#endif // SECURE

if ( events & ZDO_NWK_UPDATE_NV )

{

ZDApp_SaveNetworkStateEvt();

// Return unprocessed events

return (events ^ ZDO_NWK_UPDATE_NV);

}

#if ( SECURE != 0 )

if ( events & ZDO_FRAMECOUNTER_CHANGE )

{

if ( nwkFrameCounterChanges++ > MAX_NWK_FRAMECOUNTER_CHANGES )

ZDApp_SaveNwkKey();

// Return unprocessed events

return (events ^ ZDO_FRAMECOUNTER_CHANGE);

}

#endif

if ( events & ZDO_DEVICE_RESET )

{

// The device has been in the UNAUTH state, so reset

// Note: there will be no return from this call

SystemReset();

}

// Discard or make more handlers

return 0;

}

7.

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

}

else if ( startMode == MODE_RESUME )

{

// Just start the coordinator

devState = DEV_COORD_STARTING;

ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );

}

else

{

#if defined( LCD_SUPPORTED )

HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );

#endif

}

}

#endif // !ZDO_COORDINATOR

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

/* if router and nvram is available, fake successful orphan scan */

= ZSUCCESS;

pe = ZMAC_ORPHAN_SCAN;

nedChannels = 0;

ListSize = 0;

nwk_ScanJoiningOrphan(&scanCnf);

ret = ZSuccess;

}

else

{

devState = DEV_NWK_ORPHAN;

ret = NLME_OrphanJoinRequest( zgDefaultChannelList,

zgDefaultStartingScanDuration );

}

}

else

{

#if defined( LCD_SUPPORTED )

HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );

#endif

}

}

#endif //!ZDO COORDINATOR || SOFT_START

if ( ret != ZSuccess )

osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );

}

建立网络的过程大致是这样的:①在ZDApp_Init中调用ZDOInitDevice( 0 )这个函数;②在ZDOInitDevice中调用ZDApp_NetworkInit( extendedDelay )这个函数;③在ZDApp_NetworkInit( extendedDelay )中调用

osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay )这个函数来开启一个定时器;④定时时间到后在ZDApp_event_loop中的调用ZDO_StartDevice这个函数;⑤在ZDO_StartDevice这个函数中调用NLME_NetworkFormationRequest这个函数来建立网络;

如果不是自启动(是hold auto start),则在自己的应用程序中要添加函数ZDOInitDevice( 0 )来启动建网过程,见Sample例子的应用程序

协调器形成网络

osalInitTasks();

---->ZDApp_Init();

---->ZDOInitDevice();

---->ZDApp_NetworkInit();

---->osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );

---->events & ZDO_NETWORK_INIT;

---->ZDO_StartDevice();

如果是协调器启动

---->NLME_NetworkFormationRequest();

如果是路由器或者终端设备第一次启动

---->NLME_NetworkDiscoveryRequest();

如果是路由器重新加入:

---->nwk_ScanJoiningOrphan();

如果是终端设备重新加入:

---->NLME_OrphanJoinRequest();

如果启动失败:

osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT,

NWK_RETRY_DELAY );

*

*

*

*

---->ZDO_NetworkFormationConfirmCB();

---->osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );

---->events & ZDO_NETWORK_START

---->ZDApp_NetworkStartEvt();

---->osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );

---->events & ZDO_STATE_CHANGE_EVT

---->ZDO_UpdateNwkStatus( devState );

---->osal_msg_send( *(epDesc->epDesc->task_id), (byte *)msgPtr );

//上面事件的作用是:向每个应用层任务注册一个ZDO_STATE_CHANGE事件

协调器(自启动模式)—以SampleApp的协调器为例,并假设初始化成功,网络建立成功.

程序大致流程:

main()->osal_init_system()->osalInitTasks()->ZDApp_Init()->ZDOInitDevice()->ZDApp_NetworkInit->触发ZDAppTaskID的ZDO_NETWORK_INIT->ZDO_StartDevice()->NLME_NetworkFormationRequest()->网络建立成功ZDO_NetworkFormationConfirmCB->触发ZDAppTaskID的ZDO_NETWORK_START->ZDApp_NetworkStartEvt()->触发ZDAppTaskID的ZDO_STATE_CHANGE_EVT->ZDO_UpdateNwkStatus()->触发SampleApp_TaskID的ZDO_STATE_CHANGE->开户周期信息发送的定时器.