希望节点退网后不再主动搜索网络,而是等用户按键动作之后再重新加网,并且希望也可以重加入之前的网络,所以我的处理流程是如下两步:
1)先 NLME_LeaveReq(&req),且其中req.rejoin = true;,
req.extAddr = NULL;
req.removeChildren = false;
req.rejoin = true;
req.silent = false;
sta = NLME_LeaveReq(&req);
2)等DEV_NWK_DISC发生后执行ZDApp_StopJoiningCycle();
因为看代码ZDApp_StopJoiningCycle()必须在DEV_NWK_DISC、DEV_INIT、DEV_NWK_BACKOFF状态下才有效, NLME_LeaveReq()之后会发生ZDO_STATE_CHANGE,所以我等状态变为DEV_NWK_DISC再执行ZDApp_StopJoiningCycle();
case ZDO_STATE_CHANGE:
zclSensor_NwkState = (devStates_t)(MSGpkt->hdr.status);
if(zclSensor_NwkState==DEV_NWK_DISC)
{
ZDApp_StopJoiningCycle();
} break;
但是 发现执行ZDApp_StopJoiningCycle()之后节点还是会继续加网的动作,加入到原来的网络。这是为什么?
看ZDApp_StopJoiningCycle()的代码发现只有一个“continueJoining=FALSE”的操作,而搜索整个工程看到continueJoining变量只有在ZDApp.c中有两个赋值的操作,没有任何使用到的地方,这是ZDApp_StopJoiningCycle()无效的原因? 应该怎么做才能实现NLME_LeaveReq()之后不再执行搜索网络的动作?
YiKai Chen:
你req.rejoin = true;要改成req.rejoin = false;
Alvin Chen:
回复 YiKai Chen:
req.rejoin = true 这样是还是允许REJOIN,请参照YK的建议。
user4975928:
回复 Alvin Chen:
1,谢谢YiKai Chen和Alvin Chen,但是我主要的疑问是ZDApp_StopJoiningCycle()为什么没能实现停止扫描网络的效果?
2,同时测试了req.rejoin = false的效果,终端退网后重新上电,会加网(原来的网络)失败,不能像第一次上电那样能顺利加网。 想要的效果是退网后按键动作一下就能够重新加网,不管是新的网络还是之前的网络。
YiKai Chen:
回复 user4975928:
試試參考 Cetri 在 e2e.ti.com/…/1343379 給的 ZDApp_LeaveReset 和 ZDApp_ProcessNetworkJoin 的代碼操作
user4975928:
回复 YiKai Chen:
参考链接的代码似乎是对比较老的版本的修改,大部分添加的代码在目前3.0.1的版本都已经有,但结构有所不同,一时感觉无从参考。
目前没有修改z-stack,仅对不同参数情况下使用 NLME_LeaveReq(&req) 和 ZDApp_LeaveReset(true or false) 的效果进行了测试:
——————————代码——————————-
…
sta = NLME_LeaveReq(&req);if(sta==afStatus_SUCCESS){ZDApp_LeaveReset(true or false);}
…
———————————————————————
A,req.rejoin = true, ZDApp_LeaveReset(true);
退网后会立即重连,成功,不会复位;
B,req.rejoin =false, ZDApp_LeaveReset(true);
退网后会立即重连,成功,随后会复位;重启后加网没反应,CO、ED同时复位后加网失败(END_DEVICE_UNAUTH反复);
C,req.rejoin =false, ZDApp_LeaveReset(false);
退网后会复位,重启加网没反应,CO、ED同时复位后加网失败(END_DEVICE_UNAUTH反复);再次都重启,加网成功(仅一次,之后再重复都_DEVICE_UNAUTH);
D,req.rejoin =true, ZDApp_LeaveReset(false);
退网后会立即重连,成功,随后会复位;重启后加网没反应,CO、ED同时复位后加网失败(END_DEVICE_UNAUTH反复);对ZDApp_LeaveReset()的作用理解还不太透彻,不知道是不是应该在这里这么使用,但效果看来也是没有达到想要的目的,继续求助 !
Alvin Chen:
回复 user4975928:
你最好自己去追踪一下code。当你是ra=0时。
void ZDApp_LeaveReset( uint8 ra ) {ZDApp_LeaveCtrlSet( ra );APSME_HoldDataRequests( LEAVE_RESET_DELAY);if ( ZSTACK_ROUTER_BUILD ){osal_stop_timerEx( NWK_TaskID, NWK_LINK_STATUS_EVT );osal_clear_event( NWK_TaskID, NWK_LINK_STATUS_EVT );}if (ZG_DEVICE_ENDDEVICE_TYPE){// Save polling values to be restored after rejoinif ( ra == TRUE ){ZDApp_SavedPollRate = zgPollRate;savedResponseRate = zgResponsePollRate;savedQueuedPollRate = zgQueuedPollRate;}// Disable pollingNLME_SetPollRate(0);NLME_SetResponseRate(0);NLME_SetQueuedPollRate(0);}if ( ra == TRUE ){devState = DEV_NWK_DISC;devStartMode = MODE_REJOIN;_tmpRejoinState = true;// For rejoin, specify the extended PANID to look forosal_cpyExtAddr( ZDO_UseExtendedPANID, _NIB.extendedPANID );_NIB.nwkState = NWK_DISC;NLME_NwkDiscTerm();ZDApp_NetworkInit((uint16)(NWK_START_DELAY + ((uint16) (osal_rand() & EXTENDED_JOINING_RANDOM_MASK ))));}else{ZDApp_ResetTimerStart( LEAVE_RESET_DELAY );} }/*****void ZDApp_ResetTimerStart( uint16 delay ) {if ( !osal_get_timeoutEx( ZDAppTaskID, ZDO_DEVICE_RESET ) ){// Start the rest timerosal_start_timerEx( ZDAppTaskID, ZDO_DEVICE_RESET, delay );} }if ( events & ZDO_DEVICE_RESET ){ #ifdef ZBA_FALLBACK_NWKKEYif ( devState == DEV_END_DEVICE_UNAUTH ){ZDSecMgrFallbackNwkKey();}else #endif{// Set the NV startup option to force a "new" join.zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );// The device has been in the UNAUTH state, so reset// Note: there will be no return from this callSysCtrlSystemReset();}}
user4975928:
回复 Alvin Chen:
谢谢Alvin Chen,看到如果ra=0时最后软件会使设备执行一个复位。但是还是不理解不能重新加入网络的问题。
进行了仅使用ZDApp_LeaveReset()的测试:
A,ZDApp_LeaveReset(true);
退网后不会复位,会立即重加当前的网络;硬件复位后也只能加入之前的网络而不能加入其它网络;
B,ZDApp_LeaveReset(false); 退网后会复位,复位后加网(原来的或另外的)失败;要再次硬件复位后才能加另一个网成功,但十几秒后会自动复位;没有达到顺利重新入网的期望。协议发展了这么多年,退网再加网的问题应该早已经考虑到了,但我似乎找不到正确实现的方法,大家有处理过这个问题吗?
Alvin Chen:
回复 user4975928:
你说的一部分是对的,
当ZDApp_LeaveReset(true); 不会复位,你仔细看程序是开始模式是rejoin是会加入原来的网络。devState = DEV_NWK_DISC;devStartMode = MODE_REJOIN;_tmpRejoinState = true;
// For rejoin, specify the extended PANID to look forosal_cpyExtAddr( ZDO_UseExtendedPANID, _NIB.extendedPANID );
_NIB.nwkState = NWK_DISC;NLME_NwkDiscTerm();
当ZDApp_LeaveReset(false); 会进行NV擦除,然后复位,会复位状态为UNAUTH state
// The device has been in the UNAUTH state, so reset// Note: there will be no return from this callSysCtrlSystemReset();
你想重新加入网络需要重新发起入网申请,比如ZDO_StartDevice(0);
user4975928:
回复 Alvin Chen:
我在终端设备中使用 bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_STEERING ); 进行入网申请,无论是未加过网还是退出过网, 不知这样是不是不对的?
仿真跟踪当第一次加网时进入到ZDO_StartDevice()的入口参数为(NODETYPE_DEVICE, MODE_JOIN, 0x0F, 0x0F),于是我用ZDO_StartDevice(NODETYPE_DEVICE, MODE_JOIN, 0x0F, 0x0F);代替bdb_StartCommissioning()进行入网操作,但是没有成功。