1064 lines
36 KiB
C
1064 lines
36 KiB
C
|
/**************************************************************************************************
|
|||
|
Filename: ZDNwkMgr.c
|
|||
|
Revised: $Date: 2007-10-17 15:38:45 -0700 (Wed, 17 Oct 2007) $
|
|||
|
Revision: $Revision: 15716 $
|
|||
|
|
|||
|
Description: The ZigBee Network Manager.
|
|||
|
|
|||
|
|
|||
|
Copyright 2007 Texas Instruments Incorporated. All rights reserved.
|
|||
|
|
|||
|
IMPORTANT: Your use of this Software is limited to those specific rights
|
|||
|
granted under the terms of a software license agreement between the user
|
|||
|
who downloaded the software, his/her employer (which must be your employer)
|
|||
|
and Texas Instruments Incorporated (the "License"). You may not use this
|
|||
|
Software unless you agree to abide by the terms of the License. The License
|
|||
|
limits your use, and you acknowledge, that the Software may not be modified,
|
|||
|
copied or distributed unless embedded on a Texas Instruments microcontroller
|
|||
|
or used solely and exclusively in conjunction with a Texas Instruments radio
|
|||
|
frequency transceiver, which is integrated into your product. Other than for
|
|||
|
the foregoing purpose, you may not use, reproduce, copy, prepare derivative
|
|||
|
works of, modify, distribute, perform, display or sell this Software and/or
|
|||
|
its documentation for any purpose.
|
|||
|
|
|||
|
YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
|
|||
|
PROVIDED <EFBFBD>AS IS<EFBFBD> WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|||
|
INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
|
|||
|
NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
|
|||
|
TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
|
|||
|
NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
|
|||
|
LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
|
|||
|
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
|
|||
|
OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
|
|||
|
OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
|
|||
|
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
|
|||
|
|
|||
|
Should you have any questions regarding your right to use this Software,
|
|||
|
contact Texas Instruments Incorporated at www.TI.com.
|
|||
|
**************************************************************************************************/
|
|||
|
|
|||
|
#ifdef __cplusplus
|
|||
|
extern "C"
|
|||
|
{
|
|||
|
#endif
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* INCLUDES
|
|||
|
*/
|
|||
|
#include "ZComdef.h"
|
|||
|
#include "nwk_util.h"
|
|||
|
#include "ZDApp.h"
|
|||
|
#include "ZDObject.h"
|
|||
|
#include "ZGlobals.h"
|
|||
|
#include "ZDNwkMgr.h"
|
|||
|
|
|||
|
#if defined( MT_ZDO_FUNC )
|
|||
|
#include "MT_ZDO.h"
|
|||
|
#endif
|
|||
|
|
|||
|
#if defined ( LCD_SUPPORTED )
|
|||
|
#include "OnBoard.h"
|
|||
|
#endif
|
|||
|
|
|||
|
/* HAL */
|
|||
|
#include "hal_lcd.h"
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* CONSTANTS
|
|||
|
*/
|
|||
|
|
|||
|
#define ONE_MINUTE 60000 // 1(m) * 60(s) * 1000(ms)
|
|||
|
|
|||
|
#if defined ( LCD_SUPPORTED )
|
|||
|
const char NwkMgrStr_1[] = "NM-fail not hi";
|
|||
|
const char NwkMgrStr_2[] = "NM-cur<last fail";
|
|||
|
const char NwkMgrStr_3[] = "NM-energy too hi";
|
|||
|
const char NwkMgrStr_4[] = "NM-energy not up";
|
|||
|
#endif
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* TYPEDEFS
|
|||
|
*/
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* GLOBAL VARIABLES
|
|||
|
*/
|
|||
|
|
|||
|
// Task ID for internal task/event processing. This variable will be
|
|||
|
// received when ZDNwkMgr_Init() is called.
|
|||
|
uint8 ZDNwkMgr_TaskID = 0;
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* LOCAL VARIABLES
|
|||
|
*/
|
|||
|
|
|||
|
// Frequency Agility variables
|
|||
|
uint8 ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq = 0;
|
|||
|
zAddrType_t ZDNwkMgr_MgmtNwkUpdateNotifyAddr;
|
|||
|
uint16 ZDNwkMgr_UpdateNotifyTimer = 0;
|
|||
|
uint8 ZDNwkMgr_NumUpdateNotifySent = 0;
|
|||
|
uint8 ZDNwkMgr_WaitingForNotifyConfirm = FALSE;
|
|||
|
uint16 ZDNwkMgr_TotalTransmissions;
|
|||
|
uint16 ZDNwkMgr_TxFailures;
|
|||
|
|
|||
|
ZDO_MgmtNwkUpdateReq_t ZDNwkMgr_MgmtNwkUpdateReq;
|
|||
|
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
uint16 ZDNwkMgr_UpdateRequestTimer = 0;
|
|||
|
uint8 ZDNwkMgr_LastChannelEnergy = 0;
|
|||
|
uint16 ZDNwkMgr_LastChannelFailureRate = 0;
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
uint8 ZDNwkMgr_NewChannel;
|
|||
|
|
|||
|
// PAN ID Conflict variables
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
uint8 ZDNwkMgr_PanIdUpdateInProgress = FALSE;
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* GLOBAL FUNCTIONS
|
|||
|
*/
|
|||
|
// Freguency Agility functions
|
|||
|
void (*pZDNwkMgr_ReportChannelInterference)( NLME_ChanInterference_t *chanInterference ) = NULL;
|
|||
|
void (*pZDNwkMgr_ProcessDataConfirm)( afDataConfirm_t *afDataConfirm ) = NULL;
|
|||
|
void (*pZDNwkMgr_EDScanConfirmCB)( NLME_EDScanConfirm_t *EDScanConfirm ) = NULL;
|
|||
|
|
|||
|
// PAN ID Conflict functions
|
|||
|
void (*pZDNwkMgr_NetworkReportCB)( ZDNwkMgr_NetworkReport_t *pReport ) = NULL;
|
|||
|
void (*pZDNwkMgr_NetworkUpdateCB)( ZDNwkMgr_NetworkUpdate_t *pUpdate ) = NULL;
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* LOCAL FUNCTIONS
|
|||
|
*/
|
|||
|
|
|||
|
void ZDNwkMgr_ProcessServerDiscRsp( zdoIncomingMsg_t *inMsg );
|
|||
|
void ZDNwkMgr_SetNwkManagerAddr( uint16 nwkManagerAddr );
|
|||
|
|
|||
|
// Frequency Agility functions
|
|||
|
static void ZDNwkMgr_ProcessMsgCBs( zdoIncomingMsg_t *inMsg );
|
|||
|
|
|||
|
static void ZDNwkMgr_ProcessMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg );
|
|||
|
static void ZDNwkMgr_ProcessChannelInterference( ZDNwkMgr_ChanInterference_t *pChanInterference );
|
|||
|
static void ZDNwkMgr_ProcessEDScanConfirm( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm );
|
|||
|
static void ZDNwkMgr_CheckForChannelInterference( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm );
|
|||
|
static void ZDNwkMgr_BuildAndSendUpdateNotify( uint8 TransSeq, zAddrType_t *dstAddr,
|
|||
|
uint16 totalTransmissions, uint16 txFailures,
|
|||
|
ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm, uint8 txOptions );
|
|||
|
void ZDNwkMgr_EDScanConfirmCB( NLME_EDScanConfirm_t *EDScanConfirm );
|
|||
|
void ZDNwkMgr_ProcessDataConfirm( afDataConfirm_t *afDataConfirm );
|
|||
|
void ZDNwkMgr_ReportChannelInterference( NLME_ChanInterference_t *chanInterference );
|
|||
|
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
static void ZDNwkMgr_ProcessMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg );
|
|||
|
static void ZDNwkMgr_CheckForChannelChange( ZDO_MgmtNwkUpdateNotify_t *pNotify );
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
// PAN ID Conflict functions
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
void ZDNwkMgr_NetworkReportCB( ZDNwkMgr_NetworkReport_t *pReport );
|
|||
|
void ZDNwkMgr_NetworkUpdateCB( ZDNwkMgr_NetworkUpdate_t *pUpdate );
|
|||
|
|
|||
|
void ZDNwkMgr_ProcessNetworkReport( ZDNwkMgr_NetworkReport_t *pNetworkReport );
|
|||
|
void ZDNwkMgr_ProcessNetworkUpdate( ZDNwkMgr_NetworkUpdate_t *pNetworkUpdate );
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_Init
|
|||
|
*
|
|||
|
* @brief Initialization function for the Network Manager Task.
|
|||
|
* This is called during initialization and should contain
|
|||
|
* any application specific initialization (ie. hardware
|
|||
|
* initialization/setup, table initialization, power up
|
|||
|
* notificaiton ... ).
|
|||
|
*
|
|||
|
* @param task_id - the ID assigned by OSAL. This ID should be
|
|||
|
* used to send messages and set timers.
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_Init( byte task_id )
|
|||
|
{
|
|||
|
// Save the task ID
|
|||
|
ZDNwkMgr_TaskID = task_id;
|
|||
|
|
|||
|
ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Server_Discovery_rsp );
|
|||
|
|
|||
|
// Frequecy Agility initialization
|
|||
|
ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Mgmt_NWK_Update_req );
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Mgmt_NWK_Update_notify );
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
pZDNwkMgr_EDScanConfirmCB = ZDNwkMgr_EDScanConfirmCB;
|
|||
|
pZDNwkMgr_ProcessDataConfirm = ZDNwkMgr_ProcessDataConfirm;
|
|||
|
pZDNwkMgr_ReportChannelInterference = ZDNwkMgr_ReportChannelInterference;
|
|||
|
|
|||
|
// PAN ID Conflict initialization
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
pZDNwkMgr_NetworkReportCB = ZDNwkMgr_NetworkReportCB;
|
|||
|
pZDNwkMgr_NetworkUpdateCB = ZDNwkMgr_NetworkUpdateCB;
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addrMode = Addr16Bit;
|
|||
|
ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = INVALID_NODE_ADDR;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_event_loop
|
|||
|
*
|
|||
|
* @brief Main event loop for the Network Manager task. This function
|
|||
|
* is called to process all events for the task. Events
|
|||
|
* include timers, messages and any other user defined events.
|
|||
|
*
|
|||
|
* @param task_id - The OSAL assigned task ID.
|
|||
|
* @param events - events to process. This is a bit map and can
|
|||
|
* contain more than one event.
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
UINT16 ZDNwkMgr_event_loop( byte task_id, UINT16 events )
|
|||
|
{
|
|||
|
osal_event_hdr_t *msgPtr;
|
|||
|
(void)task_id; // Intentionally unreferenced parameter
|
|||
|
|
|||
|
if ( events & SYS_EVENT_MSG )
|
|||
|
{
|
|||
|
msgPtr = (osal_event_hdr_t *)osal_msg_receive( ZDNwkMgr_TaskID );
|
|||
|
while ( msgPtr )
|
|||
|
{
|
|||
|
switch ( msgPtr->event )
|
|||
|
{
|
|||
|
case ZDO_CB_MSG:
|
|||
|
// ZDO sends the message that we registered for
|
|||
|
ZDNwkMgr_ProcessMsgCBs( (zdoIncomingMsg_t *)msgPtr );
|
|||
|
break;
|
|||
|
|
|||
|
case NM_CHANNEL_INTERFERE:
|
|||
|
// NWK layer sends the message when it detectes Channel Interference
|
|||
|
ZDNwkMgr_ProcessChannelInterference( (ZDNwkMgr_ChanInterference_t *)msgPtr );
|
|||
|
break;
|
|||
|
|
|||
|
case NM_ED_SCAN_CONFIRM:
|
|||
|
// NWK layer sends the message when it receives an ED scan confirmation
|
|||
|
ZDNwkMgr_ProcessEDScanConfirm( (ZDNwkMgr_EDScanConfirm_t *)msgPtr );
|
|||
|
break;
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
case ZDO_NETWORK_REPORT:
|
|||
|
// NWK layer sends this message when it receives a Network Report message
|
|||
|
ZDNwkMgr_ProcessNetworkReport( (ZDNwkMgr_NetworkReport_t *)msgPtr );
|
|||
|
break;
|
|||
|
|
|||
|
case ZDO_NETWORK_UPDATE:
|
|||
|
// NKW layer sends this message when it receives a Network Update message
|
|||
|
ZDNwkMgr_ProcessNetworkUpdate( (ZDNwkMgr_NetworkUpdate_t *)msgPtr );
|
|||
|
break;
|
|||
|
#endif // NWK_MANAGER
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// Release the memory
|
|||
|
osal_msg_deallocate( (uint8 *)msgPtr );
|
|||
|
|
|||
|
// Next
|
|||
|
msgPtr = (osal_event_hdr_t *)osal_msg_receive( ZDNwkMgr_TaskID );
|
|||
|
}
|
|||
|
|
|||
|
// Return unprocessed events
|
|||
|
return (events ^ SYS_EVENT_MSG);
|
|||
|
}
|
|||
|
|
|||
|
if ( events & ZDNWKMGR_CHANNEL_CHANGE_EVT )
|
|||
|
{
|
|||
|
// Switch channel
|
|||
|
_NIB.nwkLogicalChannel = ZDNwkMgr_NewChannel;
|
|||
|
ZMacSetReq( ZMacChannel, &ZDNwkMgr_NewChannel );
|
|||
|
|
|||
|
// Our Channel has been changed -- notify to save info into NV
|
|||
|
ZDApp_NwkStateUpdateCB();
|
|||
|
|
|||
|
// Reset the total transmit count and the transmit failure counters
|
|||
|
_NIB.nwkTotalTransmissions = 0;
|
|||
|
nwkTransmissionFailures( TRUE );
|
|||
|
|
|||
|
return ( events ^ ZDNWKMGR_CHANNEL_CHANGE_EVT );
|
|||
|
}
|
|||
|
|
|||
|
if ( events & ZDNWKMGR_UPDATE_NOTIFY_EVT )
|
|||
|
{
|
|||
|
// Update the Update Notify timer
|
|||
|
if ( ZDNwkMgr_UpdateNotifyTimer > 0 )
|
|||
|
{
|
|||
|
ZDNwkMgr_UpdateNotifyTimer--;
|
|||
|
osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_NOTIFY_EVT, ONE_MINUTE );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ZDNwkMgr_NumUpdateNotifySent = 0;
|
|||
|
}
|
|||
|
|
|||
|
return ( events ^ ZDNWKMGR_UPDATE_NOTIFY_EVT );
|
|||
|
}
|
|||
|
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
if ( events & ZDNWKMGR_UPDATE_REQUEST_EVT )
|
|||
|
{
|
|||
|
// Update the Update Request timer
|
|||
|
if ( ZDNwkMgr_UpdateRequestTimer > 0 )
|
|||
|
{
|
|||
|
ZDNwkMgr_UpdateRequestTimer--;
|
|||
|
osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_REQUEST_EVT, ONE_MINUTE );
|
|||
|
}
|
|||
|
|
|||
|
return ( events ^ ZDNWKMGR_UPDATE_REQUEST_EVT );
|
|||
|
}
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
if ( events & ZDNWKMGR_SCAN_REQUEST_EVT )
|
|||
|
{
|
|||
|
if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount > 0 )
|
|||
|
{
|
|||
|
if ( NLME_EDScanRequest( ZDNwkMgr_MgmtNwkUpdateReq.channelMask,
|
|||
|
ZDNwkMgr_MgmtNwkUpdateReq.scanDuration ) == ZSuccess )
|
|||
|
{
|
|||
|
ZDNwkMgr_MgmtNwkUpdateReq.scanCount--;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ( events ^ ZDNWKMGR_SCAN_REQUEST_EVT );
|
|||
|
}
|
|||
|
|
|||
|
// Discard or make more handlers
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessMsgCBs
|
|||
|
*
|
|||
|
* @brief Process the incoming messages.
|
|||
|
*
|
|||
|
* @param msgPtr - message to process
|
|||
|
*
|
|||
|
* @return TRUE if message to be freed. FALSE otherwise.
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_ProcessMsgCBs( zdoIncomingMsg_t *inMsg )
|
|||
|
{
|
|||
|
switch ( inMsg->clusterID )
|
|||
|
{
|
|||
|
case Mgmt_NWK_Update_req:
|
|||
|
ZDNwkMgr_ProcessMgmtNwkUpdateReq( inMsg );
|
|||
|
break;
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
case Mgmt_NWK_Update_notify:
|
|||
|
ZDNwkMgr_ProcessMgmtNwkUpdateNotify( inMsg );
|
|||
|
break;
|
|||
|
#endif // NWK_MANAGER
|
|||
|
case Server_Discovery_rsp:
|
|||
|
ZDNwkMgr_ProcessServerDiscRsp( inMsg );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
// Unknown message
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* Frequency Agility Routines
|
|||
|
*/
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessMgmtNwkUpdateNotify
|
|||
|
*
|
|||
|
* @brief This function processes the incoming Management
|
|||
|
* Network Update notify.
|
|||
|
*
|
|||
|
* @param pUpdateNotify - notify message
|
|||
|
*
|
|||
|
* @return TRUE if message to be freed. FALSE otherwise.
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_ProcessMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg )
|
|||
|
{
|
|||
|
if ( zgNwkMgrMode == ZDNWKMGR_ENABLE )
|
|||
|
{
|
|||
|
ZDO_MgmtNwkUpdateNotify_t *pNotify = ZDO_ParseMgmtNwkUpdateNotify( inMsg );
|
|||
|
if ( pNotify )
|
|||
|
{
|
|||
|
ZDNwkMgr_CheckForChannelChange( pNotify );
|
|||
|
|
|||
|
osal_mem_free( pNotify );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_CheckForChannelChange
|
|||
|
*
|
|||
|
* @brief This function processes the incoming Management Network
|
|||
|
* Update notify and starts an Update Request if a channel
|
|||
|
* change is needed.
|
|||
|
*
|
|||
|
* @param pUpdateNotify - notify message
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_CheckForChannelChange( ZDO_MgmtNwkUpdateNotify_t *pNotify )
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
uint16 failureRate;
|
|||
|
uint8 lowestEnergyIndex;
|
|||
|
uint8 lowestEnergyValue = 0xFF;
|
|||
|
|
|||
|
// If any device has more than 50% transmission failures, a channel
|
|||
|
// change should be considered
|
|||
|
failureRate = ( pNotify->transmissionFailures * 100 ) / pNotify->totalTransmissions;
|
|||
|
if ( failureRate < ZDNWKMGR_CC_TX_FAILURE )
|
|||
|
{
|
|||
|
#if defined ( LCD_SUPPORTED )
|
|||
|
HalLcdWriteString( (char*)NwkMgrStr_1, HAL_LCD_LINE_1 );
|
|||
|
HalLcdWriteStringValueValue( ": ", failureRate, 10, ZDNWKMGR_CC_TX_FAILURE, 10, HAL_LCD_LINE_2 );
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// If the current failure rate is higher than the last failure rate,
|
|||
|
// a channel change should be considered
|
|||
|
if ( failureRate < ZDNwkMgr_LastChannelFailureRate )
|
|||
|
{
|
|||
|
#if defined ( LCD_SUPPORTED )
|
|||
|
HalLcdWriteString( (char*)NwkMgrStr_2, HAL_LCD_LINE_1 );
|
|||
|
HalLcdWriteStringValueValue( ": ", failureRate, 10,
|
|||
|
ZDNwkMgr_LastChannelFailureRate, 10, HAL_LCD_LINE_2 );
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Select a single channel based on the Mgmt_NWK_Update_notify based on
|
|||
|
// the lowest energy. This is the proposed new channel.
|
|||
|
for ( i = 0; i < pNotify->listCount; i++ )
|
|||
|
{
|
|||
|
if ( pNotify->energyValues[i] < lowestEnergyValue )
|
|||
|
{
|
|||
|
lowestEnergyIndex = i;
|
|||
|
lowestEnergyValue = pNotify->energyValues[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// If this new channel does not have an energy level below an acceptable
|
|||
|
// threshold, a channel change should not be done.
|
|||
|
if ( lowestEnergyValue > ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL )
|
|||
|
{
|
|||
|
#if defined ( LCD_SUPPORTED )
|
|||
|
HalLcdWriteString( (char*)NwkMgrStr_3, HAL_LCD_LINE_1 );
|
|||
|
HalLcdWriteStringValueValue( ": ", lowestEnergyValue, 10,
|
|||
|
ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL, 10, HAL_LCD_LINE_2 );
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Channel change should be done -- find out the new active channel
|
|||
|
for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
|
|||
|
{
|
|||
|
if ( ( (uint32)1 << i ) & pNotify->scannedChannels )
|
|||
|
{
|
|||
|
if ( lowestEnergyIndex == 0 )
|
|||
|
break;
|
|||
|
lowestEnergyIndex--;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( ( _NIB.nwkLogicalChannel != i ) && ( ZDNwkMgr_UpdateRequestTimer == 0 ) )
|
|||
|
{
|
|||
|
uint32 channelMask;
|
|||
|
zAddrType_t dstAddr;
|
|||
|
|
|||
|
// The new channel
|
|||
|
ZDNwkMgr_NewChannel = i;
|
|||
|
|
|||
|
// Prior to changing channels, the network manager should store the
|
|||
|
// energy scan value as the last energy scan value and the failure
|
|||
|
// rate from the existing channel as the last failure rate. These
|
|||
|
// values are useful to allow comparison of the failure rate and energy
|
|||
|
// level on the previous channel to evaluate if the network is causing
|
|||
|
// its own interference.
|
|||
|
ZDNwkMgr_LastChannelEnergy = lowestEnergyValue;
|
|||
|
ZDNwkMgr_LastChannelFailureRate = failureRate;
|
|||
|
|
|||
|
// The network manager should broadcast a Mgmt_NWK_Update_req notifying
|
|||
|
// devices of the new channel. The broadcast shall be to all routers
|
|||
|
// and coordinator.
|
|||
|
dstAddr.addrMode = AddrBroadcast;
|
|||
|
dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR_DEVRXON;
|
|||
|
channelMask = (uint32)1 << i;
|
|||
|
|
|||
|
// Increment the nwkUpdateId parameter and set the updateID in the beacon
|
|||
|
NLME_SetUpdateID(_NIB.nwkUpdateId + 1);
|
|||
|
|
|||
|
ZDP_MgmtNwkUpdateReq( &dstAddr, channelMask, 0xfe, 0, _NIB.nwkUpdateId, 0 );
|
|||
|
|
|||
|
// The network manager shall set a timer based on the value of
|
|||
|
// apsChannelTimer upon issue of a Mgmt_NWK_Update_req that changes
|
|||
|
// channels and shall not issue another such command until this
|
|||
|
// timer expires.
|
|||
|
ZDNwkMgr_UpdateRequestTimer = ZDNWKMGR_UPDATE_REQUEST_TIMER;
|
|||
|
osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_REQUEST_EVT, ONE_MINUTE );
|
|||
|
|
|||
|
// Upon receipt of a Mgmt_NWK_Update_req with a change of channels,
|
|||
|
// the local network manager shall set a timer equal to the
|
|||
|
// nwkNetworkBroadcastDeliveryTime and shall switch channels upon
|
|||
|
// expiration of this timer. NOTE: since we won't recevied our own
|
|||
|
// broadcasted Update Request, we start the channel change timer here.
|
|||
|
osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_CHANNEL_CHANGE_EVT,
|
|||
|
ZDNWKMGR_BCAST_DELIVERY_TIME );
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessMgmtNwkUpdateReq
|
|||
|
*
|
|||
|
* @brief This function processes the incoming Management
|
|||
|
* Network Update request and starts the request (if needed).
|
|||
|
*
|
|||
|
* @param Request message
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_ProcessMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg )
|
|||
|
{
|
|||
|
ZDO_MgmtNwkUpdateReq_t Req;
|
|||
|
|
|||
|
ZDO_ParseMgmtNwkUpdateReq( inMsg, &Req );
|
|||
|
|
|||
|
if ( Req.scanDuration <= 0x05 )
|
|||
|
{
|
|||
|
// Request is to scan over channelMask. The result will be reported by Confirm
|
|||
|
if ( ( !inMsg->wasBroadcast ) &&
|
|||
|
( Req.scanCount > ZDNWKMGR_MIN_SCAN_COUNT ) &&
|
|||
|
( Req.scanCount <= ZDNWKMGR_MAX_SCAN_COUNT ) )
|
|||
|
{
|
|||
|
if ( NLME_EDScanRequest( Req.channelMask, Req.scanDuration ) == ZSuccess )
|
|||
|
{
|
|||
|
// Save off the information to be used for the notify
|
|||
|
ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq = inMsg->TransSeq;
|
|||
|
ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
|
|||
|
|
|||
|
Req.scanCount--;
|
|||
|
|
|||
|
// Save off scan info for the subsequent scans
|
|||
|
ZDNwkMgr_MgmtNwkUpdateReq = Req;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( Req.scanDuration == 0xFE )
|
|||
|
{
|
|||
|
// Request is to change Channel. The command provide a new active
|
|||
|
// channel as a single channel in the channelMask.
|
|||
|
if ( Req.nwkUpdateId > _NIB.nwkUpdateId )
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
|
|||
|
// Set update ID in the Beacon
|
|||
|
NLME_SetUpdateID(Req.nwkUpdateId);
|
|||
|
|
|||
|
// Find out the new active channel
|
|||
|
for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
|
|||
|
{
|
|||
|
if ( ( (uint32)1 << i ) & Req.channelMask )
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( _NIB.nwkLogicalChannel != i )
|
|||
|
{
|
|||
|
ZDNwkMgr_NewChannel = i;
|
|||
|
|
|||
|
// Upon receipt of a Mgmt_NWK_Update_req with a change of channels,
|
|||
|
// the local network manager shall set a timer equal to the
|
|||
|
// nwkNetworkBroadcastDeliveryTime and shall switch channels upon
|
|||
|
// expiration of this timer. Each node shall also increment the
|
|||
|
// nwkUpdateId parameter and also reset the total transmit count
|
|||
|
// and the transmit failure counters.
|
|||
|
osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_CHANNEL_CHANGE_EVT,
|
|||
|
ZDNWKMGR_BCAST_DELIVERY_TIME );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( Req.scanDuration == 0xFF )
|
|||
|
{
|
|||
|
// Request is to change apsChannelMask and nwkManagerAddr
|
|||
|
if ( Req.nwkUpdateId > _NIB.nwkUpdateId )
|
|||
|
{
|
|||
|
NLME_SetUpdateID(Req.nwkUpdateId); // Set the updateID in the beacon
|
|||
|
|
|||
|
if ( ( Req.channelMask != 0 ) && ( _NIB.channelList != Req.channelMask ) )
|
|||
|
{
|
|||
|
_NIB.channelList = Req.channelMask;
|
|||
|
|
|||
|
// Our Channel List has been changed -- notify to save info into NV
|
|||
|
ZDApp_NwkStateUpdateCB();
|
|||
|
}
|
|||
|
|
|||
|
ZDNwkMgr_SetNwkManagerAddr( Req.nwkManagerAddr );
|
|||
|
}
|
|||
|
}
|
|||
|
else // 0x06-0xFD
|
|||
|
{
|
|||
|
// Request is invalid
|
|||
|
if ( !inMsg->wasBroadcast )
|
|||
|
{
|
|||
|
ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
|
|||
|
ZDP_MgmtNwkUpdateNotify( inMsg->TransSeq, &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
|
|||
|
ZDP_INVALID_REQTYPE, 0, 0, 0, 0, NULL, AF_TX_OPTIONS_NONE, false );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessServerDiscRsp
|
|||
|
*
|
|||
|
* @brief Process the incoming System Server Discovery Response
|
|||
|
*
|
|||
|
* @param pRsp - Structure containing Server Discovery response
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_ProcessServerDiscRsp( zdoIncomingMsg_t *inMsg )
|
|||
|
{
|
|||
|
ZDO_ServerDiscRsp_t Rsp;
|
|||
|
|
|||
|
ZDO_ParseServerDiscRsp( inMsg, &Rsp );
|
|||
|
|
|||
|
if ( Rsp.status == ZSuccess )
|
|||
|
{
|
|||
|
// Is the Network Manager bit set in the response?
|
|||
|
if ( Rsp.serverMask & NETWORK_MANAGER )
|
|||
|
{
|
|||
|
// Set the Remote Device's NWK Address as the Network Manager Address
|
|||
|
ZDNwkMgr_SetNwkManagerAddr( inMsg->srcAddr.addr.shortAddr );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessChannelInterference
|
|||
|
*
|
|||
|
* @brief This function processes the incoming Channel Interference
|
|||
|
* detection message and sends out a notify (if needed).
|
|||
|
*
|
|||
|
* @param pChannelInterference - interference message
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_ProcessChannelInterference( ZDNwkMgr_ChanInterference_t *pChanInterference )
|
|||
|
{
|
|||
|
// To avoid a device with communication problems from constantly
|
|||
|
// sending reports to the network manager, the device should not
|
|||
|
// send a Mgmt_NWK_Update_notify more than 4 times per hour.
|
|||
|
if ( ZDNwkMgr_NumUpdateNotifySent < 4 )
|
|||
|
{
|
|||
|
// Conduct an energy scan on all channels.
|
|||
|
if ( NLME_EDScanRequest( MAX_CHANNELS_24GHZ, _NIB.scanDuration ) == ZSuccess )
|
|||
|
{
|
|||
|
// Save the counters for the Update Notify message to be sent
|
|||
|
ZDNwkMgr_TotalTransmissions = pChanInterference->totalTransmissions;
|
|||
|
ZDNwkMgr_TxFailures = pChanInterference->txFailures;
|
|||
|
|
|||
|
// Mark scan as channel inetrference check
|
|||
|
ZDNwkMgr_MgmtNwkUpdateReq.scanCount = 0xFF;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessEDScanConfirm
|
|||
|
*
|
|||
|
* @brief This function processes the incoming ED Scan Confirm
|
|||
|
* message and sends out a notify (if needed).
|
|||
|
*
|
|||
|
* @param pEDScanConfirm - SD Scan Confirmation message
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_ProcessEDScanConfirm( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm )
|
|||
|
{
|
|||
|
if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount == 0xFF )
|
|||
|
{
|
|||
|
// Confirm to scan all channels for channel interference check
|
|||
|
ZDNwkMgr_CheckForChannelInterference( pEDScanConfirm );
|
|||
|
|
|||
|
ZDNwkMgr_MgmtNwkUpdateReq.scanCount = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Confirm to the requested scan
|
|||
|
uint16 txFailures = nwkTransmissionFailures( FALSE );
|
|||
|
|
|||
|
ZDNwkMgr_BuildAndSendUpdateNotify( ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq,
|
|||
|
&ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
|
|||
|
_NIB.nwkTotalTransmissions, txFailures,
|
|||
|
pEDScanConfirm, AF_TX_OPTIONS_NONE );
|
|||
|
// More scans needed?
|
|||
|
if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount > 0 )
|
|||
|
{
|
|||
|
osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_SCAN_REQUEST_EVT, 50 );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_CheckForChannelInterference
|
|||
|
*
|
|||
|
* @brief This function processes the incoming ED Scan Confirm
|
|||
|
* message and sends out an Update Notify (if needed).
|
|||
|
*
|
|||
|
* @param pEDScanConfirm - SD Scan Confirmation message
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_CheckForChannelInterference( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm )
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
uint8 channelEnergy = 0;
|
|||
|
uint8 energyIncreased = FALSE;
|
|||
|
|
|||
|
// Get the current channel energy
|
|||
|
if ( ( (uint32)1 << _NIB.nwkLogicalChannel ) & pEDScanConfirm->scannedChannels )
|
|||
|
{
|
|||
|
channelEnergy = pEDScanConfirm->energyDetectList[_NIB.nwkLogicalChannel];
|
|||
|
}
|
|||
|
|
|||
|
// If this energy scan does not indicate higher energy on the current
|
|||
|
// channel then other channels, no action is taken. The device should
|
|||
|
// continue to operate as normal and the message counters are not reset.
|
|||
|
for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
|
|||
|
{
|
|||
|
if ( ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels ) &&
|
|||
|
( channelEnergy > pEDScanConfirm->energyDetectList[i] ) )
|
|||
|
{
|
|||
|
energyIncreased = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// If the energy scan does indicate increased energy on the channel
|
|||
|
// in use, a Mgmt_NWK_Update_notify should be sent to the Network
|
|||
|
// Manager to indicate interference is present.
|
|||
|
if ( energyIncreased )
|
|||
|
{
|
|||
|
// Send a Management Network Update notify to the Network Manager
|
|||
|
ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = _NIB.nwkManagerAddr;
|
|||
|
ZDNwkMgr_BuildAndSendUpdateNotify( 0, &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
|
|||
|
ZDNwkMgr_TotalTransmissions, ZDNwkMgr_TxFailures,
|
|||
|
pEDScanConfirm, AF_MSG_ACK_REQUEST );
|
|||
|
ZDNwkMgr_WaitingForNotifyConfirm = TRUE; // Confirm will clear the counters
|
|||
|
|
|||
|
if ( ZDNwkMgr_NumUpdateNotifySent == 0 )
|
|||
|
{
|
|||
|
// First notify message sent within this hour. Start the Update Notify timer.
|
|||
|
ZDNwkMgr_UpdateNotifyTimer = ZDNWKMGR_UPDATE_NOTIFY_TIMER;
|
|||
|
osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_NOTIFY_EVT, ONE_MINUTE );
|
|||
|
}
|
|||
|
|
|||
|
ZDNwkMgr_NumUpdateNotifySent++;
|
|||
|
}
|
|||
|
#if defined ( LCD_SUPPORTED )
|
|||
|
else
|
|||
|
{
|
|||
|
HalLcdWriteString( (char*)NwkMgrStr_4, HAL_LCD_LINE_1 );
|
|||
|
HalLcdWriteStringValueValue( ": ", _NIB.nwkLogicalChannel, 10, channelEnergy, 10, HAL_LCD_LINE_2 );
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_BuildAndSendUpdateNotify
|
|||
|
*
|
|||
|
* @brief This builds and send a Mgmt_NWK_Update_notify message. This
|
|||
|
* function sends a unicast message.
|
|||
|
*
|
|||
|
* @param TransSeq - transaction sequence number
|
|||
|
* @param dstAddr - destination address of the message
|
|||
|
* @param pEDScanConfirm - update notify info
|
|||
|
*
|
|||
|
* @return afStatus_t
|
|||
|
*/
|
|||
|
static void ZDNwkMgr_BuildAndSendUpdateNotify( uint8 TransSeq, zAddrType_t *dstAddr,
|
|||
|
uint16 totalTransmissions, uint16 txFailures,
|
|||
|
ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm,
|
|||
|
uint8 txOptions )
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
uint8 listCount = 0;
|
|||
|
uint8 *energyValues = NULL;
|
|||
|
|
|||
|
// Count number of energy detects
|
|||
|
for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
|
|||
|
{
|
|||
|
if ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels )
|
|||
|
listCount++;
|
|||
|
}
|
|||
|
|
|||
|
if ( listCount > 0 )
|
|||
|
{
|
|||
|
energyValues = (uint8 *)osal_mem_alloc( listCount );
|
|||
|
if ( energyValues )
|
|||
|
{
|
|||
|
uint8 j = 0;
|
|||
|
|
|||
|
for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
|
|||
|
{
|
|||
|
if ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels )
|
|||
|
energyValues[j++] = pEDScanConfirm->energyDetectList[i];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Send a Management Network Update notify back
|
|||
|
ZDP_MgmtNwkUpdateNotify( TransSeq, dstAddr, pEDScanConfirm->status,
|
|||
|
pEDScanConfirm->scannedChannels,
|
|||
|
totalTransmissions, txFailures,
|
|||
|
listCount, energyValues, txOptions, false );
|
|||
|
if ( energyValues )
|
|||
|
osal_mem_free( energyValues );
|
|||
|
}
|
|||
|
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
/*********************************************************************
|
|||
|
* @fn NwkMgr_SetNwkManager
|
|||
|
*
|
|||
|
* @brief Set the local device as the Network Manager
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void NwkMgr_SetNwkManager( void )
|
|||
|
{
|
|||
|
if ( zgNwkMgrMode == ZDNWKMGR_ENABLE )
|
|||
|
{
|
|||
|
// We're the Network Manager. Set our address as the Network Manager Address
|
|||
|
ZDNwkMgr_SetNwkManagerAddr( _NIB.nwkDevAddress );
|
|||
|
|
|||
|
// Set the Network Manager bit of the Server Mask
|
|||
|
ZDO_Config_Node_Descriptor.ServerMask |= NETWORK_MANAGER;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDApp_SetNwkManagerAddr()
|
|||
|
*
|
|||
|
* @brief Sets the nwkManagerAddr in NIB.
|
|||
|
*
|
|||
|
* @param nwkManagerAddr
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_SetNwkManagerAddr( uint16 nwkManagerAddr )
|
|||
|
{
|
|||
|
if ( _NIB.nwkManagerAddr != nwkManagerAddr )
|
|||
|
{
|
|||
|
// Update the Network Manager Address
|
|||
|
_NIB.nwkManagerAddr = nwkManagerAddr;
|
|||
|
|
|||
|
// Our Network Manger Address has been changed -- notify to save info into NV
|
|||
|
ZDApp_NwkStateUpdateCB();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ReportChannelInterference
|
|||
|
*
|
|||
|
* @brief This function builds a Channel Interference detection
|
|||
|
* message and then forwards it to the Network Manager.
|
|||
|
*
|
|||
|
* @param chanInterference
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_ReportChannelInterference( NLME_ChanInterference_t *chanInterference )
|
|||
|
{
|
|||
|
ZDNwkMgr_ChanInterference_t *pChanInterference;
|
|||
|
|
|||
|
// Send Channel Interference message to the Network Manager task
|
|||
|
pChanInterference = (ZDNwkMgr_ChanInterference_t *)osal_msg_allocate( sizeof( ZDNwkMgr_ChanInterference_t ) );
|
|||
|
if ( pChanInterference )
|
|||
|
{
|
|||
|
pChanInterference->hdr.event = NM_CHANNEL_INTERFERE;
|
|||
|
|
|||
|
// Build the structure
|
|||
|
pChanInterference->totalTransmissions = chanInterference->totalTransmissions;
|
|||
|
pChanInterference->txFailures = chanInterference->txFailures;
|
|||
|
|
|||
|
osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pChanInterference );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_EDScanConfirmCB
|
|||
|
*
|
|||
|
* @brief Handle Energy Scan confirm callback
|
|||
|
*
|
|||
|
* @param scannedChannels - scanned channels
|
|||
|
* @param energyDetectList - measured energy for channels
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_EDScanConfirmCB( NLME_EDScanConfirm_t *EDScanConfirm )
|
|||
|
{
|
|||
|
ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm;
|
|||
|
|
|||
|
// Send ED Confirm to the Network Manager task
|
|||
|
pEDScanConfirm = (ZDNwkMgr_EDScanConfirm_t *)osal_msg_allocate( sizeof( ZDNwkMgr_EDScanConfirm_t ) );
|
|||
|
if ( pEDScanConfirm )
|
|||
|
{
|
|||
|
pEDScanConfirm->hdr.event = NM_ED_SCAN_CONFIRM;
|
|||
|
|
|||
|
// Build the structure
|
|||
|
pEDScanConfirm->status = EDScanConfirm->status;
|
|||
|
pEDScanConfirm->scannedChannels = EDScanConfirm->scannedChannels;
|
|||
|
osal_memcpy( pEDScanConfirm->energyDetectList, EDScanConfirm->energyDetectList, ED_SCAN_MAXCHANNELS );
|
|||
|
|
|||
|
osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pEDScanConfirm );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessDataConfirm
|
|||
|
*
|
|||
|
* @brief Process received Confirmation for Mgmt NWK Update Notify message
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_ProcessDataConfirm( afDataConfirm_t *afDataConfirm )
|
|||
|
{
|
|||
|
if ( ZDNwkMgr_WaitingForNotifyConfirm &&
|
|||
|
( afDataConfirm->transID == 0 ) &&
|
|||
|
( afDataConfirm->hdr.status == ZSuccess ) )
|
|||
|
{
|
|||
|
// The Mgmt NWK Update Notify was sent as an APS Unicast with
|
|||
|
// acknowledgement and once the acknowledgment is received the
|
|||
|
// total transmit and transmit failure counters are reset to zero.
|
|||
|
_NIB.nwkTotalTransmissions = 0;
|
|||
|
nwkTransmissionFailures( TRUE );
|
|||
|
|
|||
|
ZDNwkMgr_WaitingForNotifyConfirm = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* PAN ID Conflict Routines
|
|||
|
*/
|
|||
|
#if defined ( NWK_MANAGER )
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_NetworkReportCB
|
|||
|
*
|
|||
|
* @brief Handle the Network Report Command
|
|||
|
*
|
|||
|
* @param srcAddr - Source Address of the message.
|
|||
|
* @param status - ZSuccess.
|
|||
|
* @param serverMask - Bit mask of services matching the req serverMask.
|
|||
|
* @param securityUse -
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_NetworkReportCB( ZDNwkMgr_NetworkReport_t *pReport )
|
|||
|
{
|
|||
|
// Send Network Report message to the Network Manager task
|
|||
|
osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pReport );
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_NetworkUpdateCB
|
|||
|
*
|
|||
|
* @brief Handle the Network Update Command
|
|||
|
*
|
|||
|
* @param srcAddr - Source Address of the message.
|
|||
|
* @param status - ZSuccess.
|
|||
|
* @param serverMask - Bit mask of services matching the req serverMask.
|
|||
|
* @param securityUse -
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_NetworkUpdateCB( ZDNwkMgr_NetworkUpdate_t *pUpdate )
|
|||
|
{
|
|||
|
// Send Network Update message to the Network Manager task
|
|||
|
osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pUpdate );
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessNetworkReport
|
|||
|
*
|
|||
|
* @brief Process the incoming Network Report message
|
|||
|
*
|
|||
|
* @param pNetworkReport - Structure containing Network Report message
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_ProcessNetworkReport( ZDNwkMgr_NetworkReport_t *pNetworkReport )
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
uint16 newPID;
|
|||
|
uint8 unique = TRUE;
|
|||
|
|
|||
|
if ( pNetworkReport->reportType == NWKREPORT_PANID_CONFLICT )
|
|||
|
{
|
|||
|
if ( ZDNwkMgr_PanIdUpdateInProgress == FALSE )
|
|||
|
{
|
|||
|
do
|
|||
|
{
|
|||
|
// select a new PAN ID
|
|||
|
newPID = (uint16)osal_rand();
|
|||
|
|
|||
|
// Make sure that the chosen PAN ID is not already in use in the
|
|||
|
// local neighborhood and also not contained within the Report
|
|||
|
// Information field of the Network Report Command frame
|
|||
|
for ( i = 0; i < pNetworkReport->reportInfoCnt; i++ )
|
|||
|
{
|
|||
|
if ( pNetworkReport->panIDs[i] == newPID )
|
|||
|
{
|
|||
|
unique = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
} while ( !unique );
|
|||
|
|
|||
|
// Send out a Network Update command.
|
|||
|
NLME_SendNetworkUpdate( NWK_BROADCAST_SHORTADDR, NWKUPDATE_PANID_UPDATE,
|
|||
|
_NIB.extendedPANID, _NIB.nwkUpdateId+1, newPID );
|
|||
|
|
|||
|
ZDNwkMgr_PanIdUpdateInProgress = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDNwkMgr_ProcessNetworkUpdate
|
|||
|
*
|
|||
|
* @brief Process the incoming Network Update message
|
|||
|
*
|
|||
|
* @param pNetworkReport - Structure containing Network Update message
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDNwkMgr_ProcessNetworkUpdate( ZDNwkMgr_NetworkUpdate_t *pNetworkUpdate )
|
|||
|
{
|
|||
|
if ( pNetworkUpdate->updateType == NWKUPDATE_PANID_UPDATE )
|
|||
|
{
|
|||
|
// Our PAN ID has been changed -- notify to save info into NV
|
|||
|
ZDApp_NwkStateUpdateCB();
|
|||
|
|
|||
|
ZDNwkMgr_PanIdUpdateInProgress = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // NWK_MANAGER
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*********************************************************************/
|