zigbee 路由节点丢失后清除 该节点的残余网络信息
本文主要目标为 清除脱离网络的 路由节点(stale device)的 残留在各表中以AssociationDevList为例的残余信息。
如图所示拓扑结构中:
路由器1脱离网络后,通过协调器按键操作来 清除 协调器及路由器2 的关联表中 与路由器1 相关的条目信息。
根据AssociationDevList 条目中的age值来判断 路由节点是否脱离网络,若脱离网络,则先调用AddrMgrEntryGet( ) 获取丢失节点的短地址 和 扩展地址,然后调用NLME_LeaveReq()/AssocRemove()对表中的条目信息进行清除操作。
Z-stack中关联表AssociationDevList 主要存储与该节点有父子关系的相关节点信息,表中信息的 IEEE 地址是唯一的,每个设备加入它的父节点时会在表中添加一个记 录(一个设备掉电重启后 sniffer中显示两个短地址的一个为掉电前短地址另一个为新获取的段地址),但是子节点断电离开网络时不会删除该条记录,如果有多个子节点,频繁更换父节点会造成 AssociatedDevList 表满或溢出,使其它子节点无法加入该父节点,因此需要及时的删除一些已离开的子节点记录。其条目结构体如下:
typedef struct { UINT16 shortAddr; // 关联设备的短地址 uint16 addrIdx; // 条目索引号 起始为0 byte nodeRelation; //与该节点的关系 byte devStatus; // 设备状态 byte assocCnt; //联接次数,相同 IEEE 地址连接时会加 1 byte age; //连续未接收link status 的次数(终端设备始终增加) linkInfo_t linkInfo; } associated_devices_t; nodeRelation 可选值如下: // Node Relations #define PARENT 0//父节点 一般指协调器 #define CHILD_RFD 1//简功能节点 一般指终端 #define CHILD_RFD_RX_IDLE 2//简功能节点(空闭进 RF 接收开启) 一般指终端 #define CHILD_FFD 3//全功能节点 一般指路由器 #define CHILD_FFD_RX_IDLE 4//全功能节点(空闭进 RF 接收开启) 一般指路由器 #define NEIGHBOR 5//邻居设备 #define OTHER 6//其它设备 #define NOTUSED 0xFF //没有使用 devStatus可选值如下: #define DEV_LINK_STATUS 0x01 // 活动联接 #define DEV_LINK_REPAIR 0x02 //正在修复联接 #define DEV_SEC_INIT_STATUS 0x04 // 初后的安全 #define DEV_SEC_AUTH_STATUS 0x08 //验正过的安全 /* * Remove a device from the list. Uses the extended address. */ extern byte AssocRemove( byte *extAddr );
能够 移除 关联表 中 所指定扩展地址设备的条目信息;
调用该函数的前提是 获取相关节点的 扩展地址。
/* * @fn AddrMgrEntryGet * * @brief Get NWK address and EXT address based on index. * * @param entry * ::user - [in] user ID //需要输入用户ID * ::index - [in] index of data //相应表条目 索引号 * ::nwkAddr - [out] NWK address //读取相应条目 的端地址 * ::extAddr - [out] EXT address //读取相应条目的扩展地址 * * @return uint8 - success(TRUE:FALSE) //返回读取是否成功状态值 */ extern uint8 AddrMgrEntryGet( AddrMgrEntry_t* entry );
能够根据 索引号 读取关联表、绑定表等表中的短地址和扩展地址;
其中用户ID 主要选择对应的表,其参数为:
// user IDs - use with <AddrMgrEntry_t> #define ADDRMGR_USER_DEFAULT 0x00 //默认用于读取Assoc #define ADDRMGR_USER_ASSOC 0x01 #define ADDRMGR_USER_SECURITY 0x02 //用于读取安全相关 #define ADDRMGR_USER_BINDING 0x04 //用于读取绑定表 #define ADDRMGR_USER_PRIVATE1 0x08 //未知
相关代码如下所示:
HalLedSet ( HAL_LED_1, HAL_LED_MODE_TOGGLE ); uint8 _nodeCounter; uint8 _nodeIndex; NLME_LeaveReq_t req; req.extAddr = removeExtAddr; req.removeChildren = FALSE; req.rejoin = FALSE; req.silent = FALSE; for ( _nodeCounter = 0; _nodeCounter < NWK_MAX_DEVICES; _nodeCounter++ ) { if ( (AssociatedDevList[_nodeCounter].nodeRelation == CHILD_FFD_RX_IDLE) || (AssociatedDevList[_nodeCounter].nodeRelation == CHILD_FFD) || (AssociatedDevList[_nodeCounter].nodeRelation == PARENT)) { HalLedSet ( HAL_LED_2, HAL_LED_MODE_TOGGLE ); if ( AssociatedDevList[_nodeCounter].age > NWK_ROUTE_AGE_LIMIT ) { //HalLedSet ( HAL_LED_2, HAL_LED_MODE_TOGGLE ); AddrMgrEntry_t addrEntry; addrEntry.user = ADDRMGR_USER_DEFAULT; addrEntry.index = _nodeCounter; if ( AddrMgrEntryGet( &addrEntry ) ) { req.extAddr = addrEntry.extAddr; NLME_LeaveReq(&req); //通过leave命令 清除 stale device相关条目; addrIndex = addrEntry.extAddr[0]; //将扩展地址最后一位无线发射做验证; //AssocRemove( addrEntry.extAddr); /***** 对外进行广播以清除 活动节点上 丢失节点信息 *****/ Remove_DstAddr.endPoint = 10; Remove_DstAddr.addr.shortAddr = 0xfffc; Remove_DstAddr.addrMode = afAddr16Bit; if ( AF_DataRequest( &Remove_DstAddr, &GenericApp_epDesc, GENERICAPP_CLUSTERID3,1,&addrIndex, 0, 0, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { // Successfully requested to be sent. } } } }
网络中的路由设备接收到该命令后,重复如上代码清除 stale device相关条目信息,对其他表的操作类似。
1.设备丢失后 重新上电 关联表 会更新其短地址,很偶尔的出现一次同一个设备 sniffer的 link status 中显示两个短地址(原因未知);
2.有时使用NLME_LeaveReq()会出现无效的情况,更换为AssocRemove()则没问题 (原因未知);
3.对脱离网络的 终端设备相关条目删除 需要定时 的通报ED在网络中,可参考提供的链接进行尝试;