ZigBee快速入门
2. ZigBee2.1 设备类型(Device Types)在ZigBee 网络中存在三种逻辑设备类型:Coordinator(协调器) ,Router(路由器) 和End-Device(终端设备)
2. ZigBee
2.1 设备类型(Device Types)
在ZigBee 网络中存在三种逻辑设备类型:Coordinator(协调器) ,Router(路由器) 和End-Device(终端设备) 。ZigBee 网络由一个Coordinator 以及多个Router 和多个End_Device组成。
上图是一个简单的ZigBee 网络示意图。其中黑色节点为Coordinator ,红色节点为Router ,白色节点为End-Device 。
2.1.1 Coordinator(协调器)
协调器负责启动整个网络。它也是网络的第一个设备。协调器选择一个信道和一个网络ID(也称之为PAN ID ,即Personal Area Network ID) ,随后启动整个网络。
协调器也可以用来协助建立网络中安全层和应用层的绑定(bindings)。
注意,协调器的角色主要涉及网络的启动和配置。一旦这些都完成后,协调器的工作就像一个路由器(或者消失go away) 。由于ZigBee 网络本身的分布特性,因此接下来整个网络的操作就不在依赖协调器是否存在。
2.1.2 Router(路由器)
路由器的功能主要是:允许其他设备加入网络,多跳路由和协助它自己的由电池供电的儿子终端设备的通讯。
通常,路由器希望是一直处于活动状态,因此它必须使用主电源供电。但是当使用树群这种网络模式时,允许路由间隔一定的周期操作一次,这样就可以使用电池给其供电。
2.1.3 End-Device(终端设备)
终端设备没有特定的维持网络结构的责任,它可以睡眠或者唤醒,因此它可以可以是一个电池供电设备。
通常,终端设备对存储空间(特别是RAM 的需要) 比较小。
注意:在Z-Stack 1.4.1中一个设备的类型通常在编译的时候通过编译选项(ZDO_COORDINATOR 和RTR_NWK)确定。所有的应用例子都提供独立的项目文件来编译每一种设备类型。
2.2 栈配置(Stack Profile)
栈参数的集合需要被配置为一定的值,连同这些值在一起被称之为栈配置。ZigBee 联盟定义了这些由栈配置组成的栈参数。
网络中的所有设备必须遵循同样的栈配置。
,为了促进互用性这个目标,ZigBee 联盟为ZigBee2006规范定义了栈配置。所有遵循此栈配置的设备可以在其他开发商开发的遵循同样栈配置的网络中。
3. 寻址(Addressing)
3.1 地址类型(Address types)
ZigBee 设备有两种类型的地址。一种是64位IEEE 地址,即MAC 地址,另一种是16位网络地址。 64位地址使全球唯一的地址,设备将在它的生命周期中一直拥有它。它通常由制造商或者被安装时设置。这些地址由IEEE 来维护和分配。
16为网络地址是当设备加入网络后分配的。它在网络中是唯一的,用来在网络中鉴别设备和发送数据。
3.2 网络地址分配(Network address assignment)
ZigBee 使用分布式寻址方案来分配网络地址。这个方案保证在整个网络中所有分配的地址是唯一的。这一点是必须的,因为这样才能保证一个特定的数据包能够发给它指定的设备,而不出现混乱。同时,这个寻址算法本身的分布特性保证设备只能与他的父辈设备通讯来接受一个网络地址。不需要整个网络范围内通讯的地址分配,这有助于网络的可测量性。
在每个路由加入网络之前,寻址方案需要知道和配置一些参数。这些参数是MAX_DEPTH,MAX_ROUTERS 和MAX_CHILDREN。这些参数是栈配置的一部分,ZigBee2006协议栈已经规定了这些参数的值:MAX_DEPTH = 5,MAX_ROUTERS = 6和MAX_CHILDREN = 20。
MAX_DEPTH决定了网络的最大深度。协调器(Coordinator)位于深度0,它的儿子位于深度1,他的儿子的的儿子位于深度2,以此类推。MAX_DEPTH参数限制了网络在物理上的长度。
MAX_CHILDREN决定了一个路由(Router)或者一个协调器节点可以处理的儿子节点的最大个数。 MAX_ROUTER决定了一个路由(Router)或者一个协调器(Coordinator)节点可以处理的具有路由功能的儿子节点的最大个数。这个参数是MAX_CHILDREN的一个子集,终端节点使用(MAX_CHILDREN – MAX_ROUTER)剩下的地址空间。
如果开发人员想改变这些值,则需要完成以下几个步骤:
首先,你要保证这些参数新的赋值要合法。即,整个地址空间不能超过216,这就限制了参数能够设置的最大值。可以使用projectsZStacktools文件夹下的CSkip.xls 文件来确认这些值是否合法。当在表格中输入了这些数据后,如果你的数据不合法的话就会出现错误信息。
当选择了合法的数据后,开发人员还要保证不再使用标准的栈配置,取而代之的是网络自定义栈配置(例如:在nwk_globals.h文件中将STACK_PROFILE_ID改为NETWORK_SPECIFIC)。然后nwk_globals.h 文件中的MAX_DEPTH参数将被设置为合适的值。
,此外,还必须设置nwk_globals.c文件中的Cskipchldrn 数组和CskipRtrs 数组。这些数组的值由MAX _CHILDREN和MAX_ROUTER构成。
3.3 Z-Stack 寻址(Addressing in z-stack)
为了向一个在ZigBee 网络中的设备发送数据,应用程序通常使用AF_DataRequest()函数。数据包将要发送给一个afAddrType_t(在ZComDef.h 中定义) 类型的目标设备。
typedef struct
{
union
{
uint16 shortAddr;
} addr;
afAddrMode_t addrMode;
byte endPoint;
} afAddrType_t;
注意,除了网路地址之外,还要指定地址模式参数。目的地址模式可以设置为以下几个值:
typedef enum
{
afAddrNotPresent = AddrNotPresent,
afAddr16Bit = Addr16Bit,
afAddrGroup = AddrGroup,
afAddrBroadcast = AddrBroadcast
} afAddrMode_t;
因为在Zigbee 中,数据包可以单点传送(unicast),多点传送(multicast)或者广播传送,所以必须有地址模式参数。一个单点传送数据包只发送给一个设备,多点传送数据包则要传送给一组设备,而广播数据包则要发送给整个网络的所有节点。这个将在下面详细解释。
3.3.1 单点传送(Unicast)
,Uicast 是标准寻址模式,它将数据包发送给一个已经知道网络地址的网络设备。将afAddrMode 设置为Addr16Bit 并且在数据包中携带目标设备地址。
3.3.2 间接传送(Indirect)
当应用程序不知道数据包的目标设备在哪里的时候使用的模式。将模式设置为AddrNotPresent 并且目标地址没有指定。取代它的是从发送设备的栈的绑定表中查找目标设备。这种特点称之为源绑定。
当数据向下发送到达栈中,从绑定表中查找并且使用该目标地址。这样,数据包将被处理成为一个标准的单点传送数据包。如果在绑定表中找到多个设备,则向每个设备都发送一个数据包的拷贝。
上一个版本的ZigBee(ZigBee04),有一个选项可以讲绑定表保存在协调器(Coordinator)当中。发送设备将数据包发送给协调器,协调器查找它栈中的绑定表,然后将数据发送给最终的目标设备。这个附加的特性叫做协调器绑定(Coordinator Binding) 。
3.3.3 广播传送(broadcast)
当应用程序需要将数据包发送给网络的每一个设备时,使用这种模式。地址模式设置为AddrBroadca st 。目标地址可以设置为下面广播地址的一种:
NWK_BROADCAST_SHORTADDR_DEVALL(0xFFFF)——数据包将被传送到网络上的所有设备,包括睡眠中的设备。对于睡眠中的设备,数据包将被保留在其父亲节点直到查询到它,或者消息超时(NWK_INDIRECT_MSG_TIMEOUT在f8wConifg.cfg 中) 。
NWK_BROADCAST_SHORTADDR_DEVRXON(0xFFFD)——数据包将被传送到网络上的所有在空闲时打开接收的设备(RXONWHENIDLE),也就是说,除了睡眠中的所有设备。
NWK_BROADCAST_SHORTADDR_DEVZCZR(0xFFFC)——数据包发送给所有的路由器,包括协调器。
3.3.4 组寻址(Group Addressing)
当应用程序需要将数据包发送给网络上的一组设备时,使用该模式。地址模式设置为afAddrGroup 并且addr.shortAddr 设置为组ID 。
在使用这个功能呢之前,必须在网络中定义组。(参见Z-stack API 文档中的aps_AddGroup()函数) 。 注意组可以用来关联间接寻址。再绑定表中找到的目标地址可能是是单点传送或者是一个组地址。另外,广播发送可以看做是一个组寻址的特例。
下面的代码是一个设备怎样加入到一个ID 为1的组当中:
aps_Group_t group;
// Assign yourself to group 1
,group.ID = 0x0001;
group.name[0] = 0; // This could be a human readable string
aps_AddGroup( SAMPLEAPP_ENDPOINT, &group );
3.4 重要设备地址(Important Device Adresses)
应用程序可能需要知道它的设备地址和父亲地址。使用下面的函数获取设备地址(在ZStack API 中定义) :
l NLME_GetShortAddr()——返回本设备的16位网络地址
l NLME_GetExtAddr()—— 返回本设备的64位扩展地址
使用下面的函数获取该设备的父亲设备的地址:
l NLME_GetCoordShortAddr()——返回本设备的父亲设备的16位网络地址
l NLME_GetCoordExtAddr()—— 返回本设备的父亲设备的64位扩展地址
4. 绑定(Binding)
绑定是一种两个(或者多个) 应用设备之间信息流的控制机制。在ZigBee2006发布版本中,它被称为资源绑定,所有的设备都必须执行绑定机制。
绑定允许应用程序发送一个数据包而不需要知道目标地址。APS 层从它的绑定表中确定目标地址,然后将数据继续向目标应用或者目标组发送。
注意:在ZigBee 的1.0版本中,绑定表是保存在协调器(Coordinator当中) 。现在所有的绑定记录都保存在发送信息的设备当中。
4.1 建立绑定表(Building a Binding Table)
有三种方法可以建立一个绑定表:
l Zigbee Device Object Bind Request ——一个启动工具可以告诉设备创建一个绑定记录
l Zigbee Device Object End Device Bind Request ——两个设备可以告诉协调器它们想要建立一个绑定表记录。协调器来协调并在两个设备中创建绑定表记录。
l Device Application ——一个设备上的应用程序建立或者管理一个绑定表
4.1.1 ZigBee Device Object Binding Request
,任何一个设备都可以发送一个ZDO 信息给网络中的另一个设备,用来建立绑定表。称之为援助绑定,它可以为一个发送设备创建一个绑定记录。
4.1.1.1 启动申请(The Commissioning Application)
一个应用程序可以通过ZDP_BindReq()函数(在ZDProfile.h) ,并在绑定表中包含两个请求(地址和终点) 以及想要的群ID 。第一个参数(目标dstAddr) 是绑定源的短地址即,16位网络地址。
确定你已经在ZDConfig.h 允许了这个功能(ZDO_BIND_UNBIND_REQUEST)。
你也可以使用ZDP_UnbindReq()用同样的参数取消绑定记录。
目标设备发回ZigBee Device Object Bind 或者Unbind Response 信息,该信息是ZDO 代码根据动作的状态,通过调用ZDApp_BindRsq()或者ZDApp_UnbindRsq()函数来分析和通知ZDApp.c 的。
对于绑定响应,从协调器返回的状态将是ZDP_SUCCESS,ZDP_TABLE_FULL或者ZDP_NOT_SUPPORTED 。
对于解除绑定响应,从协调器返回的状态将是ZDP_SUCCESS,ZDP_NO_ENTRY或者ZDP_NOT_SUPPORTED 。
4.1.1.2 ZigBee Device Object End Device Bind Request
这个机制是在指定的时间周期(timeout period) 内,通过按下选定设备上的按钮或者类似的动作来绑定。协调器在指定的时间周期内,搜集终端设备的绑定请求信息,然后以配置ID(Profile ID) 和群ID(Cluster I
D) 协议为基础,创建一个绑定表记录作为结果。默认的设备绑定时间周期(APS_DEFAULT_MAXBINDING_TIME)是16秒钟(在nwk_globals.h中定义) 。但是将它添加到f8wConfig.cfg 中,则可以更改。
在―用户指南‖中的应用程序就是一个终端设备绑定的例子(在每个设备上按下SW2按键) 。
你应该注意到,所有的例程都有处理关键事件的函数(例如:在TransmitApp.c 中的TransmitApp_HandleKeys()函数) 。这个函数调用ZDApp_SendEndDeviceBindReq()(在ZDApp.c 中) 。这个函数搜集所有终端节点的请求信息,然后调用ZDP_EndDeviceBindReq()函数将这些信息发送给协调器。
协调器调用函数ZDP_IncomingData()【ZDProfile.c 中】函数接收这些信息,然后再调用ZDApp_ProcessEndDeviceBindReq ()【ZDObject.c 中】函数分析这些信息,最后调用ZDApp_EndDeviceBindReqCB【Z DApp.c 中】函数,这个函数再调用ZDO_MatchEndDeviceBind()【ZDObject.c 中】函数来处理这个请求。
当收到两个匹配的终端设备绑定请求,协调器在请求设备中启动创建源绑定记录的进程。假设在ZD O 终端设备中发现了匹配的请求,协调器将执行下面的步骤:
l 发送一个解除绑定请求给第一个设备。这个终端设备锁定进程,这样解除绑定被首先发送来去掉一个已经存在的绑定记录。
l 等待ZDO 解除绑定的响应,如果响应的状态是ZDP_NO_ENTRY,则发送一个ZDO 绑定请求在源设备中创建一个绑定记录。如果状态是ZDP_SUCCESS,则继续前进到第一个设备的群ID 。
,l 等待ZDO 绑定响应,如果收到了,则继续前进到第一个设备的下一个群ID 。
l 当地一个设备完成后,用同样的方法处理第二个设备。
l 当第二个设备也完成之后,发送ZDO 终端设备绑定请求消息给两个设备。
4.1.1.3 Device Application Binding Manager
另一种进入设备绑定记录的方式是应用自己管理绑定表。这就意味着应用程序需要通过调用下面的绑定管理函数在本地进入并且删除绑定记录:
l bindAddEntry()——在绑定表中增加一个记录
l bindRemoveEntry()——从绑定表中删除一个记录
l bindRomoveClusterIdFromList()——从一个存在的绑定表记录中删除一个群ID
l bindAddClusterIdToList()——向一个已经存在的绑定记录中增加一个群ID
l bindRemoveDev()——删除所有地址引用的记录
l bindRemoveSrcDev()——删除所有源地址引用的记录
l bindUpdateAddr()——将记录更新为另一个地址
l bindFindExisting()——查找一个绑定表记录
l bindIsClusterIdInList()——在表记录中检查一个已经存在的群ID
l bindNumBoundTo()——拥有相同地址(源或者目的) 的记录的个数
l bindNumEntries()——表中记录的个数
l bindCapacity()——最多允许的记录个数
l bindWriteNV()——在NV 中更新表
4.1.2 配置源绑定(Configuring Source Binding)
为了在你的设备中使能源绑定在f8wConfig.cfg 文件中包含REFLECTOR 编译标志。同时在f8wConf ig.cfg 文件中查看配置项目NWK_MAX_BINDING_ENTRIES和MAX_BINDING_CLUSTER_IDS。NWK_MAX_BINDING_ENTRIES是限制绑定表中的记录的最大个数,MAX_BINDING_CLUSTER_IDS是每个绑定记录的群ID 的最大个数。
,绑定表在静态RAM 中(未分配) ,因此绑定表中记录的个数,每条记录中群ID 的个数都实际影响着使用RAM 的数量。每一条绑定记录是8字节多(MAX_BINDING_CLUSTER_IDS * 2字节) 。除了绑定表使用的静态RAM 的数量,绑定配置项目也影响地址管理器中的记录的个数。
5. 路由(Routing)
5.1 概述(Overview)
A mesh network is described as a network in which the routing of messages is performed as a de centralized ,cooperative process involving many peer devices routing on each others’ behalf.
路由对与应用层来说是完全透明的。应用程序只需简单的向下发送去往任何设备的数据到栈中,栈会负责寻找路径。这种方法,应用程序不知道操作是在一个多跳的网络当中的。
路由还能够自愈ZigBee 网络,如果某个无线连接断开了,路由功能又能自动寻找一条新的路径避开那个断开的网络连接。这就极大的提高了网络的可靠性,同时也是ZigBee 网络的一个关键特性。
5.2 路由协议(Routing Protocol)
ZigBee 执行基于用于AODV 专用网络的路由协议。简化后用于传感器网络。ZigBee 路由协议有助于网络环境有能力支持移动节点,连接失败和数据包丢失。
当路由器从他自身的应用程序或者别的设备那里收到一个单点发送的数据包,则网络层(NWK Layer) 根据一下程序将它继续传递下去。如果目标节点是它相邻路由器中的一个,则数据包直接被传送给目标设备。否则,路由器将要检索它的路由表中与所要传送的数据包的目标地址相符合的记录。如果存在与目标地址相符合的活动路由记录,则数据包将被发送到存储在记录中的下一级地址中去。如果没有发现任何相关的路由记录,则路由器发起路径寻找,数据包存储在缓冲区中知道路径寻找结束。
ZigBee 终端节点不执行任何路由功能。终端节点要向任何一个设备传送数据包,它只需简单的将数据向上发送给它的父亲设备,由它的父亲设备以它自己的名义执行路由。同样的,任何一个设备要给终端节点发送数据,发起路由寻找,终端节的的父亲节点都已它的名义来回应。
注意ZigBee 地址分配方案使得对于任何一个目标设备,根据它的地址都可以得到一条路径。在Z-St ack 中,如果万一正常的路径寻找过程不能启动的话(通常由于缺少路由表空间) ,那么Z-Stack 拥有自动回退机制。
此外,在Z-Stack 中,执行的路由已经优化了路由表记录。通常,每一个目标设备都需要一条路由表记录。但是,通过把一定父亲节点记录与其子所有子结点的记录合并,这样既可以优化路径也可以不丧失任何功能。
ZigBee 路由器,包括协调器执行下面的路由函数:(i)路径发现和选择;(ii)路径保持维护;(iii)路径期满。
5.2.1 路径的发现和选择(Route Discovery and Selection)
,路径发现是网络设备凭借网络相互协作发现和建立路径的一个过程。路由发现可以由任意一个路由设备发起,并且对于某个特定的目标设备一直执行。路径发现机制寻找源地址和目标地址之间的所有路径,并且试图选择可能的最好的路径。
路径选择就是选择出可能的最小成本的路径。每一个结点通常持有跟它所有邻接点的―连接成本(link cost s)‖。通常,连接成本的典型函数是接收到的信号的强度。沿着路径,求出所有连接的连接成本总和,便可以得到整个路径的―路径成本‖。路由算法试图寻找到拥有最小路径成本的路径。
路径通过一系列的请求和回复数据包被发现。源设备通过向它的所有邻接节点广播一个路由请求数据包,来请求一个目标地址的路径。当一个节点接收到RREQ 数据包,它依次转发RREQ 数据包。但是在转发之前,它要加上最新的连接成本,然后更新RREQ 数据包中的成本值。这样,沿着所有它通过的连接,RREQ 数据包携带着连接成本的总和。这个过程一直持续到RREQ 数据包到达目标设备。通过不同的路由器,许多RREQ 副本都将到达目标设备。目标设备选择最好的RREQ 数据包,然后发回一个路径答复数据包(a Route Reply)RREP 给源设备。
RREP 数据包是一个单点发送数据包,它沿着中间节点的相反路径传送直到它到达原来发送请求的节点为止。
一旦一条路径被创建,数据包就可以发送了。当一个结点与它的下一级相邻节点失去了连接(当它发送数据时,没有收到MAC ACK) ,该节点向所有等待接收它的RREQ 数据包的节点发送一个RERR 数据包,将它的路径设为无效。各个结点根据收到的数据包RREQ 、RREP 或者RERR 来更新它的路由表。
5.2.2 路径保持维护(Route maintenance)
网状网提供路径维护和网络自愈功能。中间节点沿着连接跟踪传送失败,如果一个连接被认定是坏链,那么上游节点将针对所有使用这条连接的路径启动路径修复。节点发起重新发现直到下一次数据包到达该节点,标志路径修复完成。如果不能够启动路径发现或者由于某种原因失败了,节点则向数据包的源节点发送一个路径错误包(RERR),它将负责启动新路径的发现。这两种方法,路径都自动重建。
5.2.3 路径期满(Route expiry)
路由表为已经建立连接路径的节点维护路径记录。如果在一定的时间周期内,没有数据通过沿着这条路径发送,这条路径将被表示为期满。期满的路径一直保留到它所占用的空间要被使用为止。这样,路径在绝对不使用之前不会被删除掉的。在配置文件f8wConfig.cfg 文件中配置自动路径期满时间。设置RO UTE_EXPIRY_TIME为期满时间,单位为秒。如果设置为0,则表示关闭自动期满功能。
5.3 表存储(Table storage)
路由功能需要路由器保持维护一些表格。
5.3.1 路由表(Routing table)
每一个路由器包括协调器都包含一个路由表。设备在路由表中保存数据包参与路由所需的信息。每一条路由表记录都包含有目的地址,下一级节点和连接状态。所有的数据包都通过相邻的一级节点发送到目的地址。同样,为了回收路由表空间,可以终止路由表中的那些已经无用的路径记录。
,路由表的容量表明一个设备路由表拥有一个自由路由表记录或者说它已经有一个与目标地址相关的路由表记录。在文件―f8wConfig.cfg‖文件中配置路由表的大小。将MAX_RTG_ENTRIES设置为表的大小(不能小于4) 。
5.3.2 路径发现表(Route discovery table)
路由器设备致力于路径发现,保持维护路径发现表。这个表用来保存路径发现过程中的临时信息。这些记录只在路径发现操作期间存在。一旦某个记录到期,则它可以被另一个路径发现使用。这个值决定了在一个网络中,可以同时并发执行的路径发现的最大个数。这个可以在f8wConfig.cfg 文件中配置MAX_ RREQ_ENTRIES。
5.4 路径设置快速参考(Routing Settings Quick reference)

6. ZDO 消息请求(ZDO Message requests)
ZDO 模块提供功能用来发送ZDO 服务发现请求消息,接收ZDO 服务发现回复消息。下图描述了应用程序发送IEEE 地址请求和接收IEEE 地址回复的函数调用。
ZDO IEEE 地址请求及应答
下面这个例子,一个应用程序想知道什么时候一个新的设备加入网络。一个应用想要接收所有ZDO 设备的通知信息。
ZDO Device Announce delivered to an application
7. 便携式设备(Portable Devices)
在ZigBee2006中终端节点就是便携式的设备。这就意味着当一个终端节点没有侦听到它的父节点回应(超出范围或者无法胜任) ,它将试着重新加入网络(加入到另一个新的父亲节点) 。没有设置或者编译标志位来设置这个选项。
终端节点通过巡检(MAC 数据请求) 失败或者通过数据消息失败侦听它的父亲节点都没有回应。MAX _POLL_FAILURE_RETRIES用来控制失败的敏感度。这个值可以在f8wConfig.cfg 文件中修改。并且,这个值越大敏感度就越低,重新加入网络需要的时间就更长。
当网络层侦测到它的父亲节点没有回应,它将调用ZDO_SynIndicationCB()函数,这个函数将启动重新加入。重新加入过程首先对已有的父亲节点进行孤儿扫描(orphan-scan),然后扫描潜在的父亲节点并且跟它的潜在父节点加入网络。