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

Parents
  • Hi Tu,

    I do not know of any functions to manually initiate route discovery that are visible to the application in our SDK. A lot of the NWK management and functions are internal parts of the ZBOSS stack, and thus not available to use. I have asked our developers if they know of any way to do this.

    I also have some questions to help me better understand your set up. Was the router originally in range of the coordinator, had it in it's neighbor table, and were able to communicate with it, before you moved it out of range? What kind of messages are the router trying to send to the coordinator? 

    And for the first condition to start a route discovery, when the router send route requests, the coordinator can definitely hear it

     Could you clarify this for me? Is the router sending route request commands to the coordinator, but the command is not received on the coordinator's side? From further up in your description it seemed like the problem is that the router does not try to initiate route discovery, even though the router is out of range and does not receive the packets, but now you are saying the router is sending a route request command and the coordinator is in range to receive this (but does not for some reason)?

    Best regards,

    Marte

  • Hi Marte,

    Here are some more elaborate infomation about my set up

    "Was the router originally in range of the coordinator, had it in it's neighbor table, and were able to communicate with it, before you moved it out of range? "   

    -Yes, they can communicate with the coordinator before they get out of range. For the neigbor table, i investigate the link status message of each and every one of the node, all of them have link to every other nodes. but the incomming cost and outgoing cost  of some links are very bad like 6 or 7.


    "What kind of messages are the router trying to send to the coordinator?"

    -i try to send a report attribute message made with  the function zb_aps_send_user_payload(). I just made up some data (data send, cluster, atrribute, etc) to do it. 


    "Is the router sending route request commands to the coordinator, but the command is not received on the coordinator's side? "  " Could you clarify this for me?"

    - Sorry for confusing you with my bad writing. So as I said i'd learnt that there are 2 cases for the router to start a route discovery, so i try to test them one by one. So, so for the first case, when the link status of the router is not having the link to coordinator(addr 0x0000), it did send route request. that is what i mean by "And for the first condition to start a route discovery, when the router send route requests, the coordinator can definitely hear it"

    But with the second case when i try to move the router out of range so that the message it sent does not have any MAC ACK return and the LQI very low (<20). I wait for about 2 mins and then i reset the device but notthing happen, no route request send.


    So for some more information, i only used the board as pca10059, pca10100, pca10056 with Zigbee SDK 4.1.0 The code for coordinator i used is the zigbee cli and the code for the router and the sdk_config is attach below

    /**
     * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     *
     * @defgroup zigbee_examples_light_bulb main.c
     * @{
     * @ingroup zigbee_examples
     * @brief Dimmable light sample (HA profile)
     */
    
    #include "sdk_config.h"
    #include "zboss_api.h"
    #include "zboss_api_addons.h"
    #include "zb_mem_config_med.h"
    #include "zb_ha_dimmable_light.h"
    #include "zb_error_handler.h"
    #include "zb_nrf52_internal.h"
    #include "zigbee_helpers.h"
    #include "nrf_timer.h"
    #include "bsp.h"
    #include "boards.h"
    #include "app_pwm.h"
    #include "app_timer.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrf_802154.h"
    
    
    #undef ZB_NWK_LINK_STATUS_PERIOD
    #define ZB_NWK_LINK_STATUS_PERIOD 0xa
    
    #undef ZB_NWK_ROUTER_AGE_LIMIT 
    #define ZB_NWK_ROUTER_AGE_LIMIT 1
    
    #define MAX_CHILDREN                      10                                    /**< The maximum amount of connected devices. Setting this value to 0 disables association to this device.  */
    #define IEEE_CHANNEL_MASK                 (1l << ZIGBEE_CHANNEL)                /**< Scan only one, predefined channel to find the coordinator. */
    #define HA_DIMMABLE_LIGHT_ENDPOINT        10                                    /**< Device endpoint, used to receive light controlling commands. */
    #define ERASE_PERSISTENT_CONFIG           ZB_FALSE                              /**< Do not erase NVRAM to save the network parameters after device reboot or power-off. */
    #define BULB_PWM_NAME                     PWM1                                  /**< PWM instance used to drive dimmable light bulb. */
    #define BULB_PWM_TIMER                    2                                     /**< Timer number used by PWM. */
    
    /* Basic cluster attributes initial values. */
    #define BULB_INIT_BASIC_APP_VERSION       01                                    /**< Version of the application software (1 byte). */
    #define BULB_INIT_BASIC_STACK_VERSION     10                                    /**< Version of the implementation of the Zigbee stack (1 byte). */
    #define BULB_INIT_BASIC_HW_VERSION        11                                    /**< Version of the hardware of the device (1 byte). */
    #define BULB_INIT_BASIC_MANUF_NAME        "Nordic"                              /**< Manufacturer name (32 bytes). */
    #define BULB_INIT_BASIC_MODEL_ID          "Dimable_Light_v0.1"                  /**< Model number assigned by manufacturer (32-bytes long string). */
    #define BULB_INIT_BASIC_DATE_CODE         "20180416"                            /**< First 8 bytes specify the date of manufacturer of the device in ISO 8601 format (YYYYMMDD). The rest (8 bytes) are manufacturer specific. */
    #define BULB_INIT_BASIC_POWER_SOURCE      ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE   /**< Type of power sources available for the device. For possible values see section 3.2.2.2.8 of ZCL specification. */
    #define BULB_INIT_BASIC_LOCATION_DESC     "Office desk"                         /**< Describes the physical location of the device (16 bytes). May be modified during commisioning process. */
    #define BULB_INIT_BASIC_PH_ENV            ZB_ZCL_BASIC_ENV_UNSPECIFIED          /**< Describes the type of physical environment. For possible values see section 3.2.2.2.10 of ZCL specification. */
    
    #ifdef  BOARD_PCA10059                                                          /**< If it is Dongle */
    #define IDENTIFY_MODE_BSP_EVT             BSP_EVENT_KEY_0                       /**< Button event used to enter the Bulb into the Identify mode. */
    #define ZIGBEE_NETWORK_STATE_LED          BSP_BOARD_LED_0                       /**< LED indicating that light switch successfully joind Zigbee network. */
    #else
    #define IDENTIFY_MODE_BSP_EVT             BSP_EVENT_KEY_3                       /**< Button event used to enter the Bulb into the Identify mode. */
    #define ZIGBEE_NETWORK_STATE_LED          BSP_BOARD_LED_2                       /**< LED indicating that light switch successfully joind Zigbee network. */
    #endif
    #define BULB_LED                          BSP_BOARD_LED_3                       /**< LED immitaing dimmable light bulb. */
    
    #if (APP_BULB_USE_WS2812_LED_CHAIN)
    #define LED_CHAIN_DOUT_PIN                NRF_GPIO_PIN_MAP(1,7)                 /**< GPIO pin used as DOUT (to be connected to DIN pin of the first ws2812 led in chain) */
    #endif
    
    /* Declare endpoint for Dimmable Light device with scenes. */
    #define ZB_HA_DECLARE_LIGHT_EP(ep_name, ep_id, cluster_list)                         \
    ZB_ZCL_DECLARE_HA_DIMMABLE_LIGHT_SIMPLE_DESC(ep_name, ep_id,                       \
      ZB_HA_DIMMABLE_LIGHT_IN_CLUSTER_NUM, ZB_HA_DIMMABLE_LIGHT_OUT_CLUSTER_NUM);      \
    ZBOSS_DEVICE_DECLARE_REPORTING_CTX(reporting_info## device_ctx_name,               \
     ZB_HA_DIMMABLE_LIGHT_REPORT_ATTR_COUNT);        \
    ZBOSS_DEVICE_DECLARE_LEVEL_CONTROL_CTX(cvc_alarm_info## device_ctx_name,           \
     ZB_HA_DIMMABLE_LIGHT_CVC_ATTR_COUNT);       \
    ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, ep_id, ZB_AF_HA_PROFILE_ID,                   \
      0,     \
      NULL,                 \
      ZB_ZCL_ARRAY_SIZE(cluster_list, zb_zcl_cluster_desc_t),\
      cluster_list,                                          \
      (zb_af_simple_desc_1_1_t*)&simple_desc_##ep_name,      \
      ZB_HA_DIMMABLE_LIGHT_REPORT_ATTR_COUNT,                \
      reporting_info## device_ctx_name,                      \
      ZB_HA_DIMMABLE_LIGHT_CVC_ATTR_COUNT,                   \
      cvc_alarm_info## device_ctx_name)
    
    #if !defined ZB_ROUTER_ROLE
    #error Define ZB_ROUTER_ROLE to compile light bulb (Router) source code.
    #endif
    
    APP_TIMER_DEF(timer);
    
    /* Main application customizable context. Stores all settings and static values. */
    typedef struct
    {
      zb_zcl_basic_attrs_ext_t         basic_attr;
      zb_zcl_identify_attrs_t          identify_attr;
      zb_zcl_scenes_attrs_t            scenes_attr;
      zb_zcl_groups_attrs_t            groups_attr;
      zb_zcl_on_off_attrs_ext_t        on_off_attr;
      zb_zcl_level_control_attrs_t     level_control_attr;
    } bulb_device_ctx_t;
    
    typedef struct
    {
        zb_uint16_t     attr_id;  /**< Attribute ID specific to cluster */
        zb_uint8_t      attr_type; /**< Attribute type (see @ref zb_zcl_attr_type_t) */
        zb_uint8_t      *data_p;   /**< Attribute data */
        zb_uint16_t     *data_p_16;   /**< Attribute data */
        zb_uint32_t     *data_p_32;   /**< Attribute data */
    } attr_info_t;
    
    typedef struct {
        zb_uint8_t      src_endpoint;  /*!< Source endpoint */
        zb_uint8_t      dst_addr_mode; /*!< Destinition address mode*/
        zb_addr_u       dst_addr;       /*!< Destinition address */
        zb_uint8_t      dst_endpoint;  /*!< Destinition endpoint */
        zb_uint16_t     profile_id;   /*!< Profile ID for reporting */
        zb_uint16_t     cluster_id;   /*!< Cluster ID for reporting */
        attr_info_t     attr_info[10];
    } reporting_info_t;
    
    static bulb_device_ctx_t m_dev_ctx;
    
    ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(identify_attr_list, &m_dev_ctx.identify_attr.identify_time);
    
    
    ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(groups_attr_list, &m_dev_ctx.groups_attr.name_support);
    
    ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(scenes_attr_list,
      &m_dev_ctx.scenes_attr.scene_count,
      &m_dev_ctx.scenes_attr.current_scene,
      &m_dev_ctx.scenes_attr.current_group,
      &m_dev_ctx.scenes_attr.scene_valid,
      &m_dev_ctx.scenes_attr.name_support);
    
    ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT(basic_attr_list,
     &m_dev_ctx.basic_attr.zcl_version,
     &m_dev_ctx.basic_attr.app_version,
     &m_dev_ctx.basic_attr.stack_version,
     &m_dev_ctx.basic_attr.hw_version,
     m_dev_ctx.basic_attr.mf_name,
     m_dev_ctx.basic_attr.model_id,
     m_dev_ctx.basic_attr.date_code,
     &m_dev_ctx.basic_attr.power_source,
     m_dev_ctx.basic_attr.location_id,
     &m_dev_ctx.basic_attr.ph_env,
     m_dev_ctx.basic_attr.sw_ver);
    
    /* On/Off cluster attributes additions data */
    ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST_EXT(on_off_attr_list,
      &m_dev_ctx.on_off_attr.on_off,
      &m_dev_ctx.on_off_attr.global_scene_ctrl,
      &m_dev_ctx.on_off_attr.on_time,
      &m_dev_ctx.on_off_attr.off_wait_time);
    
    ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST(level_control_attr_list,
     &m_dev_ctx.level_control_attr.current_level,
     &m_dev_ctx.level_control_attr.remaining_time);
    
    ZB_HA_DECLARE_DIMMABLE_LIGHT_CLUSTER_LIST(dimmable_light_clusters,
      basic_attr_list,
      identify_attr_list,
      groups_attr_list,
      scenes_attr_list,
      on_off_attr_list,
      level_control_attr_list);
    
    ZB_HA_DECLARE_LIGHT_EP(dimmable_light_ep,
     HA_DIMMABLE_LIGHT_ENDPOINT,
     dimmable_light_clusters);
    
    ZB_HA_DECLARE_DIMMABLE_LIGHT_CTX(dimmable_light_ctx,
     dimmable_light_ep);
    
    
    /**@brief Function for initializing the application timer.
     */
    static void timer_init(void)
    {
      uint32_t error_code = app_timer_init();
      APP_ERROR_CHECK(error_code);
    }
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
      ret_code_t err_code = NRF_LOG_INIT(NULL);
      APP_ERROR_CHECK(err_code);
    
      NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    void zboss_signal_handler(zb_bufid_t bufid)
    {
        /* Update network status LED */
      zb_zdo_app_signal_hdr_t  * p_sg_p      = NULL;
      zb_zdo_app_signal_type_t   sig         = zb_get_app_signal(bufid, &p_sg_p);
        /* No application-specific behavior is required. Call default signal handler. */
      switch (sig)
      {
        default:
        ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
        break;
      }
    
      if (bufid)
      {
        zb_buf_free(bufid);
      }
    }
    
    
    void _my_own_handler (void *p_context)
    {
      // static zb_bufid_t last_bufid = 0;
      // if(last_bufid != 0) zb_buf_free(last_bufid);
      zb_bufid_t bufid;
      bufid = zb_buf_get_out_func();
      if(bufid == 0 || bufid == 28) {
        zb_buf_free(bufid);
        return;
      }
      zb_addr_u addr = {
        .addr_short = 0x0000,
      };
      
      NRF_LOG_INFO("bufid %d", bufid);
      zb_uint8_t payload[8] = {0x08, 0, 0x0a, 0x55, 0x00, 0x21, 0x03, 0x00};
      payload[1] = bufid;
      if(ZB_JOINED() == 1)
        zb_aps_send_user_payload(bufid, addr, 0x0104, 0x55, 1, 1, 2, ZB_FALSE, payload, sizeof(payload));
      app_timer_start(timer, APP_TIMER_TICKS(6000), NULL);
    }
    /**@brief Function for application main entry.
     */
    int main(void)
    {
      zb_ret_t       zb_err_code;
      zb_ieee_addr_t ieee_addr;
    
        /* Initialize timer, logging system and GPIOs. */
      timer_init();
      log_init();
    
        /* Initialize Zigbee stack. */
      ZB_INIT("led_bulb");
        /* Set Zigbee stack logging level and traffic dump subsystem. */
      ZB_SET_TRACE_LEVEL(ZIGBEE_TRACE_LEVEL);
      ZB_SET_TRACE_MASK(ZIGBEE_TRACE_MASK);
      ZB_SET_TRAF_DUMP_OFF();
    
        /* Set device address to the value read from FICR registers. */
      zb_osif_get_ieee_eui64(ieee_addr);
      zb_set_long_address(ieee_addr);
    
        /* Set static long IEEE address. */
      zb_set_network_router_role(IEEE_CHANNEL_MASK);
      //zb_set_max_children(MAX_CHILDREN);
        zb_set_max_children(3);
      zigbee_erase_persistent_storage(ZB_FALSE);
      zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));
    
        /* Initialize application context structure. */
      UNUSED_RETURN_VALUE(ZB_MEMSET(&m_dev_ctx, 0, sizeof(m_dev_ctx)));
        /* Register callback for handling ZCL commands. */
        //ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
    
        /* Register dimmer switch device context (endpoints). */
      ZB_AF_REGISTER_DEVICE_CTX(&dimmable_light_ctx);
        /** Start Zigbee Stack. */
      zb_err_code = zboss_start_no_autostart();
      ZB_ERROR_CHECK(zb_err_code);
      app_timer_create(&timer, APP_TIMER_MODE_SINGLE_SHOT, _my_own_handler);
      app_timer_start(timer, APP_TIMER_TICKS(5000), NULL);
    
    
      while(1)
      {
        zboss_main_loop_iteration();
        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
      }
    }
    
    
    /**
     * @}
     */

    8510.sdk_config.h

    Thank you for your support

    Best regards,

    Tu

  • Hi Tu,

    Sorry for the delay. I have an update from the Zigbee team regarding the sniffer log you attached. I have copied their response below:

    In pcap file, the first procedure when the router 0xf392 started to look for a new route to the coordinator begins around 248th packet and seems to end successfully. I think the router was reset in that point. Then it sends ZCL commands to trigger looking for a new route one more time. A new route is also found this time but at 1008th packet the router 0xf392 seems to forget that it should send packets thru 0x1b67 instead of directly. It looks like a stack issue.
    How is reporting triggered? By ZBOSS or manually by the customer?

    I got this before I updated them about what you wrote in your last reply, so not all of it might be relevant if the problem is that the router still sees the coordinator. I have updated our Zigbee team with the updated information from you, and I have asked for clarification regarding your questions.

    Best regards,

    Marte

  • 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

Reply
  • 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

Children
  • 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

  • Hi Tu,

    Tu Hoang said:
    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.

     Yes, that seems to be the case. Because of the asymmetry in the coordinator's and router's transmit power, the coordinator is able to send packets to the router, but not the other way around, because the transmit power of the router is too low for the packet to reach the coordinator. Since the router receives link status from the coordinator, it believes the coordinator to be a neighbor, so it tries to send directly. So the solution would be to reduce the transmit power of the coordinator as well, so that it is unable to reach the router.

    Tu Hoang said:
    Is there a way for us to set the "send_via_routing" by ourself ?

    This is a part of the internal stack, which is precompiled, and is not forwarded to the SDK, so this is unfortunately not available in the code.

    Tu Hoang said:
    is there any way i can avoid the problem i currently have with this link symetry?

     If you are just going to test things as you have been doing now, it does not need to be symmetrical. In that case, you just need to make sure that the transmit power of both devices are such that they are unable to send packets to each other. Since the router still receives broadcasted messages from the coordinator, the transmit power of the coordinator is high enough that the router is still in range. Reducing the transmit power of the coordinator sufficiently so that the router is out of range would solve the problem.

    Best regards,

    Marte

  • Hi Marte,

    Thank you very much for your help,

    I understand the problem now, may be i will try to reduce the power of the coordinator sufficiently to be out of range, but to do so, can i measure the RSSI to approximately determine the range. I know there are some tools in NRF connect but it is for bluetooth, zigbee has the same antena so can i check the link symetry by that.

    Once again, thank you and have a good day,

    Best regards,

    Tu

  • Hi Tu,

    You can use the function zb_zdo_get_diag_data() to get RSSI. This will be the last known RSSI from a device with a specified short address. This will give the RSSI in energy level, but you can convert it to dBm with the function nrf_802154_dbm_from_energy_level_calculate().

    zb_uint8_t lqi, rssi;
    int8_t rssi_dbm;
    zb_zdo_get_diag_data(0x0000, &lqi, &rssi);
    rssi_dbm = nrf_802154_dbm_from_energy_level_calculate(rssi);

    Best regards,

    Marte

Related