下面看一下终端结点的不同之处,下面这个图是终端结点的的编译选项,这里我们可以看到没有了编译选项SOFT_START。这里我们重点看一下不同之处。

#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
// Device Logical Type
uint8 zgDeviceLogicalType = DEVICE_LOGICAL_TYPE;
#if defined ( SOFT_START )
#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_SOFT
#elif defined( ZDO_COORDINATOR )
#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_COORDINATOR
#elif defined (RTR_NWK)
#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ROUTER
#else
#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ENDDEVICE
#endif
最后得出
zgDeviceLogicalType = DEVICE_LOGICAL_TYPE =ZG_DEVICETYPE_ENDDEVICE
这里主要的不同还是在应用程序中的按键部分,下面是按键的程序,这个是在SimpleSwitch.c中
void zb_HandleKeys( uint8 shift, uint8 keys )
{
uint8 startOptions;
uint8 logicalType;
// Shift is used to make each button/switch dual purpose.
if ( shift )
{
if ( keys & HAL_KEY_SW_1 )
{
}
if ( keys & HAL_KEY_SW_2 )
{
}
if ( keys & HAL_KEY_SW_3 )
{
}
if ( keys & HAL_KEY_SW_4 )
{
}
}
else
{
if ( keys & HAL_KEY_SW_1 )
{
if ( myAppState == APP_INIT )
{
// In the init state, keys are used to indicate the logical mode.
// The Switch device is always an end-device 在这里当按下S1按键时设置为终端设备
logicalType = ZG_DEVICETYPE_ENDDEVICE;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
// Do more configuration if necessary and then restart device with auto-start bit set
zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
startOptions = ZCD_STARTOPT_AUTO_START;
zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
zb_SystemReset();
}
else
{
// Initiate a binding with null destination
zb_BindDevice(TRUE, TOGGLE_LIGHT_CMD_ID, NULL);
}
}
if ( keys & HAL_KEY_SW_2 )
{
if ( myAppState == APP_INIT )
{
// In the init state, keys are used to indicate the logical mode.
// The Switch device is always an end-device按键SW2和SW1的作用是一样的,都是设置为终端设备,这里也和协调器和路由器稍微有点不同
logicalType = ZG_DEVICETYPE_ENDDEVICE;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
startOptions = ZCD_STARTOPT_AUTO_START;
zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
zb_SystemReset();
}
else
{
// Send the command to toggle light
zb_SendDataRequest( 0xFFFE, TOGGLE_LIGHT_CMD_ID, 0,
(uint8 *)NULL, myAppSeqNumber, 0, 0 );
}
}
if ( keys & HAL_KEY_SW_3 )
{
// Remove all existing bindings
zb_BindDevice(FALSE, TOGGLE_LIGHT_CMD_ID, NULL);
}
if ( keys & HAL_KEY_SW_4 )
{
}
}
}
从上面可以看出KEY1 KEY2都是作为终端设备的。而在函数中也并没有改变上面的变量的类型。下面的这个函数,在函数uint8 ZDOInitDevice( uint16 startDelay )调用的,上面在分析协调器的时,也有看到,这个函数在这里就直接返回,并没有起到什么作用。
void ZDAppDetermineDeviceType( void )
{
if ( zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE )
return;
#if defined ( SOFT_START )
if ( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR )
{
devStartMode = MODE_HARD; // Start as a coordinator
ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
}
else
{
if ( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER )
{
softStartAllowCoord = FALSE; // Don't allow coord to start
continueJoining = TRUE;
}
devStartMode = MODE_JOIN; // Assume joining
}
#endif // SOFT_START
}
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);
}
}
在ZDO_StartDevice()函数中可以根据不同的选项来进行操作。
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 */
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( "StartDevice ERR", "MODE unknown" );
#endif
}
}
#endif //!ZDO COORDINATOR || SOFT_START
if ( ret != ZSuccess )
osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
}
在终端的结点时,就会执行蓝色的代码。至此,在程序中设备类型就确定了。这样整个工程中的三个设备就可以确定,并按照设定的方式来加入网络,或者形成网络了。
补充:
还有一个问题有点迷糊,现在解决一下,就是zgDeviceLogicalType全局变量是怎么改变的,因为这个全局变量会在函数void ZDAppDetermineDeviceType( void )用到,在工程中搜索zgDeviceLogicalType变量,并没有发现那里给其赋于了新值,只在ZGlobals.c文件中有下面的赋值,可是我们在应用程序中对NV条目也就是ZCD_NV_LOGICAL_TYPE中,写入了新的值。在按键处理程序中,
uint8 zgDeviceLogicalType = DEVICE_LOGICAL_TYPE;
zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType );
if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )
{
logicalType = ZG_DEVICETYPE_COORDINATOR;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
}
那条目ZCD_NV_LOGICAL_TYP中的值是怎么最后赋给了zgDeviceLogicalType变量呢?这个按键程序完后会执行系统的重启命令。
可以看到在
typedef struct zgItem
{
uint16 id;
uint16 len;
void *buf;
} zgItem_t;
static CONST zgItem_t zgItemTable[] =
{
#if defined ( NV_INIT )
{
ZCD_NV_LOGICAL_TYPE, sizeof(zgDeviceLogicalType), &zgDeviceLogicalType//在这里进行了彼此之间的联系
},
{
ZCD_NV_POLL_RATE, sizeof(zgPollRate), &zgPollRate
},
.......
}
在下面的函数初始化的进行判断
uint8 zgInit( void )
{
uint8 i = 0;
uint8 setDefault = FALSE;
// Do we want to default the Config state values 这里可以看到zgReadStartupOptions()读取ZCD_NV_STARTUP_OPTION条目的选项,在前面的应用中我们可以看到,ZCD_NV_STARTUP_OPTION条目中已经写入了ZCD_STARTOPT_AUTO_START值也就是0x04 & 0x01,if判断不成功。setDefualt=FALSE
if ( zgReadStartupOptions() & ZCD_STARTOPT_DEFAULT_CONFIG_STATE )
{
setDefault = TRUE;
}
...................
while ( zgItemTable[i].id != 0x00 )
{
// Initialize the item
zgItemInit( zgItemTable[i].id, zgItemTable[i].len, zgItemTable[i].buf, setDefault );
// Move on to the next item
i++;
}
// Clear the Config State default
if ( setDefault )
{
zgWriteStartupOptions( ZG_STARTUP_CLEAR, ZCD_STARTOPT_DEFAULT_CONFIG_STATE );
}
return ( ZSUCCESS );
}
#define ZCD_STARTOPT_DEFAULT_CONFIG_STATE 0x01
#define ZCD_STARTOPT_DEFAULT_NETWORK_STATE 0x02
#define ZCD_STARTOPT_AUTO_START 0x04
在zgItemInit()函数中,由于传递过来的值是setDefault为FALSE,也就是NV条目中已经写入了值所以,不会进行默认的初始化,而是读出条目中的值 ,这样就会把ZCD_NV_LOGICAL_TYP条目中的值,赋值给了zgDeviceLogicalType变量。这里也就是对这个变量的改变过程。
static uint8 zgItemInit( uint16 id, uint16 len, void *buf, uint8 setDefault )
{
uint8 status;
// If the item doesn't exist in NV memory, create and initialize
// it with the value passed in. 如果条目已经存在的话,直接返回成功,不存在的的话直接创建和初始化
status = osal_nv_item_init( id, len, buf );
if ( status == ZSUCCESS )
{
if ( setDefault )
{
// Write the default value back to NV
status = osal_nv_write( id, 0, len, buf );
}
else
{
// The item exists in NV memory, read it from NV memory
条目已经存在则读取
status = osal_nv_read( id, 0, len, buf );
}
}
return (status);
}