终端设备无法重入网络 使用 (zstack1.2.2a)
测试环境:
一个ZC ,5个ZED ,ZED 是电池设备 (均采用 zstack 1.2.2 或1.2.2a)
操作:
重复重启 ZC, 造成 ZED 断网寻网 。
目的:
验证 寻网一段时间,然后休眠一段时间 的新逻辑,(rejoin scan====》 rejoin backoff====》rejoin scan)
代码上增加:
在应用层 loop 中的 ZDO_STATE_CHANGE 事件中,
当DEV_NWK_DIS 时, 调用HAL_LED_BLINK() 函数 让LED1 一直闪
当DEV_NWK_BACKOFF 时, 调用HAL_LED_SET() 函数 将LED1 关闭
这样 断网的时候 LED1 就一直闪, 休眠(rejoin backoff)的时 ,灯就熄灭。
发现问题:
重刷了很多次之后, 发现 有些设备 断网后,LED1 一直闪,rejoin scan 的时间过完 ,还是无法进入rejoin backoff。
用抓包软件抓了一下, 发现有两种情况
情况1 : 设备是有发beacon request 出来的。 但是ZC 启动完成后, 设备仍然无法进入网络。
情况2: 设备只是闪LED1 ,但是 实际上没有发beacon request出来
以上两种情况 只是 设备无法 入网的 现象。
针对情况1 我的猜测:
让我不明白的 为甚么, 设备过了rejoin scan 规定时间后, 无法进入rejoin back off呢?
针对情况2 我的猜测 :
或者是设备已经 进入rejoin backoff 了,但 LED1 没有关闭。(即 设备的state 改变了 , 但是没有把改变 的状态 传到 应用层 的ZDO_STATE_CHANGE 事件上)
顺便把数据包附下上去,情况1下设备的devstartmode是什么,有没有可能出现过节点在发rejoin request的时候,刚好把协调器断电了?
情况2,协议栈里面其他地方也有用到这个LED闪的,
终于等到你!
情况 1 devstart mode?
devstate 吗? 此时 设备的 状态 是DEV_NWK_DIS,(很抱歉 log 没存起来)
如果是1.2.2的话,会有两种情况。
1. 设备发出rejoin request, 但是 协调器就是永远不response, ( 这个暂时没有log)
2. 设备发出rejoin request, 协调器也响应了, 但是设备还是依然 处于寻网状态, 除非 协调器开permit join 。
log:6303.1.2.2断网后response成功但实际无法入网要重开permitjoin.rar
情况2, 这个很容易复现的,只要你把 闪灯 的操作 放在 ZDO_STATE_CHANGE 事件里 的DEV_NWK_DIS case 中。
几个rejoin logic 下来,基本就可以出现了。
另外有个问题非常想请问你, rejoin backoff 的默认值 设置为30分钟 可以吗?
1800000 虽然没有超过uint32 , 但真的可以吗?
VV,
情况1 的 log 抓到了。
52 条: 发orphan notification,
92 条: 发了rejoin request, 有ACK, 但是没有rejoin response
接着就一直 beacon 下去了!
log :3364.rejoin request 有ACK 但没有rejoin response.rar
另外一个log 说明一下:
log :2626.rejoin response成功但实际无法入网要重开permitjoin.rar
582条~599条: 终端 发了3次rejoin request, 协调器才响应了 成功。
但实际上 它还是 依然 继续 寻网 发beacon
等到1336条 : 我开了 协调器的permit join。
这时 终端设备 才 association 成功 进入网络。。。。
所以我不明白,既然都 rejoin response 告诉成功了,为什么后面还要 开permit join 才能进来
你使用的Rejoin是自己写的吗?怎么是unsecured rejoin,你可以看到你的rejoin是没有加密的,所以是unsecure rejoin,然后还需要trust center去授权的,如果permit join在关掉的情况下,就不允许入网了。
谢谢 VV
第一 : Rejoin 不是我自己写的。 我也奇怪为什么 就变成 unsecure rejoin 了, (前面一个 (第592条)还是加密的rejoin。)
第二,撇开加密的问题, 为什么 不加密的rejoin request 反倒有 rejoin response。而且rejoin response的 返回 是允许入网的。
谢谢!
你的0xF292这个是一个终端设备,但是在发起Rejoin Request确没有Data Request发出来。
你在协议栈做什么改动?
这个问题复现的流程是什么
VV:
1. rejoin 的code 我没有改动,使用的是HA1.2.2.a 原有的 那套逻辑(rejoin scan ---> resjoin backoff ---> rejoin scan)
2. 为什么突然就变成unsecured rejoin, 这个我也很诧异, 加不加密不是 在工程编译的时候 使能 SECURE=1 就开启了吗?
程序运行过程中 应用层 的软件难道还可以 修改为不加密 吗?
所以 这个肯定不是 客户应用代码 造成的。。。。
我怀疑是 NWK key 丢失了, 但是 抓包过程中又无法判断 NWK key 什么时候 更新 什么时候传输到 终端节点!
3. 所有的终端设备 发起rejoin request 都 必须 发起 data request 吗?
这个我倒没留意, 但是如果终端设备 是RFD_RCVC_ALWAYS_ON=TRUE, 难道 发起rejoin request 还需要 发起data request吗?
这个 规定 在zstack 中 哪里说明?
4. 我现在 也还不是很清楚 百分百 复现该问题的 流程 是怎样?
以下两种情况下 出现过,终端设备无法 rejoin到 网络中, 除非开启ZC的 permijoin 。
====》 边缘节点情况,
如下图,我们在一间100平米的房间内 不同位置布置了终端设备,
这些终端设备 我们在程序上 设置 每6秒 就发送一条 msg (IEEE request) 到 协调器
放置一个晚上之后, 第二天早上 红色 圈中的 终端设备 均出现 断网 无法连接 协调器的情况
然后重新开启 permitjoin 的 时候 也基本都可以 重新加入, (只是它们都使用了新的 短地址)
=====》 重复复位协调器 并删除Association List 。
(PS: 删除Association List 只是我们自定的一个功能, 主要是防止ZC 列表撑满了僵尸设备, 这里只是说明有过类似操作 造成终端设备无法入网)
多次 操作复位之后, 就出现了 终端设备 无法rejoin的 现象。
具体可以参考 post :https://e2e.ti.com/support/wireless_connectivity/zigbee_6lowpan_802-15-4_mac/f/158/p/506481/1850037#1850037
谢谢!
VV:
不知道你是否记得 自己 发的一篇关于ZigBee 状态机的文章:http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/104629.aspx
在 第 20 点 DEV_NWK_REJOIN状态到DEV_END_DEVICE_UNAUTH(20)
有这么一句话:
如果在ZDApp_RestoreNwkKey( uint8 incrFrmCnt ),读取network key错误,或者之前保存的network key已经不在的情况下,那么就发了Unsecure Rejoin的方式。
读取network 可以错误 的几率,我相信 非常少吧!
那么 network key 不见呢?,这是有可能! 比如终端设备 寻网 过程中 自己把 NWK KEY 清除, 然后把NV flash 里面的东西全清了!
我假设 一下, 如果 终端设备发送了Rejoin Request以后,收到父设备回复的Rejoin Response消息,那么程序会次进入到ZDApp_ProcessNetworkJoin( void
) , 进行 Verify NWK key is available before sending Device_annce 对吧!
else if ( devState == DEV_NWK_ORPHAN || <strong><span style="color:#ff0000;">devState == DEV_NWK_SEC_REJOIN_CURR_CHANNEL</span></strong> || devState == DEV_NWK_TC_REJOIN_CURR_CHANNEL || devState == DEV_NWK_TC_REJOIN_ALL_CHANNEL || devState == DEV_NWK_SEC_REJOIN_ALL_CHANNEL ) { ...................... // results of an orphaning attempt by this device // results of an orphaning attempt by this device <strong><span style="color:#ff0000;"> if (nwkStatus == ZSuccess)</span></strong> { //When the device has successfully rejoined then reset retryCnt retryCnt = 0; // Verify NWK key is available before sending Device_annce if ( ZG_SECURE_ENABLED && ( ZDApp_RestoreNwkKey( TRUE ) == false ) ) { // wait for auth from trust center ZDApp_ChangeState( DEV_END_DEVICE_UNAUTH ); // Start the reset timer for MAX UNAUTH time ZDApp_ResetTimerStart( MAX_DEVICE_UNAUTH_TIMEOUT ); }
但是在此之前 终端设备 进入
predevState == DEV_NWK_SEC_REJOIN_ALL_CHANNEL 时,
会把NWK KEY 清掉。。。。
这时ZDApp_ResetTimerStart( MAX_DEVICE_UNAUTH_TIMEOUT ); 时间一到! 是不是就悲剧了!
请问你这个问题解决了吗? 我们做的设备这两天也遇到了同样的问题了,一个协调器组网带了20个end device,过了一个晚上后发现有15个终端设备处于失去父节点状态,一直不能重新入网,其余的5个设备连接状态正常,搜索了相关问题资料,如 http://www.kaleidscope.cn:1020/archives/992 做了修改测试,还是不行,也是要协调器端开启permitjoin才能重新入网。
你好,http://www.kaleidscope.cn:1020/archives/992这帖子是我的,我使用的是Mesh1.0.0,当时Susan Yang提供的方法,我们几个小伙伴都遇到这样的问题,必须开permitjoin才可以,后来按照Susan Yang的方法修改后是可以解决这个问题的。这种问题当时一般是出现在信号弱的终端节点上。
如果你们还是不能解决我建议在协调器上做心跳检测,如果检测到某个节点掉线了就自动打开Permitjoin一段时间,等待节点再次加入。
如果有更好的解决办法望分享。
谢谢回复,我使用的也是Z-Stack Mesh 1.0.0版本,看过代码,其实在ZDApp.c的第1600行左右,当devStartMode = MODE_REJOIN;时紧跟着 _tmpRejoinState = true; 已经对_tmpRejoinState 置成ture了,所以在ZDApp_NetworkInit里面添加的语句这么看是多余的。
出现的终端掉线重连不了的问题还没解决。
分析出来的是终端掉线后若重启有RESUME模式进入orphan状态,发送orphan notification,协调器没有回coord realignment,而后状态立刻切到rejoin模式搜索网络,这时就必须协调器开启 permit join 才能重新入网。
这个问题我们也碰到的,目前已经解决了。问题的本身其实就是密钥被清除了,代码内可以搜索到,做法上我们是改写了重连的机制,不让他清楚密钥,并且开启Rejoin 为True ,始终允许重连,就可以了。
@xiaobo zhang 的回答是正解!
@我要把牛头上交国家 这种做法只适应老版本的zstack 。 也许老版本的zstack 也有这样的问题,
@Xiaobo Zhang @MarS 谢谢! 秘钥清除的函数应该是ZDApp_ResetNwkKey吧,搜了下应用层并没有调用,调用处应该在闭源部分。 如果限制清除秘钥,就只能在这个函数里直接return; 而不做任何动作即可,是这样吗?
另外,您说的“开启rejoin为true”, 应该在协调器端修改吧? 如何修改比较合适,能否贴段代码参考呀? 谢了!
void ZDApp_ProcessNetworkJoin( void )
{
if ( (devState == DEV_NWK_JOINING) ||
((devState == DEV_NWK_ORPHAN) &&
(ZDO_Config_Node_Descriptor.LogicalType == NODETYPE_ROUTER)) )
{
...
}
else if ( devState == DEV_NWK_ORPHAN ||
devState == DEV_NWK_SEC_REJOIN_CURR_CHANNEL ||
devState == DEV_NWK_TC_REJOIN_CURR_CHANNEL ||
devState == DEV_NWK_TC_REJOIN_ALL_CHANNEL ||
devState == DEV_NWK_SEC_REJOIN_ALL_CHANNEL )
{
// results of an orphaning attempt by this device
if (nwkStatus == ZSuccess)
{
...
}
else
{
if ( devStartMode == MODE_RESUME )
{
...
}
else if(devStartMode == MODE_REJOIN)
{
if ( ZSTACK_END_DEVICE_BUILD )
{
devStartMode = MODE_REJOIN;
_tmpRejoinState = true;
_NIB.nwkState = NWK_INIT;
if( prevDevState == DEV_NWK_SEC_REJOIN_CURR_CHANNEL )
{
runtimeChannel = MAX_CHANNELS_24GHZ;
prevDevState = DEV_NWK_SEC_REJOIN_ALL_CHANNEL ;
}
else if ( prevDevState == DEV_NWK_SEC_REJOIN_ALL_CHANNEL)
{
// Set the flag that will ask the device to do trust center network layer rejoin.
// 网络密钥无需擦除,避免强干扰状态下,
// 长时间没有收到新的网络密钥,进而复位到未入网状态
// 造成无法重新入网情况
//_NIB.nwkKeyLoaded = FALSE;
//ZDApp_ResetNwkKey(); // Clear up the old network key.
#ifdef DEBUG_REJOIN
HalUARTWrite(0,"Don't clearing network key\n", sizeof("Don't clearing network key\n"));
#endif
runtimeChannel = (uint32) (1L << _NIB.nwkLogicalChannel);
prevDevState = DEV_NWK_TC_REJOIN_CURR_CHANNEL ;
}
}
}
}
感谢提供思路和解决方法,我已经备份至http://www.kaleidscope.cn:1020/archives/992 ,侵删。
你好,我用zstack不做什么修改(不加按键什么的控制组网) ,终端什么时候都可以入网,那个Permitjoin是不是一直开着的?
默认一直打开Permitjoin
@MarS ,您好!谢谢您的回复,您贴的这部分代码以及关键的那2两行关于nwkkey被清除导致终端掉线后重连不上的代码,我搜索了工程并没有这部分,ZDApp_ResetNwkKey,并没有调用, 我用的是Z-Stack Mesh 1.0.0 版本,请问您用的是哪个版本?
所以这么看,问题还不是这么简单的,还需继续探讨啊。
我用到 就是 Zstack HA 1.2.2a
我们用到可能不一样!
我使用这种方法的话,还是不行,附件说我的抓包log,请求帮助
log抓包文件
@VV
我的网关使用的是ZHA1.2.2的,也是出现无法重入网的,按照http://www.kaleidscope.cn:1020/archives/992这个改了之后,还是一直无法重现入网,附件是我的抓包log,求助一下。