This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

[Zigbee-mesh] How to initiate the route discovery manually?

Hi everyone,

I am making a zigbee mesh with just coordinator and routers only. I intended to have the mesh to cover a very large areas with nodes that can be moved (not frequently). I am using SDK4.1.0, for coordiantor , i uploaded the CLI example inside and for the router  i used the exact same example of lilght bulb with the only change is that i exclude every parts relating to notification led or button.

Tell my if i am wrong but from what i learn, when the nodes send a message to another node, without having the address in the routing table it will initalise the route discovery by (1) sending route request or (2) after some time out when it did not received a MAC ACK from the node it try to send to. My expectation is that i will work like a charm since it is almost the same as the example but it did not. It has a really annoying that even with the router is very far from the coordinator, even with very low LQI and miss a lot of MAC ACKs, it still persistently try to send to the coordinator and not every try to broadcast route requeset. And for the first condition to start a route discovery, when the router send route requests, the coordinator can definitely hear it (i have a sniffer just right by coorfinator side).

So my question is that i want to start the route discovery manually to have better control over the mesh. is there any way i can do that. If not, is there any solution for the route discovery. 

Thank you in advances,

Best regards,

Tu

  • Hi Marte,

    Thank you for your reply,  the way i used to send report was by using this

            ZB_ZCL_FINISH_PACKET(buffer, cmd_ptr)                                                           \
            ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb); \
    

    It is what i wrote by referencing the write attribute command  in zb_zcl_commands.h which is used in CLI example. And I do the reporting at a constant interval of 10s by using a timer.

    I do not know if it has anything wrong with this method then so please forward this to them as well. If they need more information on the way i send, please let me know.

    Best regards,

    Tu

  • Hi Tu,

    I do not see any wrong with how you are sending the commands. Thank you for providing additional information!

    I have not gotten a response from the team yet, but I have pinged them. I also looked more into some of your earlier questions myself, and I do have some thoughts regarding them.

    Regarding next-hop address, you are correct that according to the specification it should be two octets, in order to contain the 16 bit network address. From my understanding, next_hop_addr_ref in zboss_api_internal.h does not contain the actual network address, but it is a reference to the address. This is why it is of type zb_uint8_t, and the size is 8 bits, because it is a pointer or reference, not the address. If you for example look at zb_zdo_routing_table_record_s, which is the format of the RoutingTableList record format of the mgmt_rtg_rsp command (Table 2.132 in the documentation you attached), then you will see that this has next_hop_addr (without the added _ref at the end), which is of the correct size (zb_uint16_t).

    As for the status field, it references zb_nwk_route_state_t which could give some more information, but that is not available in the SDK. A lot of the ZBOSS stack is precompiled and unavailable in the SDK, and sometimes you might find references to something, but not the actual definition of this. The file zboss_api_internal.h is used to move some internal parts so they are accessible, but this means that it might be difficult to understand everything that is going on, as a lot is still hidden in the stack. However, I looked up the same file in NCS (nRF Connect SDK), which is another SDK we have. Zigbee in this is also based on the ZBOSS stack, as nRF5 SDK is, but it is using a newer version of the stack. There I found that the status field of zb_nwk_routing_t instead referenced nwk_route_state, which can actually be found in NCS (though not in nRF5 SDK). It can be found here, but I have also copied it here:

    /**
     * @name NWK route state
     * @anchor nwk_route_state
    */
    /** @{ */
    #define ZB_NWK_ROUTE_STATE_ACTIVE               0U
    #define ZB_NWK_ROUTE_STATE_DISCOVERY_UNDERWAY   1U
    #define ZB_NWK_ROUTE_STATE_DISCOVERY_INACTIVE   2U
    #define ZB_NWK_ROUTE_STATE_VALIDATION_UNDERWAY  3U
    /* actually ZB_NWK_ROUTE_STATE_DISCOVERY_FAILED never used, so 2 bits are
     * enough for state */
    #define ZB_NWK_ROUTE_STATE_DISCOVERY_FAILED     4U
    #define ZB_NWK_ROUTE_STATE_NUM                  5U
    /** @} */

    So there you can both see what the different states are defined as, as well as the following:

    actually ZB_NWK_ROUTE_STATE_DISCOVERY_FAILED never used, so 2 bits are enough for state

    So I guess that is the explanation for why the status field is only 2 bits, and not 3 as in the specification. 

    I believe changing gc_neighbor_table should have an affect. Usually, in order to configure parameters like these, you would have to recompile the ZBOSS stack (which is already precompiled for the SDK, as I mentioned above). However, the file zb_mem_config_context.h gives the ability to change and configure some of these storage parameters without having to do so. So it seems like using that you can change this. You are mentioning gc_neighbor_table, which is the neighbor table. This will not affect the routing table, as they are two different things. Additionally, the only thing you can change regarding this is the size of the table.

    gc usually stands for garbage collection in regards to computer science. This is a form of memory management, where the garbage collector deallocate memory occupied by garbage, where garbage is memory that was allocated by the program, but is no longer referenced. It is used so that developers do not have to manually perform this memory management, but it instead happens automatically, depending on what and when the developer has specified it to do so. 

    Tu Hoang said:
    And I also notice that when I print out the neighbor table of a node connected directly to the coordinator, all entry by default will have the destination address is 0x0000 along every others parameters in zb_nwk_routing_t is 0, Is it means that they are not currently using any route from the routing table?

     I am a bit confused by this. Are you checking both the neighbor and routing table of the node? If you are talking about the neighbor entry of the coordinator, it makes sense that the address is 0x0000, as that will be the address of your coordinator. Which parameters in zb_nwk_routing_t are 0? And by zb_nwk_routing_t, do you mean the routing table entry in Table 3.56 in the documentation?

    This was what I was able to figure out after some digging. I hope it clarifies some of your questions, and if not, I will try to ask the developers again. As for your other questions, I am still waiting for an answer to them, but I will let you know when I have anything more to share.

    Best regards,

    Marte

  • Hi Marte,

    Thank you for your extremely detailed answer.

    I now understand the setting of members in the routing table struct. It is very thoughtful of you to explain them in such elaborated manner.  So in your answer, you mentioned "You are mentioning gc_neighbor_table, which is the neighbor table. This will not affect the routing table, as they are two different things. Additionally, the only thing you can change regarding this is the size of the table"  Does this means that the only thing that I can change in the neighbor table and routing table is the size of them? And if, for example, i just read out a few entry in the routing table and neighbor table, if i change parameter like the aging counter in the neighbor table to 3 so that routing request happen faster. Is it possible?

    Then, in the part where you got confuse, let me explain more clearly. The neighbor table and routing table here are refer to the data that i can log. I printed them both in every 5 seconds by using a loop. At that time, the node that i am monitor see like 3 neighbor (including the coordinator) and all the entry in the gc routing table are 0 which make it looks like the route for coordinator. So I just want to know if this is a normal behavior for zigbee.

    Thank you for your help,

    Best regards,

    Tu

  • Hi Tu,

    I am sorry for the delayed response. Our Zigbee team started an internal ticket with the developers of the ZBOSS stack, and got a response now with some comments regarding the stack's behavior and your tests. I will share their response with you here:

    1. Routing table entry lifetime is not infinite. When the routing table entry is used, an internal function to reset route expiry is called. If routing table entry is not used, i.e. this function is not called, it will expire after a timeout. This expiration timeout is decided by ZB_NWK_ROUTING_TABLE_EXPIRY and ZB_NWK_EXPIRY_PENDING:
      ZB_NWK_ROUTING_TABLE_EXPIRY (60) times * ZB_NWK_EXPIRY_PENDING (5s) = 300s.
    2. Sending a packet directly is better than sending it via routing. So it is not that the router forgets that it must send the packet via routing, but instead that it discovered that the packet can be sent directly, and will thus do that instead.
    3. Changing the transmit power with nrf_802154_tx_power_set() is probably causing an asymmetric link, where the TX power differs significantly, such that packets can go in one direction, but not in another.
      By default ZBOSS tries to send packets directly, but if another device has problems receiving the packets, there are other problems (bad RSSI/LQA), or it continues to send indirectly even after receiving a direct packet, the device is marked in the neighbor table as "send_via_routing" in order to not send directly.

    I hope this answers some of the questions you had!

    Best regards,

    Marte

  • Hi Marte,

    Thank you for your detail answer, but i just want to clarify this answer a little bit.

    So, basically, the sum up of your this answer is that the new route is unused because after some time, the router recognized that it could send the packet directly to the coordinator while actually it could not (due to router still receive the link status from coordinator). This makes the link is not maintain and expired after some time due to link asymetry. Is this correct, if it is it align with what i guess from previous message.

    Then, the reason i have nrf_802154_tx_power_set() is because i want to change the transmit power of the device so that its link become symetric. But it did not work so well, so as you can see in my code, i commented those lines.

    Next, your team said "if it continues to send indirectly even after receiving a direct packet, the device is marked in the neighbor table as "send_via_routing" in order to not send directly." in the third part of the answer. Is there a way for us to set the "send_via_routing" by ourself ?. Because,  as you can see, the router could only send 1 2 packet via routing and then it stopped.

    Finally, I just want to ask another question, is there any way i can avoid the problem i currently have with this link symetry? beside tuning the antena to a point where the transmit and receive ability is equal (which is kind of hard and i could not think of a way to do that since we do not have enough measure instrument). And then, How can i check to see if the 2 antena on two separate board have link symetry problem by using code or any other means? Next, if i use the nrf_802154_tx_power_set() to change the tx power to compensate for the antena, could it work for me. Finally, is there any recommendation for me to avoid this problem in the future.

    Once again thank you for your support,

    Best regards,

    Tu

Related