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.

终端设备入网问题

Other Parts Discussed in Thread: CC2530

终端设备和路由器加入协调器网络之后,

1.如果协调器断电了,终端节点会加入路由器,如果协调器又上电了,发现协调器无法控制终端了?为什么?因为PANID和协调器不一样了吗?

2.如果把终端节点设置为只加入协调器(永远不加入路由器),那协调器断电再上电,终端节点能不能加入协调器?

3.如何把终端设备设置为只加入协调器,即使有路由也不加入路由器,协调器断电时一直再尝试加入协调器?

  • 1. 抓包才能知道為什麼,猜測是路由變了,需要等一段時間讓路由恢復
    2.&3. 沒辦法把终端设备设置为只加入协调器
  • 请提供抓包文件,
    2和3无法实现。
  • 是这样的,环境中有ZLL灯(第三方产品,是路由器)
    协调器和终端设备都是TI的CC2530,测试的时候,
    终端设备,和ZLL灯加入协调器后,某个时候,协调器重启了,
    发现重启后终端部分节点无法入网了,因为此时协调器变化了导致无法入网?
    (有部分终端可以入网,所有终端设备离协调器的距离都在10米内,无遮挡)
  • 只能通过抓包文件来判断原因
  • 你好,之前问你你说“如果你只想加入coordinator,可以在device state发生变化时,用NLME_GetCoordShortAddr()获取看看是不是coord。”
    现在怎么又说终端设备在协调器断电后,不能选择是加入协调器还是路由器?
    我想在协调器断电又上电时,终端设备还加入协调器?
  • NLME_GetCoordShortAddr 确实是获取父节点的地址,
    你的coordinator 是0x0000 ,coordinator 掉线后,end device 会连入路由。这是你无法选择,当你一个设备入网时会选择一个信号质量最好的入网,这是你无法改变的,你直接尝试做些逻辑看看能不能实现。

  • 现在的情况是,协调器重启后,因为节点加入了路由,协调器再上电后就控制不了节点了,
    原因未知,节点的短地址也变化了(即使开启了NV),因为上位机是通过协调器去控制所有的终端设备的,
    终端设备一旦加入路由,协调器和终端就无通信了,可有什么解决方案
  • 你要抓包,你从哪里得知短地址变化了?
  • 建议你咨询一下第三方产品那边,你可以看一下我发的帖子是一个正常的变化。
    e2echina.ti.com/.../169842
  • 在网上看到一个方法,在终端设备里把下面的函数里的部分参数修改一下
    如下把地址和深度都改为0,这样即使路由器存在,是不是协调器断电的时候,
    终端设备不会加入路由器?而协调器上电的时候,终端设备又加上了协调器
    void ZDO_beaconNotifyIndCB( NLME_beaconInd_t *pBeacon )
    {
    pNwkDesc->chosenRouter = 0;//默认INVALID_NODE_ADDR;
    pNwkDesc->chosenRouterDepth = 0;//默认0xFF;

    if ( ( (capacity) || ( pBeacon->sourceAddr == _NIB.nwkCoordAddress ) ) && (selected) )
    {
    // this is the new chosen router for joining...
    pNwkDesc->chosenRouter = 0;//默认pBeacon->sourceAddr;
    pNwkDesc->chosenRouterLinkQuality = pBeacon->LQI;
    pNwkDesc->chosenRouterDepth = 0;//默认pBeacon->depth;
    }
    }
  • 给你一个思路:
    在EndDevice的ZDO_beaconNotifyIndCB中加入类似逻辑:
    通过判断Beacon的source地址来判断。
    if ( pBeacon->sourceAddr == 0x0000 )
  • 改动后的函数如下,是否正确?

    void ZDO_beaconNotifyIndCB( NLME_beaconInd_t *pBeacon )
    {
    // Pass the beacon Indication to another task if it registers the callback
    // Otherwise, process the beacon notification here.
    if (zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID] != NULL )
    {
    zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID]( (void*)pBeacon );
    }
    else
    {
    networkDesc_t *pNwkDesc;
    networkDesc_t *pLastNwkDesc;
    uint8 found = false;

    // Add the network to the Network Descriptor List
    pNwkDesc = NwkDescList;
    pLastNwkDesc = NwkDescList;
    while (pNwkDesc)
    {
    if ((pNwkDesc->panId == pBeacon->panID) &&
    (pNwkDesc->logicalChannel == pBeacon->logicalChannel))
    {
    found = true;
    break;
    }
    pLastNwkDesc = pNwkDesc;
    pNwkDesc = pNwkDesc->nextDesc;
    }

    // If no existing descriptor found, make a new one and add to the list
    if (found == false)
    {
    pNwkDesc = osal_mem_alloc( sizeof(networkDesc_t) );
    if ( !pNwkDesc )
    {
    // Memory alloc failed, discard this beacon
    return;
    }

    // Clear the network descriptor
    osal_memset( pNwkDesc, 0, sizeof(networkDesc_t) );

    // Initialize the descriptor
    pNwkDesc->chosenRouter = 0;//默认INVALID_NODE_ADDR;
    pNwkDesc->chosenRouterDepth = 0;//默认0xFF;

    // Save new entry into the descriptor list
    if ( !NwkDescList )
    {
    NwkDescList = pNwkDesc;
    }
    else
    {
    pLastNwkDesc->nextDesc = pNwkDesc;
    }
    }

    // Update the descriptor with the incoming beacon
    pNwkDesc->stackProfile = pBeacon->stackProfile;
    pNwkDesc->version = pBeacon->protocolVersion;
    pNwkDesc->logicalChannel = pBeacon->logicalChannel;
    pNwkDesc->panId = pBeacon->panID;
    pNwkDesc->updateId = pBeacon->updateID;

    // Save the extended PAN ID from the beacon payload only if 1.1 version network
    if ( pBeacon->protocolVersion != ZB_PROT_V1_0 )
    {
    osal_cpyExtAddr( pNwkDesc->extendedPANID, pBeacon->extendedPanID );
    }
    else
    {
    osal_memset( pNwkDesc->extendedPANID, 0xFF, Z_EXTADDR_LEN );
    }

    // check if this device is a better choice to join...
    // ...dont bother checking assocPermit flag is doing a rejoin
    if ( ( pBeacon->LQI > gMIN_TREE_LQI ) &&
    ( ( pBeacon->permitJoining == TRUE ) || ( _tmpRejoinState ) ) )
    {
    uint8 selected = FALSE;
    uint8 capacity = FALSE;

    #if defined ( ZIGBEEPRO )
    if ( ((pBeacon->LQI > pNwkDesc->chosenRouterLinkQuality) &&
    (pBeacon->depth < MAX_NODE_DEPTH)) ||
    ((pBeacon->LQI == pNwkDesc->chosenRouterLinkQuality) &&
    (pBeacon->depth < pNwkDesc->chosenRouterDepth)) )
    {
    selected = TRUE;
    }
    #else
    if ( pBeacon->depth < pNwkDesc->chosenRouterDepth )
    {
    selected = TRUE;
    }
    #endif

    if ( ZSTACK_ROUTER_BUILD )
    {
    capacity = pBeacon->routerCapacity;
    }
    else if ( ZSTACK_END_DEVICE_BUILD )
    {
    capacity = pBeacon->deviceCapacity;
    }

    //if ( ( (capacity) || ( pBeacon->sourceAddr == _NIB.nwkCoordAddress ) ) && (selected) )

    if ( ( (capacity) || ( pBeacon->sourceAddr == 0x0000) ) && (selected) )
    {
    // this is the new chosen router for joining...
    pNwkDesc->chosenRouter = pBeacon->sourceAddr;
    pNwkDesc->chosenRouterLinkQuality = pBeacon->LQI;//这里要改?
    pNwkDesc->chosenRouterDepth = 0;//默认pBeacon->depth;
    }

    if ( pBeacon->deviceCapacity )
    pNwkDesc->deviceCapacity = 1;

    if ( pBeacon->routerCapacity )
    pNwkDesc->routerCapacity = 1;
    }
    }
    }

    另外,

    1.该函数的下面是否要修改?

    // Initialize the descriptor
    pNwkDesc->chosenRouter = 0;//默认INVALID_NODE_ADDR;
    pNwkDesc->chosenRouterDepth = 0;//默认0xFF;

    2.LQI需要修改吗?Depth改为0是否可以?

    pNwkDesc->chosenRouter = pBeacon->sourceAddr;
    pNwkDesc->chosenRouterLinkQuality = pBeacon->LQI;//这里要改?
    pNwkDesc->chosenRouterDepth = 0;//默认pBeacon->depth;

    2.做了上述修改后,终端在协调器断电后不会加入路由,再协调器再次上电后会加入协调器,是否可以实现?

  • 不建议你修改路由深度等其他内容,只要判断一下是不是coordinator 不是就忽略,我没有试过,理论上是可以的。你去试一下。
  • 那函数void ZDO_beaconNotifyIndCB( NLME_beaconInd_t *pBeacon )
    的下面部分修改为
    if ( ( (capacity) || ( pBeacon->sourceAddr == 0x0000) ) && (selected) )
    {
    // this is the new chosen router for joining...
    pNwkDesc->chosenRouter = pBeacon->sourceAddr;
    pNwkDesc->chosenRouterLinkQuality = pBeacon->LQI;
    pNwkDesc->chosenRouterDepth = pBeacon->depth;
    }
    还是
    if ( pBeacon->sourceAddr == 0x0000)
    {
    // this is the new chosen router for joining...
    pNwkDesc->chosenRouter = pBeacon->sourceAddr;
    pNwkDesc->chosenRouterLinkQuality = pBeacon->LQI;
    pNwkDesc->chosenRouterDepth = pBeacon->depth;
    }
  • 你差不多这样弄,不是coordinator就直接忽略它,也不执行下面的判断。PS由于ZDO这个文件是通用的,注意不要在ZC以及ZR也生效。
    if (zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID] != NULL )
    {
    zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID]( (void*)pBeacon );
    }
    else{

    if ( pBeacon->sourceAddr == 0x0000){
    ........


    }

    }
  • 那就是下面这样了,else的时候先判断是不是协调器,不是的话直接就不执行下面的了,
    如果是协调器在执行下面的语句
    void ZDO_beaconNotifyIndCB( NLME_beaconInd_t *pBeacon )
    {
    // Pass the beacon Indication to another task if it registers the callback
    // Otherwise, process the beacon notification here.
    if (zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID] != NULL )
    {
    zdoCBFunc[ZDO_BEACON_NOTIFY_IND_CBID]( (void*)pBeacon );
    }
    else
    {
    if ( pBeacon->sourceAddr == 0x0000)
    {
    ......
    }
    }