协议栈如何辨别设备类型?在上图中可以看到协调器建立网络的步骤以及路由器和终端加入网络的过程,但协议栈究竟如何区分设备类型,仅从图中无法看出。
在ZDApp.c文件中,ZDOInitDevice( uint16 startDelay )函数调用了ZDAppDetermineDeviceType()函数,函数原型:/********************************************************************** @fn ZDAppDetermineDeviceType()* @brief Determines the type of device to start.** Looks at zgDeviceLogicalType and determines what type of* device to start. The types are:* ZG_DEVICETYPE_COORDINATOR* ZG_DEVICETYPE_ROUTER* ZG_DEVICETYPE_ENDDEVICE** @param none* @return none*/void ZDAppDetermineDeviceType( void ){if ( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR ){devStartMode = MODE_HARD; // Start as a coordinatorZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;}else{if ( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER )ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_ROUTER;else if ( zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE )ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_DEVICE;// If AIB_apsUseExtendedPANID is set to a non-zero value by commissioning// The device shall do rejoin the network. Otherwise, do normal joinif ( nwk_ExtPANIDValid( AIB_apsUseExtendedPANID ) == false ){devStartMode = MODE_JOIN; // Assume joining}else{devStartMode = MODE_REJOIN;}}}该函数中的关键句是if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) ,其中,在ZGlobals,c文件中有如下定义:zgDeviceLogicalType = DEVICE_LOGICAL_TYPE 而在ZGlobals.h文件中有如下宏定义:#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_COORDINATOR,最终在sapi.h文件中,出现如下宏定义:#define ZG_DEVICETYPE_COORDINATOR 0x00 ,这样看来似乎绕了一圈又绕回了原点,其实并非如此,在ZGlobals.h文件中完整的宏定义代码:// Default Device Logical Type#if !defined ( DEVICE_LOGICAL_TYPE )#if ( ZG_BUILD_COORDINATOR_TYPE )// If capable, default to coordinator#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_COORDINATOR #elif ( ZG_BUILD_RTR_TYPE )#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ROUTER#elif ( ZG_BUILD_ENDDEVICE_TYPE )// Must be an end device#define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ENDDEVICE#else#error ZSTACK_DEVICE_BUILD must be defined as something!#endif#endif可以看出,设备是协调器,路由器还是终端,都是在这里区别开来的。
区别的关键就变成了条件编译语句中的判断条件(高亮显示的三个语句),还是该头文件下,有以下条件编译:// Setup to work with the existing (old) compile flags#if !defined ( ZSTACK_DEVICE_BUILD )#if defined ( ZDO_COORDINATOR )#define ZSTACK_DEVICE_BUILD (DEVICE_BUILD_COORDINATOR) #elif defined ( RTR_NWK )#define ZSTACK_DEVICE_BUILD (DEVICE_BUILD_ROUTER)#else#define ZSTACK_DEVICE_BUILD (DEVICE_BUILD_ENDDEVICE)#endif#endif// Use the following to macros to make device type decisions#define ZG_BUILD_COORDINATOR_TYPE (ZSTACK_DEVICE_BUILD & DEVICE_BUILD_COORDINATOR)#define ZG_BUILD_RTR_TYPE (ZSTACK_DEVICE_BUILD & (DEVICE_BUILD_COORDINATOR | DEVICE_BUILD_ROUTER))#define ZG_BUILD_ENDDEVICE_TYPE (ZSTACK_DEVICE_BUILD & DEVICE_BUILD_ENDDEVICE)#define ZG_BUILD_RTRONLY_TYPE (ZSTACK_DEVICE_BUILD == DEVICE_BUILD_ROUTER)#define ZG_BUILD_JOINING_TYPE (ZSTACK_DEVICE_BUILD & (DEVICE_BUILD_ROUTER | DEVICE_BUILD_ENDDEVICE))#if ( ZSTACK_DEVICE_BUILD == DEVICE_BUILD_COORDINATOR )#define ZG_DEVICE_COORDINATOR_TYPE 1#else#define ZG_DEVICE_COORDINATOR_TYPE (zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR)#endif#if ( ZSTACK_DEVICE_BUILD == (DEVICE_BUILD_ROUTER | DEVICE_BUILD_COORDINATOR) )#define ZG_DEVICE_RTR_TYPE 1#else#define ZG_DEVICE_RTR_TYPE ((zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) || (zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER))#endif#if ( ZSTACK_DEVICE_BUILD == DEVICE_BUILD_ENDDEVICE )#define ZG_DEVICE_ENDDEVICE_TYPE 1#else#define ZG_DEVICE_ENDDEVICE_TYPE (zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE)#endif#define ZG_DEVICE_JOINING_TYPE ((zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER) || (zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE))#if ( ZG_BUILD_RTR_TYPE )#if ( ZG_BUILD_ENDDEVICE_TYPE )#define ZSTACK_ROUTER_BUILD (ZG_BUILD_RTR_TYPE && ZG_DEVICE_RTR_TYPE)#else#define ZSTACK_ROUTER_BUILD 1#endif#else#define ZSTACK_ROUTER_BUILD 0#endif#if ( ZG_BUILD_ENDDEVICE_TYPE )#if ( ZG_BUILD_RTR_TYPE )#define ZSTACK_END_DEVICE_BUILD(ZG_BUILD_ENDDEVICE_TYPE && ZG_DEVICE_ENDDEVICE_TYPE)#else#define ZSTACK_END_DEVICE_BUILD 1#endif#else#define ZSTACK_END_DEVICE_BUILD 0#endif可以看到该段代码的解释Use the following to macros to make device type decisions,使用下列宏来决定设备类型。
其实,整个文件都是一些宏定义和条件编译语句,都是涉及如何区别设备类型,但鉴于代码太难读,又是初学,所以无法再往下分析了。
总之,ZDOInitDevice( uint16 startDelay )函数调用ZDAppDetermineDeviceType()函数之后就已经确定了设备类型。
今天发现,设备类型的最终定义在Tools文件下的三个配置文件中,图1在f8wCoord.cfg、f8wEndev.cfg和f8wRouter.cfg三个配置文件中分别定义了协调器、路由器和终端各自所具有的的功能。