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.

请教:ZC是如何处理新加入的连续多个ZED节点?

个人分析如下:

1、ZDO_JoinIndicationCB函数的处理

(1)每次产生回调,会新增到单链表ZDApp_NewDeviceList中,然后开启定时器事件ZDO_NEW_DEVICE

(2)在ZDO_NEW_DEVICE事件中处理

(3)根据链表节点,重复开启ZDO_NEW_DEVICE

疑问:这里的每个节点的timeDelta参数的计算?

举例:第一个节点加入时间T1(开启timer),第二个节点加入时间T2 = T1 + 100MS,那么第二个节点的timeDelta = ZDAPP_NEW_DEVICE_TIME - 100 = 500

当第一个节点ZDAPP_NEW_DEVICE_TIME时间到达后,处理;第二个节点,此时加入设备链表不是已经经过了500ms,怎么还是开启timer = 500的定时器?

ZStatus_t ZDO_JoinIndicationCB(uint16 ShortAddress, uint8 *ExtendedAddress,
                                uint8 CapabilityFlags, uint8 type)
{
        // get the remaining time of the timer
        timeToFire = osal_get_timeoutEx( ZDAppTaskID, ZDO_NEW_DEVICE );

        pNewDevice->next = NULL;
        pNewDevice->shortAddr = ShortAddress;

//////////////////////////////////////////////////////////////////////////////
//这里时间处理不明白?
        pNewDevice->timeDelta = ZDAPP_NEW_DEVICE_TIME - timeToFire;
//////////////////////////////////////////////////////////////////////////////

        // Start the timer only if there is no pending timer
        if ( pNewDevice->timeDelta == ZDAPP_NEW_DEVICE_TIME )
        {
          osal_start_timerEx( ZDAppTaskID, ZDO_NEW_DEVICE, ZDAPP_NEW_DEVICE_TIME );
        }

    return ZSuccess;

}

      // process the new device event
      if ( ZDApp_NewDeviceList )
      {
        ZDAppNewDevice_t *pNewDevice;
        uint16 timeDelta;

        (void) ZDSecMgrNewDeviceEvent( ZDApp_NewDeviceList->shortAddr );

        pNewDevice = (ZDAppNewDevice_t *) ZDApp_NewDeviceList->next;
        osal_mem_free( ZDApp_NewDeviceList );
        ZDApp_NewDeviceList = pNewDevice;

        if ( pNewDevice )
        {
          timeDelta = pNewDevice->timeDelta;
          pNewDevice = pNewDevice->next;

          while ( pNewDevice )
          {
//////////////////////////////////////////////////////////////////
//这里时间处理不明白?
            pNewDevice->timeDelta -= timeDelta;
//////////////////////////////////////////////////////////////////
            pNewDevice = pNewDevice->next;
          }

          osal_start_timerEx( ZDAppTaskID, ZDO_NEW_DEVICE, timeDelta );
        }
      }

  • 只有当没有ZDO_NEW_DEVICE没有no pending timer才会去开启ZDO_NEW_DEVICE任务。
    // Start the timer only if there is no pending timer
    if ( pNewDevice->timeDelta == ZDAPP_NEW_DEVICE_TIME )
    {
    OsalPortTimers_startTimer( ZDAppTaskID, ZDO_NEW_DEVICE, ZDAPP_NEW_DEVICE_TIME );
    }
    此外关于节点加入网络,为了防止发送冲突,建议是当一个节点入网成功后入网后续节点
  • 这里第一个加网的设备产生的ZDO_JoinIndicationCB,此时ZDO_NEW_DEVICE,没有开启,则会打开ZDO_NEW_DEVICE任务,但是ZDAPP_NEW_DEVICE_TIME时间还没有到,此时又有新的节点加入,这里的timeDelta处理,没明白什么意思?
  • ZStatus_t ZDO_JoinIndicationCB(uint16_t ShortAddress, uint8_t *ExtendedAddress,
                                    uint8_t CapabilityFlags, uint8_t type)
    {
      (void)ExtendedAddress;
      //check if the device is leaving before responding to rejoin request
      if( OsalPortTimers_getTimerTimeout( ZDAppTaskID , ZDO_DEVICE_RESET) )
      {
        return ZFailure; // device leaving , hence do not allow rejoin
      }
    
    #if ZDO_NV_SAVE_RFDs
        (void)CapabilityFlags;
    
    #else  // if !ZDO_NV_SAVE_RFDs
        if (CapabilityFlags & CAPINFO_DEVICETYPE_FFD)
    #endif
        {
          ZDApp_NVUpdate();  // Notify to save info into NV.
        }
    
    
        if ( type == NWK_ASSOC_JOIN ||
             type == NWK_ASSOC_REJOIN_UNSECURE ||
             type == NWK_ASSOC_REJOIN_SECURE )
        {
          uint16_t timeToFire;
          ZDAppNewDevice_t *pNewDevice, *pDeviceList;
    
          pNewDevice = (ZDAppNewDevice_t *) OsalPort_malloc( sizeof(ZDAppNewDevice_t) );
    
          if ( pNewDevice == NULL )
          {
            // Memory alloc failed
            return ZMemError;
          }
    
          // Add the new device to the New Device List
          if ( ZDApp_NewDeviceList == NULL )
          {
            // The list is empty, add the first element
            ZDApp_NewDeviceList = pNewDevice;
          }
          else
          {
            pDeviceList = ZDApp_NewDeviceList;
    
            // Walk the list to last element
            while ( pDeviceList->next )
            {
              pDeviceList = (ZDAppNewDevice_t *) pDeviceList->next;
            }
    
            // Add new device at the end
            pDeviceList->next = pNewDevice;
          }
    
          // get the remaining time of the timer
          timeToFire = OsalPortTimers_getTimerTimeout( ZDAppTaskID, ZDO_NEW_DEVICE );
    
          pNewDevice->next = NULL;
          pNewDevice->shortAddr = ShortAddress;
          pNewDevice->timeDelta = ZDAPP_NEW_DEVICE_TIME - timeToFire;
    //pNewDevice->timeDelta 
          // Start the timer only if there is no pending timer
          if ( pNewDevice->timeDelta == ZDAPP_NEW_DEVICE_TIME )
          {
            OsalPortTimers_startTimer( ZDAppTaskID, ZDO_NEW_DEVICE, ZDAPP_NEW_DEVICE_TIME );
          }
        }
    
        return ZSuccess;
    }
    
    // // get the remaining time of the timer
          timeToFire = OsalPortTimers_getTimerTimeout( ZDAppTaskID, ZDO_NEW_DEVICE );
    获取当前ZDO_NEW_DEVICE剩余timer,
    
    //写入一个新设备的timer
     pNewDevice->timeDelta = ZDAPP_NEW_DEVICE_TIME - timeToFire;
    
    只有当timeToFire为0 即timer已经结束或者一个还没开启ZDO_NEW_DEVICE才会去重新开启一个ZDO_NEW_DEVICE任务
    
      // Start the timer only if there is no pending timer
          if ( pNewDevice->timeDelta == ZDAPP_NEW_DEVICE_TIME )
          {
            OsalPortTimers_startTimer( ZDAppTaskID, ZDO_NEW_DEVICE, ZDAPP_NEW_DEVICE_TIME );
          }

  • if ( pNewDevice )
    {
    timeDelta = pNewDevice->timeDelta;
    pNewDevice = pNewDevice->next;

    while ( pNewDevice )
    {
    //////////////////////////////////////////////////////////////////
    // 新设备timer 需要减去已经用去的时间获取剩余timer ,直到最有一个新入网设备
    pNewDevice->timeDelta -= timeDelta;
    //////////////////////////////////////////////////////////////////
    pNewDevice = pNewDevice->next;
    }
  • 我想问的是为什么pNewDevice->timeDelta = ZDAPP_NEW_DEVICE_TIME - timeToFire??
    如果第一个节点加入100ms后,第二个加入,此时第二个节点timeDelta = ZDAPP_NEW_DEVICE_TIME - 100 = 500
    第一个节点加入开启的ZDO_NEW_DEVICE时间到达,再次开启第二个节点的ZDO_NEW_DEVICE事件
    那么第二个节点的时间,不就不是ZDAPP_NEW_DEVICE_TIME ,而是2 * timeDelta = 1000了??
  • 你没看明白吧,当你ZDAPP_NEW_DEVICE_TIME有剩余不会再次开启ZDO_NEW_DEVICE事件。
    第二个节点会在
    while ( pNewDevice )
    {

    pNewDevice->timeDelta -= timeDelta;

    pNewDevice = pNewDevice->next;
    }
  • 如果只有两个节点
    第一个节点开启ZDO_NEW_DEVICE后,时间到达后,处理完成后

    pNewDevice = (ZDAppNewDevice_t *) ZDApp_NewDeviceList->next;
    osal_mem_free( ZDApp_NewDeviceList );//第一个节点就会删除
    ZDApp_NewDeviceList = pNewDevice;//第二个节点成为链表头

    if ( pNewDevice )
    {
    timeDelta = pNewDevice->timeDelta;
    pNewDevice = pNewDevice->next;//一共两个节点,所有这里为null,因此 while ( pNewDevice )不成立

    while ( pNewDevice )
    {
    pNewDevice->timeDelta -= timeDelta;
    pNewDevice = pNewDevice->next;
    }

    osal_start_timerEx( ZDAppTaskID, ZDO_NEW_DEVICE, timeDelta );
    //这里的时间不就是之前计算的timeDelta =ZDAPP_NEW_DEVICE_TIME - timeToFire
    }
  • 无非两种情况:
    1.第一个节点过程中,第二个节点已经加入了。list 里面会有两个节点timeDelta等于 第一个节点执行完成后剩余time ,第二个节点两个。
    2.第一个节点已经完成并且timer 为0 了。在if ( pNewDevice->timeDelta == ZDAPP_NEW_DEVICE_TIME ) the timer only if there is no pending timer重新开启一个ZDO_NEW_DEVICE。

    如果你有疑问可以去debug 观察一下。
  • 个人理解错误。
    Thanks Alvin!