ZigBee网络管理主要分为以下几个部分:
- 如何查看节点的网络地址
- 如何查看节点的父节点的网络地址
- 如何通过节点的网络地址得到节点的MAC地址
- 如何通过节点的MAC地址查询节点的网络地址
- 如何获得网络的拓扑结构
1、ZigBee网络中的设备地址
在讲述ZigBee网络中的地址类型之前,需要了解一下ZigBee网络中设备类型,在ZigBee无线网络中,主要有三种类型的设备,设备类型的选择是在编译时根据不同的编译选项来确定的。
- 协调器(Coordinator)
协调器负责建立网络,系统上电后,协调器会自动选择一个信道,然后选择一个网络号,建立网络。协调器主要是在网络建立、网络配置方面起作用,一旦网络建立了,协调器就与路由器的功能是一致的。
- 路由器(Router)
在ZigBee网络中,路由器主要有三个功能:
- 允许节点加入网络
- 进行数据的路由
- 辅助其子节点通信
如果一个节点是通过路由加入网络,该节点就称为该路由器的子节点的 (child node)。
- 终端节点(End-device)
终端节点只需要加入已建立的网络即可,终端节点不具有网络维护功能。
注意:设备类型在ZigBee协议栈中是通过参数来指定的,例如:ZDO_COORDINATOR表示设备类型为协调器,RTR_NWK表示设备类型为路由器。
- 设备地址
在网络中进行通信,需要标识每个设备的地址,在ZigBee无线网络中,设备地址有以下两种:
①64-bit的IEEE地址 (64-bit IEEE address)IEEE地址是64位的,并且是全球唯一的,每个CC2530单片机的IEEE地址在出厂时就已经定义好了(当然,在用户学习阶段,可以通过编程软件SmartRF Flash Programmer修改设备的IEEE地址)。64位的IEEE地址又被称为MAC地址(MAC address)或扩展地址(Extended address).
②16-bit的网络地址 (16-bit network address)网络地址是16位的,该地址是在设备加入网络时,按照一定的算法计算得到并分配给加入网络的设备。网络地址在某个网络中是唯一的,16位的网络地址主要有两个功能:在网络中标识不同的设备;在网络数据传输时指定目的地址和源地址。16位的IEEE地址又被称为逻辑地址(Logical Address)或短地址(Short Address)。
2、ZigBee无线网路中的地址分配机制
ZigBee无线网络中的地址分配机制为分布式分配机制(Distributed Addressing Scheme)。
在ZigBee无线网络中,协调器(Coordinator)在建立网络以后使用0x0000作为自己的网络地址(即协调器的默认网络地址是0x0000)。在路由器 (Router)和终端(Enddevice)加入网络以后,父设备会自动给它分配16位的网络地址。
网络地址是16位的,因此最多可以分配给65536个节点,地址的分配取决于整个网络的架构,整个网络的架构由以下3个值决定:
- 网络的最大深度(Lm)
- 每个父节点拥有的节点最大数目(Cm)
- 每个父节点拥有的子节点中路由器的最大数目(Rm)
可以根据下面的公式来计算某父节点的路由器子设备之间的地址间隔Cskip(d):
根据上述公式,可以推算:
父节点分配的第1个路由器地址=父亲设备地址 + 1;
父节点分配的第2个路由器地址= 父亲设备地址 + 1 + Cskip(d);
父节点分配的第3个路由器地址=父亲设备地址 + 1 + 2xCskip(d);
..............................
父节点分配的第n个路由器地址=父亲设备地址 + 1 + (n-1)xCskip(d);
依次运算规则可以很容易地计算出网络中各个设备的节点地址。所以得到终端节点的网络地址计算公式如下:
下面结合一个具体的例子来熟悉一下ZigBee网络节点地址的计算过程。假设在一个ZigBee无线网络,网络拓扑结构图如图所示,下面给出每个设备网络地址的计算过程:
由图可知,网络的最大深度为Lm=3,每个父节点拥有的子节点最大数目Cm=5,每个父节点拥有的孩子节点中路由器的最大数目Rm=3。
对于协调器而言,路由器子设备之间的地址间隔Cskip(d=0)计算公式如下:
因此,与协调器相连的3个路由器的网络地址计算公式如下:
路由器1的网络地 = 协调器网络地址 + 1
= 0x0000 + 1
= 0x0001
路由器2的网络地址 = 协调器网络地址+1+Csikp(d)
= 0x0000+1+21
= 0x0016
路由器3的网络地址 = 协调器网络地址 + 1 + 2*Cskip(d)
= 0x0000 + 1 + 2*21
= 0x002B
终端节点的网络地址需要使用下面的公式:
因此,与路由器相连的2个终端节点的网络地址计算公式如下:
对于路由器1而言,路由器子设备之间的地址间隔Cskip(d=1)计算公式如下:
因此,与协调器相连的3个路由器的网络地址计算公式如下:
路由器4的网络地址=协调器网络地址+1
=0x0001+1
=0x0002
路由器5的网络地址=协调器网络地址+1+Cskip(d=1)
=0x0001+1+6
=0x0008
路由器6的网络地址=协调器网络地址+1+2*Cskip(d=1)
=0x0001+1+2*6
=0x000E
终端节点的网络地址需要使用下面的公式:
因此,与路由器l相连的2个终端节点的网络地址计算公式如下:
通过上面的分析可知,对于ZigBee无线网络,只要Lm、Cm、Am这3个值确定了,整个网络设备的地址就可以计算出来。也可以看出来,同一个父节点相连的终端节点的网络地址是连续的,但是同一个父节点相连的路由器节点的网络地址通常是不连续的。
上面的地址分配过程分析只是为了理解ZigBee协议的地址分配机制,这部分内容在ZigBee协议栈里面已经实现了,我们不必关心地址分配问题,只需要使用分配好的地址进行网络通信即可。
在ZigBee协议栈里面,提供了三个参数MAX_DEPTH、MAX_ROUTERS和MAX_CHILDREN分别对应于上面分析中的Lm、 Rm和Cm。
修改广播发送函数,让其可以根据自己设备的类型,将自己设备的编号发送至协调器,如下:
void SampleApp_SendPeriodicMessage( void )
{
uint8 device = 0;
if(SampleApp_NwkState == DEV_ROUTER)
{
device = 1; // 表示路由器
}
else if(SampleApp_NwkState == DEV_END_DEVICE)
{
device = 2; // 表示终端
}
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID, // 数据类型ID 现在为表示广播
1, // 发送数据长度
(uint8*)&device, // 发送数据的地址 变量值为0
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
当设备加入网络,我们开启定时器,周期性广播发送,如下:
定时发送开启之后,会周期性触发SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件,而这个事件处理时,会调用广播发送,如下:
定时的周期由参数SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT设置,现在设置其值为1000,也就是定时周期为1秒。
在数据接收时,产生无线接收事件,然后会调用SampleApp_MessageMSGCB()对数据进行处理,如图:
函数SampleApp_MessageMSGCB()对接收到的数据进行判断,区分路由器和终端设备。然后在数据包中取出 16 位短地址。通过串口打印出来,代码如下:
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
uint8 i,len;
uint16 addr;
char buf[20];
switch ( pkt->clusterId )
{
case SAMPLEAPP_SERIAL_CLUSTERID: // 判断为串口数据
len = pkt->cmd.Data[0];
for(i=0;i<len;i++)
{
HalUARTWrite(0,&pkt->cmd.Data[i+1],1);
}
break;
case SAMPLEAPP_PERIODIC_CLUSTERID: // 判断为广播数据
addr = pkt->srcAddr.addr.shortAddr; // 读出数据包的16位短地址
if(pkt->cmd.Data[0] == 1)
{
HalUARTWrite(0,"ROUTER ShortAddr:0x",19); // 打印设备类型 路由
}
else if(pkt->cmd.Data[0] == 2)
{
HalUARTWrite(0,"ENDDEVICE ShortAddr:0x",22); // 打印设备类型 终端
}
sprintf(buf,"%X\n",addr); // 将16位短地址转为字符串
HalUARTWrite(0,buf,6); // 打印短地址字符串
break;
case SAMPLEAPP_FLASH_CLUSTERID:
flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );
HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );
break;
}
}
将修改后的程序分别以协调器、路由器、终端的方式下载到3个或以上设备,协调器连接到 PC 机。上电后每个设备往协调器发送自身编号,协调器通过串口打印出来,如图: