This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

关于退网操作,使用NLME_LeaveReq()且等ZDO_STATE_CHANGE之后再ZDApp_StopJoiningCycle()似乎没有效果,仍然会重新执行加网动作

Other Parts Discussed in Thread: Z-STACK

希望节点退网后不再主动搜索网络,而是等用户按键动作之后再重新加网,并且希望也可以重加入之前的网络,所以我的处理流程是如下两步:

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()之后不再执行搜索网络的动作?

  • 你req.rejoin = true;要改成req.rejoin = false;
  • req.rejoin = true 这样是还是允许REJOIN,请参照YK的建议。
  • 1,谢谢YiKai Chen和Alvin Chen,但是我主要的疑问是ZDApp_StopJoiningCycle()为什么没能实现停止扫描网络的效果?
    2,同时测试了req.rejoin = false的效果,终端退网后重新上电,会加网(原来的网络)失败,不能像第一次上电那样能顺利加网。 想要的效果是退网后按键动作一下就能够重新加网,不管是新的网络还是之前的网络。
  • 試試參考 Cetri 在 e2e.ti.com/.../1343379 給的 ZDApp_LeaveReset 和 ZDApp_ProcessNetworkJoin 的代碼操作
  • 参考链接的代码似乎是对比较老的版本的修改,大部分添加的代码在目前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()的作用理解还不太透彻,不知道是不是应该在这里这么使用,但效果看来也是没有达到想要的目的, 继续求助 !
  • 你最好自己去追踪一下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 rejoin
        if ( ra == TRUE )
        {
           ZDApp_SavedPollRate = zgPollRate;
           savedResponseRate = zgResponsePollRate;
           savedQueuedPollRate = zgQueuedPollRate;
        }
    
        // Disable polling
        NLME_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 for
        osal_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 timer
        osal_start_timerEx( ZDAppTaskID, ZDO_DEVICE_RESET, delay );
      }
    }
    
      if ( events & ZDO_DEVICE_RESET )
      {
    #ifdef ZBA_FALLBACK_NWKKEY
        if ( 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 call
          SysCtrlSystemReset();
        }
      }

  • 谢谢Alvin Chen,看到如果ra=0时最后软件会使设备执行一个复位。但是还是不理解不能重新加入网络的问题。
    进行了仅使用ZDApp_LeaveReset()的测试:
    A,ZDApp_LeaveReset(true);
    退网后不会复位,会立即重加当前的网络;硬件复位后也只能加入之前的网络而不能加入其它网络;
    B,ZDApp_LeaveReset(false);
    退网后会复位,复位后加网(原来的或另外的)失败;要再次硬件复位后才能加另一个网成功,但十几秒后会自动复位;

    没有达到顺利重新入网的期望。协议发展了这么多年,退网再加网的问题应该早已经考虑到了,但我似乎找不到正确实现的方法,大家有处理过这个问题吗?
  • 你说的一部分是对的,
    当ZDApp_LeaveReset(true); 不会复位,你仔细看程序是开始模式是rejoin是会加入原来的网络。
    devState = DEV_NWK_DISC;
    devStartMode = MODE_REJOIN;
    _tmpRejoinState = true;

    // For rejoin, specify the extended PANID to look for
    osal_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 call
    SysCtrlSystemReset();
    你想重新加入网络需要重新发起入网申请,比如ZDO_StartDevice(0);
  • 我在终端设备中使用 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()进行入网操作,但是没有成功。