ZigBee2006和 ZigBee 2007使用分布式寻址方案来分配网络地址。这个方案保证在整个网络中所有分配的地址是唯一的。这一点是必须的,因为这样才能保证一个特定的数据包能够发给它指定的设备,而不出现混乱。同时,这个寻址算法本身的分布特性保证设备只能与他的父辈设备通讯来接受一个网络地址。不需要整个网络范围内通讯的地址分配,这有助于网络的可测量性。
假设父设备可拥有的最大子设备数为Cm,其拥有的最大路由子设备数为 Rm,网络的最大深度为Lm,则父设备所能分配子区段地址数为:
若Rm=1,Cskip(d)= 1+Cm*(Lm-d-1);
若Rm不为1,则Cskip(d)=(1+Cm-Rm-Cm*( Rm)^(Lm-d-1))/(1-Rm).
子节点为父设备的第n个子路由器的短地址分配:
Achild =Aparent +(n-1)*Cskip(d)+1,n=1
Achild =Aparen +(n-1)*Cskip(d),n>1
子节点为父设备的第n个子终端设备的短地址分配:
Achild = Aparent + Rm*Cskip(d)+ n
ZigBee 2007 PRO 使用的随机地址分配机制,对新加入的节点使用随机地址分配,为保证网络内地址分配不重复,使用其余的随机地址再进行分配。当一个节点加入时,将接收到父节点的随机分配地址,然后产生“设备声明”(包含分配到的网络地址和IEEE地址)发送至网络中的其余节点。如果另一个节点有着同样的网络地址,则通过路由器广播“网络状态-地址冲突”至网络中的所有节点。所有发生网络地址冲突的节点更改自己的网络地址,然后再发起“设备声明”检测新的网络地址是否冲突。
终端设备不会广播“地址冲突”,他们的父节点会帮助完成。如果一个终端设备发生了“地址冲突”,他们的父节点发送“重新加入”消息至终端设备,并要求他们更改网络地址。然后,终端设备再发起“设备声明”检测新的网络地址是否冲突。
当接收到“设备声明”后,关联表和绑定表将被更新使用新的网咯地址,但是路由表不会被更新。
在每个路由加入网络之前,寻址方案需要知道和配臵一些参数。这些参数是MAX_DEPTH(最大网络深度)、MAX_ROUTERS(最多路由数)和MAX_CHILDREN(最多子节点数)。这些参数是栈配臵的一部分,ZigBee2007协议栈已经规定了这些参数的值:
#if ( STACK_PROFILE_ID == ZIGBEEPRO_PROFILE )
#define MAX_NODE_DEPTH 20
#elif ( STACK_PROFILE_ID == HOME_CONTROLS )
#define MAX_NODE_DEPTH 5
#elif ( STACK_PROFILE_ID == GENERIC_STAR )
#define MAX_NODE_DEPTH 5
#elif ( STACK_PROFILE_ID == NETWORK_SPECIFIC )
#define MAX_NODE_DEPTH 5
#endif
#define NWK_MAX_ROUTERS 6
#define NWK_MAX_DEVICES 21
MAX_DEPTH决定了网络的最大深度。协调器(Coordinator)位于深度0,它的儿子位于深度1,他的儿子的的儿子位于深度2,以此类推。MAX_DEPTH参数限制了网络在物理上的长度。
MAX_CHILDREN决定了一个路由(Router)或者一个协调器节点可以处理的儿子节点的最大个数。
MAX_ROUTER决定了一个路由(Router)或者一个协调器(Coordinator)节点可以处理的具有路由功能的儿子节点的最大个数。这个参数是MAX_CHILDREN的一个子集,终端节点使用(MAX_CHILDREN – MAX_ROUTER)剩下的地址空间。
本文中ZigBee网络示意图所示的MAX_DEPTH=3,MAX_CHILDREN=5,MAX_ROUTER=2。
如果开发人员想改变这些值,则需要完成以下几个步骤:
首先,你要保证这些参数新的赋值要合法。即,整个地址空间不能超过216,这就限制了参数能够设臵的最大值。可以使用projects\ZStack\tools文件夹下的CSkip.xls文件来确认这些值是否合法。当在表格中输入了这些数据后,如果你的数据不合法的话就会出现错误信息。
当选择了合法的数据后,开发人员还要保证不再使用标准的栈配臵,取而代之的是网络自定义栈配臵(例如:在nwk_globals.h文件中将STACK_PROFILE_ID改为NETWORK_SPECIFIC)。然后nwk_globals.h文件中的MAX_DEPTH参数将被设臵为合适的值。
此外,还必须设臵nwk_globals.c文件中的Cskipchldrn数组和CskipRtrs数组。这些数组的值由MAX_CHILDREN和MAX_ROUTER构成。
#if ( STACK_PROFILE_ID == ZIGBEEPRO_PROFILE )
uint8 CskipRtrs[1] = {0};
uint8 CskipChldrn[1] = {0};
#elif ( STACK_PROFILE_ID == HOME_CONTROLS )
uint8 CskipRtrs[MAX_NODE_DEPTH+1] = {6,6,6,6,6,0};
uint8 CskipChldrn[MAX_NODE_DEPTH+1] = {20,20,20,20,20,0};
#elif ( STACK_PROFILE_ID == GENERIC_STAR )
uint8 CskipRtrs[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
uint8 CskipChldrn[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
#elif ( STACK_PROFILE_ID == NETWORK_SPECIFIC )
uint8 CskipRtrs[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
uint8 CskipChldrn[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
#endif // STACK_PROFILE_ID
假设父设备可拥有的最大子设备数为Cm,其拥有的最大路由子设备数为 Rm,网络的最大深度为Lm,则父设备所能分配子区段地址数为:
若Rm=1,Cskip(d)= 1+Cm*(Lm-d-1);
若Rm不为1,则Cskip(d)=(1+Cm-Rm-Cm*( Rm)^(Lm-d-1))/(1-Rm).
子节点为父设备的第n个子路由器的短地址分配:
Achild =Aparent +(n-1)*Cskip(d)+1,n=1
Achild =Aparen +(n-1)*Cskip(d),n>1
子节点为父设备的第n个子终端设备的短地址分配:
Achild = Aparent + Rm*Cskip(d)+ n
ZigBee 2007 PRO 使用的随机地址分配机制,对新加入的节点使用随机地址分配,为保证网络内地址分配不重复,使用其余的随机地址再进行分配。当一个节点加入时,将接收到父节点的随机分配地址,然后产生“设备声明”(包含分配到的网络地址和IEEE地址)发送至网络中的其余节点。如果另一个节点有着同样的网络地址,则通过路由器广播“网络状态-地址冲突”至网络中的所有节点。所有发生网络地址冲突的节点更改自己的网络地址,然后再发起“设备声明”检测新的网络地址是否冲突。
终端设备不会广播“地址冲突”,他们的父节点会帮助完成。如果一个终端设备发生了“地址冲突”,他们的父节点发送“重新加入”消息至终端设备,并要求他们更改网络地址。然后,终端设备再发起“设备声明”检测新的网络地址是否冲突。
当接收到“设备声明”后,关联表和绑定表将被更新使用新的网咯地址,但是路由表不会被更新。
在每个路由加入网络之前,寻址方案需要知道和配臵一些参数。这些参数是MAX_DEPTH(最大网络深度)、MAX_ROUTERS(最多路由数)和MAX_CHILDREN(最多子节点数)。这些参数是栈配臵的一部分,ZigBee2007协议栈已经规定了这些参数的值:
#if ( STACK_PROFILE_ID == ZIGBEEPRO_PROFILE )
#define MAX_NODE_DEPTH 20
#elif ( STACK_PROFILE_ID == HOME_CONTROLS )
#define MAX_NODE_DEPTH 5
#elif ( STACK_PROFILE_ID == GENERIC_STAR )
#define MAX_NODE_DEPTH 5
#elif ( STACK_PROFILE_ID == NETWORK_SPECIFIC )
#define MAX_NODE_DEPTH 5
#endif
#define NWK_MAX_ROUTERS 6
#define NWK_MAX_DEVICES 21
MAX_DEPTH决定了网络的最大深度。协调器(Coordinator)位于深度0,它的儿子位于深度1,他的儿子的的儿子位于深度2,以此类推。MAX_DEPTH参数限制了网络在物理上的长度。
MAX_CHILDREN决定了一个路由(Router)或者一个协调器节点可以处理的儿子节点的最大个数。
MAX_ROUTER决定了一个路由(Router)或者一个协调器(Coordinator)节点可以处理的具有路由功能的儿子节点的最大个数。这个参数是MAX_CHILDREN的一个子集,终端节点使用(MAX_CHILDREN – MAX_ROUTER)剩下的地址空间。
本文中ZigBee网络示意图所示的MAX_DEPTH=3,MAX_CHILDREN=5,MAX_ROUTER=2。
如果开发人员想改变这些值,则需要完成以下几个步骤:
首先,你要保证这些参数新的赋值要合法。即,整个地址空间不能超过216,这就限制了参数能够设臵的最大值。可以使用projects\ZStack\tools文件夹下的CSkip.xls文件来确认这些值是否合法。当在表格中输入了这些数据后,如果你的数据不合法的话就会出现错误信息。
当选择了合法的数据后,开发人员还要保证不再使用标准的栈配臵,取而代之的是网络自定义栈配臵(例如:在nwk_globals.h文件中将STACK_PROFILE_ID改为NETWORK_SPECIFIC)。然后nwk_globals.h文件中的MAX_DEPTH参数将被设臵为合适的值。
此外,还必须设臵nwk_globals.c文件中的Cskipchldrn数组和CskipRtrs数组。这些数组的值由MAX_CHILDREN和MAX_ROUTER构成。
#if ( STACK_PROFILE_ID == ZIGBEEPRO_PROFILE )
uint8 CskipRtrs[1] = {0};
uint8 CskipChldrn[1] = {0};
#elif ( STACK_PROFILE_ID == HOME_CONTROLS )
uint8 CskipRtrs[MAX_NODE_DEPTH+1] = {6,6,6,6,6,0};
uint8 CskipChldrn[MAX_NODE_DEPTH+1] = {20,20,20,20,20,0};
#elif ( STACK_PROFILE_ID == GENERIC_STAR )
uint8 CskipRtrs[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
uint8 CskipChldrn[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
#elif ( STACK_PROFILE_ID == NETWORK_SPECIFIC )
uint8 CskipRtrs[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
uint8 CskipChldrn[MAX_NODE_DEPTH+1] = {5,5,5,5,5,0};
#endif // STACK_PROFILE_ID