当前位置:首页 > 物联网学习笔记 > 正文

zigbee(zstack)几种绑定方式的程序实现及应用举例

一:Zigbee 绑定的四种方式及其程序代码实现:

1、 两个节点分别通过按键机制调用 ZDP_EndDeviceBindReq 函数即:在一定时间内两个节点都通过按键(其他方式也可以)触发调用这个函数特点:这个函数的调用将会向协调器发出绑定请求(具体如何调用及参数设置请看协议栈相关代码),如果在 16S(协议栈默认)时间内两个节点都执行了这个函数,协调器就会帮忙实现绑定, 这个过程的代码很复杂, 我不想说。 绑定表应该是存在 OutCluster 那边,即这两个节点应该是一个输出控制命令,一个接收控制命令,绑定表存在输出控制命令这边,至于如何实现,有兴趣同学可以继续研究代码。
注意:这种方式一定需要协调器,否则不行;但是一旦绑定成功,不再需要协调器,协调器只是帮忙绑定的一个第三方; 虽然叫做 EndDeviceBind,但是不局限于 End Device,路由器也一样用;重复上述操作会解绑定,也就是说这是一个乒乓方式。首先要在初始化程序中注册End_Device_Bind_rsp进程,然后按键绑定请求程序如下:

if(Up_down_mark==1)
{
Up_down_mark=0;
HalLedSet ( HAL_LED_2, HAL_LED_MODE_ON );
// Initiate an End Device Bind Request for the mandatory endpoint
dstAddr.addrMode = Addr16Bit;
dstAddr.addr.shortAddr = 0x0000; // Coordinator
ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(),
ZG_Serial_Control_epDesc.endPoint,
ZG_Serial_Control_PROFID,
ZG_Serial_Control_MAX_CLUSTERS, (cId_t *)ZG_Serial_Control_ClusterList,
ZG_Serial_Control_MAX_CLUSTERS, (cId_t *)ZG_Serial_Control_ClusterList,
FALSE );

}

回调处理函数如下:

case End_Device_Bind_rsp:
if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
{
HalLedSet ( HAL_LED_2, HAL_LED_MODE_OFF );
}
break;

2、 Match 方式
即:一个节点可以通过调用 afSetMatch 函数允许或禁止本节点被 Match(协议栈默认允许,可以手工关闭),然后另外一个节点在一定的时间内发起 ZDP_MatchDescReq 请求,允许被 Match 的节点会响应这个 Req,发起的节点在接收到 RSP 的时候就会自动处理绑定。特点:不需要别人帮忙,只要在网络中的节点互相之间就可以实现,但是前提是他们一定要 Match,即一方的 outcluster 至少有一个是另外一方的 incluster,这种方式在很多时候用起来比较方便。
注意:如果同时有多个节点(一个节点上的多个端点也一样)处于允许 Match 状态,那么req 的这个节点可能会收到一大票满足 Match 条件的 rsp, 那么你发起 req 的节点要在这个处理上多下功夫了。首先在初始化函数中注册Match_Desc_rsp进程,然后按键请求函数如下:

if(Right_left_mark==1)
{
Right_left_mark=0;
HalLedSet ( HAL_LED_2, HAL_LED_MODE_ON );
// Initiate a Match Description Request (Service Discovery)
dstAddr.addrMode = AddrBroadcast;
dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR,
ZG_Serial_Control_PROFID,
ZG_Serial_Control_MAX_CLUSTERS, (cId_t *)ZG_Serial_Control_ClusterList,
ZG_Serial_Control_MAX_CLUSTERS, (cId_t *)ZG_Serial_Control_ClusterList,
FALSE );
}

回调处理函数如下:

case Match_Desc_rsp:
{
ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
if ( pRsp )
{
if ( pRsp->status == ZSuccess && pRsp->cnt )
{
ZG_Serial_Control_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
ZG_Serial_Control_DstAddr.addr.shortAddr = pRsp->nwkAddr;
// Take the first endpoint, Can be changed to search through endpoints
ZG_Serial_Control_DstAddr.endPoint = pRsp->epList[0];

// Light LED
HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF );
}
osal_mem_free( pRsp );
}
}
break;

3、 ZDP_BindReq 和 ZDP_UnbindReq 方式即:应用程序通过调用这两个函数实现绑定和解绑定,这种方式很有趣。具体说来是为了让 A 和 B 绑定到一起,还需要一个节点 C。例如:你想 A 控制 B,那么这种方式是由 C 发出 bind 或 unbind 命令给 A(发给谁谁就处理绑定、并负责存储绑定表), A 在接收到 req 的时候直接处理绑定,也就是添加绑定表项,并且这个过程 B 并不知道。但是A 知道绑定表里面有了关于控制 B 的记录,并且这种方式可以实现一个节点绑定到一个 Group 上去。
注意:这种方式需要知道 A 和 B 的长地址,具体协议栈拿长地址做什么用,有兴趣的就去挖代码好了。首先需要注册Bind_rsp/Unbind_rsp,然后绑定请求函数如下:
destAddr.addrMode = Addr16Bit;
destAddr.addr.shortAddr = BUILD_UINT16( Uart_buf[1], Uart_buf[2] ); //目标设备网络地址
osal_cpyExtAddr(Bind_SourceAddr,&Uart_buf[3]);

devAddr.addrMode = Addr64Bit;
osal_cpyExtAddr( devAddr.addr.extAddr, &Uart_buf[11] );

ZDP_BindReq( &destAddr,
Bind_SourceAddr,
ZG_Serial_Control_ENDPOINT,
ZG_Serial_Control_CLUSTERID,
&devAddr,
ZG_Serial_Control_ENDPOINT,
0 );
回调处理函数如下:
if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )//绑定成功
HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF );

4、 手工管理绑定表
即:通过应用程序调用诸如 bindAddEntry(函数在 BindingTable.h 文件中定义,具体实现被封包了 )来实现手工绑定表管理,这种方式自由度很大,也不需要别的节点参与,但是应用程序要做的工作多一些,整个绑定表都是你说了算。
注意:这种方式你需要事先知道被绑定的节点信息,诸如短地址,端点号, incluster 和outcluster 这些信息,否则你没办法把那些函数的参数填进去。子节点对其父节点的绑定,绑定表添加绑定程序:
BindAddr.addrMode = Addr64Bit;
osal_cpyExtAddr( BindAddr.addr.extAddr, &Uart_buf[1] );
bindAddEntry(ZG_Serial_Control_ENDPOINT,
&BindAddr,
ZG_Serial_Control_ENDPOINT,
ZG_Serial_Control_MAX_CLUSTERS,
ZG_Serial_Control_ClusterList);
绑定表删除绑定条目:
BindAddr.addrMode = Addr64Bit;
osal_cpyExtAddr( BindAddr.addr.extAddr, &Uart_buf[1] );
pBindingTable = bindFindExisting( ZG_Serial_Control_ENDPOINT,
&BindAddr,
ZG_Serial_Control_ENDPOINT );

bindRemoveEntry( pBindingTable );

二、应用场合举例

1、第一种方式(enddevicebind)
例:网络中有协调器存在,另外有两个节点 A 和 B,这两个节点具有互补特性(即 A 节点的 incluster 是 B 节点的 outcluster), A 和 B 结点都有按钮可以通过程序来触发EndDeviceBind 的调用。在这种情况下,你只要在规定的时间内分别按 A 和 B 上的某个按钮,绑定就会在协调器的帮助下自动完成。这适合于节点很方便操作,没有被装墙里或者无法接触的地方;绑定完成后,具有 outcluster 性质的 B 节点即可以通过绑定方式给具有 incluster 性质的 A 节点发消息,但是不能指望反过来由 A 发消息给 B,因为 A节点根本就没有关于 B 的信息,绑定表是存在 B 中的。

2、第二种方式(Match)
例: 网络中不一定有协调器存在, 但是有 A、 B、 C、 D 等多个节点, A 性质是 Outcluster,B、 C、 D 的性质是 Incluster,你可以通过按键策略来在一定时间内允许 B、 C、 D 中的任何一个开启被 Match 的功能,同时 A 发起 Match 请求(广播的),那么被允许 Match的节点就会在收到请求后将自己的信息返给 A, A 在得到 rsp 的时候来处理绑定,如果你还想让 A 绑到其它节点上,可以依次这么做。这种方式其实同第一种操作过程类似,
只不过不需要协调器的参与。

3、第三种方式(Bindreq,Unbindreq)
例:假设你有一个主控(可能是 ARM 板子,可能是 PC……),并且有一个 Zigbee 节点 A通过串口或者 U 口等方式连在了主控上, 主控可以给 A 发命令(什么命令你要自己定义、自己实现了 );你还有一个 B 节点是开关,还有一个 C 节点是灯。你想让在 B 上建立绑定表,以用来控制 C。那么你可以通过主机命令 A 向另外的节点 B 发起 BindReq 要求,主机发给 A 的命令中会带着 C 的一些信息(主机如何有 C 的信息?这种场合下, 主机应该了解整个网络的细节,至于如何了解。。。。,以后再说)。这样, A 就可以向 B 发起BindReq 请求,这个请求的参数中包含了必要的 C 的信息, B 在收到请求后就会建立起关于控制 C 的绑定表,以后 B 可以通过开关控制 C 了,也不再需要 A 的参与。这种方式适合那种集中管理的网络。

5、 第四种方式(手工)
例:你还是有一个主机,主机上有 Zigbee 节点 A 能够串口或者 U 口通信。你想由主机来深入地管理整个网络上的绑定情况,你就可以通过主机给 A 发命令,告诉 A 给某一个节点发命令,让它去建立、删除、追加。。。。绑定表。这种方式实际上最灵活,但是需要用左的工作最多,用户也需要很清晰的思路去管理绑定表,要是不小心管理错了,就杯具了。

标签:
上一篇: 下一篇:

报歉!评论已关闭。