微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI Zigbee设计交流 > zigbee端末掉线和重连的问题 cc2530协议栈2.5.1a

zigbee端末掉线和重连的问题 cc2530协议栈2.5.1a

时间:10-02 整理:3721RD 点击:

掉线:一般都什么样的问题容易引起掉线呢?比如硬件,软件的那些方面呢?协议栈哪里呢?

重连:要说掉线不好分析,若能重连也可以。

1:设备掉线重连:

掉线后进入下面回调函数

void ZDO_SyncIndicationCB( uint8 type, uint16 shortAddr )

产生ZDO_NWK_JOIN_REQ

之后进入到

void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )

case ZDO_NWK_JOIN_REQ:

devStartMode = MODE_RESUME;//改为resume模式

2.设备断电后重新上电,直接就是resume模式

ZDApp_NetworkInit( 0 );//初始化网络

启动osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );

进入到UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )

if ( events & ZDO_NETWORK_INIT )

devState = DEV_INIT;//初始化状态

ZDO_StartDevice();//开始入网

进入后执行最后一个else,以孤儿方式组网

devState = DEV_NWK_ORPHAN;
ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
zgDefaultStartingScanDuration );

等待回调函数

void ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )

把结果通知ZDO_NWK_JOIN_IND

在此处void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )

case ZDO_NWK_JOIN_IND:

进入端末处理

ZDApp_ProcessNetworkJoin();

else if ( devState == DEV_NWK_ORPHAN || devState == DEV_NWK_REJOIN )

if (nwkStatus == ZSuccess)

devState = DEV_END_DEVICE;
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );////至此入网成功

否则失败了

else
{

     if ( devStartMode == MODE_RESUME )、、、掉线后恢复网络失败后到此处
     {
          if ( ++retryCnt <= MAX_RESUME_RETRY )//////此处非常不明白为什么第一次执行后,就判断由resume改成rejoin模式呢?上面路由节点是3次后换模式
         {
            if ( _NIB.nwkPanId == 0xFFFF || _NIB.nwkPanId == INVALID_PAN_ID )
            devStartMode = MODE_JOIN;
        else
        {
            devStartMode = MODE_REJOIN;
            _tmpRejoinState = true;
        }
    }
    // Do a normal join to the network after certain times of rejoin retries
    else if( AIB_apsUseInsecureJoin == true )///////此处改为join模式还能恢复到原来的网络了吗?
    {
        devStartMode = MODE_JOIN;
    }

   resume模式恢复网络失败后,清楚表后,重新执行网络初始化

   // setup a retry for later...

    ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
        + (osal_rand()& EXTENDED_JOINING_RANDOM_MASK)) );

}

之后再次进入void ZDO_StartDevice()//再次加入网络

这次执行路由或者终端节点处理中的

if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )//////上1次执行的else的resume模式
devState = DEV_NWK_DISC;

ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );////发现网络,这里具体是什么作用不是太清楚,开始模式为join和rejoin时,入网都要先执行NLME_NetworkDiscoveryRequest,进入case ZDO_NWK_DISC_CNF:尝试大于2次后再执行NLME_ReJoinRequest吗?为什么这样做呢?

等待回调函数

ZStatus_t ZDO_NetworkDiscoveryConfirmCB(uint8 status)

ZDApp_SendMsg(  ZDO_NWK_DISC_CNF,)

进入处理消息

void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )

    case ZDO_NWK_DISC_CNF:

若尝试大于2次

else if ( devStartMode == MODE_REJOIN )
{

    devState = DEV_NWK_REJOIN;//////切换rejoin方式入网

    if ( NLME_ReJoinRequest( ZDO_UseExtendedPANID, pChosenNwk->logicalChannel) != ZSuccess )

////////////////////以rejoin方式组网也是在ZDO_JoinConfirmCB等待入网的结果,成功则切换devState = DEV_END_DEVICE;osal_set_event( ZDAppTaskID, /////////////////////ZDO_STATE_CHANGE_EVT );失败则重新初始化网络

  {

             ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
              + ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
}

为什么有些设备就是容易掉线,甚至有的失败执行上述重连过程也连不回来的,最坏的情况当协调器允许入网时候,这个设备竟然重新入网而不是恢复原来的网络,上述重连过程我理解的对吗?哪里可能有问题导致重连失败呢?上述过程都是协议栈原来的代码,我并没有进行修改。

抓包发现,重连的设备开始阶段都会发送orphan Notification,

若协调器相应了回复coordinator realignment,则非常大的概率就成功入网继续Device Announce

若协调器没有响应,则掉线设备恢复网络失败,此时设备是否应该重新发送呢?但上面程序中指执行一次NLME_OrphanJoinRequest,失败后if ( ++retryCnt <= MAX_RESUME_RETRY )切换模式rejoin了。而改为NLME_ReJoinRequest方式入网。

但抓包发现能恢复原来网络的大多是orphan Notification,之后协调器及时回复coordinator realignment的。发送rejoin是较少的。

接着楼上的问题:

void ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )
{
if ( Status == ZSUCCESS )

{nwkStateReJoin = FALSE;

else
{nwkStateReJoin = TRUE;

用nwkStateReJoin 这个标志位来判断掉线重连状态的。为什么有时候设备是能上下通信的,而nwkStateReJoin =true呢?

或者说在哪里能准确判断这个端末是否在线呢?

尝试过在sapi中case ZDO_STATE_CHANGE:

SAPI_StartConfirm(ZB_SUCCESS或ZB_INIT);

但发现有时候不可靠呢?有时候断线后重连后并未执行此处SAPI_StartConfirm

非常棒的对终端设备入网流程处理的研究,为了更加清晰的了解整个过程,请下载最新的协议栈Z-Stack Home 1.2.2a,在Z-Stack Developer Guide里面有专门介绍终端设备入网,断线,orphan,rejoin这块的状态机转换图。

我把你的红体子抄下来,进行回复了。

if ( devStartMode == MODE_RESUME )、、、掉线后恢复网络失败后到此处
     {
          if ( ++retryCnt <= MAX_RESUME_RETRY )//////此处非常不明白为什么第一次执行后,就判断由resume改成rejoin模式呢?上面路由节点是3次后换模式

这个地方虽然写了要判断多次,实际上跟你判断一样,在Resume状态只判断了一次,然后直接进入Rejoin状态的。因为在resume状态,节点发送orphan notification出来,等待父设备回复,如果父设备没有回复就直接去找网络了

 else if( AIB_apsUseInsecureJoin == true )///////此处改为join模式还能恢复到原来的网络了吗?

如果改成join以后,可以加到原来的网络,但也是有可能加到其他网络去。所以如果需要一直让设备处于Rejoin状态的话,就要如下的改动。

void ZDApp_NetworkInit( uint16 delay ) { + if ( devStartMode == MODE_REJOIN ) + { + _tmpRejoinState = true; + } if ( delay ) { // Wait awhile before starting the device osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay ); } else { osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT ); } }

ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );////发现网络,这里具体是什么作用不是太清楚,开始模式为join和rejoin时,入网都要先执行NLME_NetworkDiscoveryRequest,进入case ZDO_NWK_DISC_CNF:尝试大于2次后再执行NLME_ReJoinRequest吗?为什么这样做呢?

发现网络就是去信道上搜索网络,节点会发送beacon Request,然后其他有接收设备能力的设备会发送beacon出来,beacon里面就会带有网络相关的信息,为了让节点能够开始rejoin过程,这个建议你通过空中sniffer 去看下到底发生了什么。

3次的目的在于确实这个发送beacon的设备一个可靠的设备,另外可以收集更多的beacon,用于挑选一个最好的作为父设备入网。

为什么有些设备就是容易掉线,甚至有的失败执行上述重连过程也连不回来的,最坏的情况当协调器允许入网时候,这个设备竟然重新入网而不是恢复原来的网络,上述重连过程我理解的对吗?哪里可能有问题导致重连失败呢?上述过程都是协议栈原来的代码,我并没有进行修改。

抓包发现,重连的设备开始阶段都会发送orphan Notification,

若协调器相应了回复coordinator realignment,则非常大的概率就成功入网继续Device Announce

掉线的根本原因的节点给父设备发数据,没有ACK,即便重发也没有ACK,节点就会触发断线,进入Resume状态。

那么没有ACK的可能比较多,节点射频性能差,两点之间有阻挡物,环境干扰,等等。

如果节点从rejoin 到join状态以后,那么协调器必须要在入网允许的情况下,节点才能加。Rejoin是不需要这个判断的。

Orphan 就是resume这个状态发出来的

@VV

感谢回复

非常感谢@VV的回复

1.在掉线的情况下我们是不允许改变成join模式的,核心的问题还是为什么在orphan或者rejoin模式下一直也连不回去呢?我们就让终端开门狗复位重启,连回去的概率就大大增加了。但还是有连不回去的情况发生。但可能休息一段不确定的时间,终端在重启后还能连回去。这问题到底是出在哪里呢?

2.抓包发现掉线的终端重启后第一次发送orphan。若协调器应答并回复realgnment,则重连成功。但有时有些掉线的设备即使重启后都不发送orphan,可能是哪里出了问题呢?都是网络初始化执行同样的过程。

3.orphan失败后,终端进入rejoin模式。但抓包发现,此时能成功恢复网络的都是终端发出了rejoin,并且协调器ack 他们的第三个字节相同,然后协调器rejoin response,则终端恢复网络成功。失败的情况下终端一直没有发出rejoin request,请问是终端没有发出呢,还是只有成功的情况下才会发出呢?

4.您上面回复的解释说掉线都是终端发出后,没有收到协调器的ack。但问题23,我抓包感觉终端都没有发出orphan或者rejoin request。当然重连失败了。不知道终端出了什么问题。

5.终端发出orphan后,协调器为什么没有回复realignment呢?这段代码在哪里呢?是如何处理的,是协调器没有接到呢,还是接到后处理发现不对而没有回复呢?

@lei chen9 

请问您的这个问题解决了吗?

我现在也是ZED离网后,一直beacon request,能收到父节点的beacon回复,但就是不发rejoin request,不能重新入网。

@lei chen9

1, 在重启之前你的节点处于什么状态,时discover 状态吗?如果是discover状态的话,那么节点有没有收到合适的beacon,信号强度足够好。

你使用的是哪个版本的协议栈? 

代码做下修改

void ZDApp_NetworkInit( uint16 delay )
{
+  if ( devStartMode == MODE_REJOIN )
+  {
+    _tmpRejoinState = true;
+  }
  
  if ( delay )
  {
    // Wait awhile before starting the device
    osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );
  }
  else
  {
    osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
  }
}

2, 有没有可能没有抓到orphan,状态机每次重新都会执行到resume模式

3,跟第一个问题类似,检查下。

@sinan chen, 

按照上面回答的第一个问题,尝试下。

@VV你好,

我的问题在这个判断里,LQI值始终为0,请问LQI是在哪里计算的呢?我用是sniffer捕捉信号强度是没问题的

if ( ( pBeacon->LQI > gMIN_TREE_LQI ) &&
( ( pBeacon->permitJoining == TRUE ) || ( _tmpRejoinState ) ) )
{

Z-Stack Home 1.2.2a.44539 这个版本可以按你的方法修改吗? 让dev一直处于 rejion状态@VV

受教了,讲解的很清楚明白

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top