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

Problem sending multiple diagnostic messages

Hello

I am contacting you because I have a problem with the "otThreadSendDiagnosticGet()" function.
In my program, I am trying to retrieve the list of RLOC16s of the children of all the routers in the Thread network.
My problem is that the "otThreadSendDiagnosticGet ()" command works once after it doesn't work anymore.

For example, if I have a network with a Leader and 2 routers:

  1. I get the RLOC16s from the routers on the network via the function "otThreadGetRouterInfo (thread_ot_instance_get (), i, & routerInfo)" (i is the index in the router table)
  2. I send the command "otThreadSendDiagnosticGet ()" to the first router on my list and wait for the response.
  3. When I received the response, I send the command "otThreadSendDiagnosticGet()" to the second router ... -> but here I have no more response




Do you have any idea why my other requests are not sending? (whereas if I send normal requests (requests to the "light" resource for example) in addition to diagnostic requests, these requests have no problem and go correctly)

Thank you

Parents Reply Children
  • Do you have any idea where the problem is coming from?

    Thank you

  • Not sure why it does not work for you, maybe there is something wrong with how you call the function, or on the node that receives the request. 

    I did a test on my own, and I have no problems with sending multiple diag requests:

    I used nRF5 SDK for Thread and Zigbee v4.1.0, and the simple_coap_server example for my test. Attaching main.c that you can use to test this on your own: 

    /**
     * Copyright (c) 2017 - 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 simple_coap_server_example_main main.c
     * @{
     * @ingroup simple_coap_server_example_example
     * @brief Simple CoAP Server Example Application main file.
     *
     * @details This example demonstrates a CoAP server application that provides resources to control BSP_LED_3
     *          via CoAP messages. It can be controlled by a board with related Simple CoAP Server application.
     */
    
    #include <stdint.h>
    
    #include "app_scheduler.h"
    #include "app_timer.h"
    #include "nrf_delay.h"
    #include "bsp_thread.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log.h"
    #include "nrf_log_default_backends.h"
    
    #include "thread_coap_utils.h"
    #include "thread_utils.h"
    
    #include <openthread/thread.h>
    #include <openthread/thread_ftd.h>
    #include <openthread/netdiag.h>
    
    #define SCHED_QUEUE_SIZE      32                              /**< Maximum number of events in the scheduler queue. */
    #define SCHED_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum app_scheduler event size. */
    
    static uint8_t        m_router_flag          = false;
    static uint8_t        m_diag_request         = false;
    
    /***************************************************************************************************
     * @section Buttons
     **************************************************************************************************/
    
    static void bsp_event_handler(bsp_event_t event)
    {
        switch(event)
        {
            case BSP_EVENT_KEY_3:
                thread_coap_utils_provisioning_enable_set(true);
                break;
    
            default:
                return;
        }
    }
    
    /***************************************************************************************************
     * @section Callbacks
     **************************************************************************************************/
    
    static void thread_state_changed_callback(uint32_t flags, void * p_context)
    {
        if (flags & OT_CHANGED_THREAD_ROLE)
        {
            switch (otThreadGetDeviceRole(p_context))
            {
                case OT_DEVICE_ROLE_CHILD:
                    m_router_flag = false;
                    break;
                case OT_DEVICE_ROLE_ROUTER:
                case OT_DEVICE_ROLE_LEADER:
                    m_router_flag = true;
                    break;
    
                case OT_DEVICE_ROLE_DISABLED:
                case OT_DEVICE_ROLE_DETACHED:
                default:
                    m_router_flag = false;
                    thread_coap_utils_provisioning_enable_set(false);
                    break;
            }
        }
    
        NRF_LOG_INFO("State changed! Flags: 0x%08x Current role: %d\r\n",
                     flags,
                     otThreadGetDeviceRole(p_context));
    
    }
    
    /***************************************************************************************************
     * @section Initialization
     **************************************************************************************************/
    
    /**@brief Function for initializing the Application Timer Module.
     */
    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();
    }
    
    
    /**@brief Function for initializing the Thread Board Support Package.
     */
    static void thread_bsp_init(void)
    {
        uint32_t error_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
        APP_ERROR_CHECK(error_code);
    
        error_code = bsp_thread_init(thread_ot_instance_get());
        APP_ERROR_CHECK(error_code);
    }
    
    
    /**@brief Function for initializing the Thread Stack.
     */
    static void thread_instance_init(void)
    {
        thread_configuration_t thread_configuration =
        {
            .radio_mode            = THREAD_RADIO_MODE_RX_ON_WHEN_IDLE,
            .autocommissioning     = true,
            .default_child_timeout = 10,
        };
    
        thread_init(&thread_configuration);
        thread_cli_init();
        thread_state_changed_callback_set(thread_state_changed_callback);
    }
    
    
    /**@brief Function for initializing the Constrained Application Protocol Module.
     */
    static void thread_coap_init(void)
    {
        thread_coap_utils_configuration_t thread_coap_configuration =
        {
            .coap_server_enabled               = true,
            .coap_client_enabled               = false,
            .configurable_led_blinking_enabled = false,
        };
    
        thread_coap_utils_init(&thread_coap_configuration);
    }
    
    
    /**@brief Function for initializing scheduler module.
     */
    static void scheduler_init(void)
    {
        APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    }
    
    void HandleDiagnosticGetResponse(                     otMessage *          aMessage,
                                                          const otMessageInfo *aMessageInfo,
                                                          void *               aContext)
    {
        NRF_LOG_INFO("Diag response");
        m_diag_request = false;
    }
    
    /***************************************************************************************************
     * @section Main
     **************************************************************************************************/
    
    int main(int argc, char * argv[])
    {
        log_init();
        scheduler_init();
        timer_init();
    
        // Initialize the Thread stack.
        thread_instance_init();
        thread_coap_init();
        thread_bsp_init();
    
        otRouterInfo routerInfo;
        otIp6Address ipv6rloc;
        uint8_t maxRouterId = 0;
        uint8_t nextRouterId = 0;
        uint8_t ipv6rloc_string[128];
        uint8_t tlvTypes[1] = {OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE};
    
        otThreadSetReceiveDiagnosticGetCallback(thread_ot_instance_get(), HandleDiagnosticGetResponse, NULL);
    
        while (true)
        {
            thread_process();
            app_sched_execute();
    
            if(m_router_flag && !m_diag_request)
            {
                
                maxRouterId = otThreadGetMaxRouterId(thread_ot_instance_get());
    
                while ((otThreadGetRouterInfo(thread_ot_instance_get(), nextRouterId, &routerInfo) != OT_ERROR_NONE) && (maxRouterId > nextRouterId))
                {
                    nextRouterId++;
                }
                if(nextRouterId < maxRouterId)
                {
                    sprintf(ipv6rloc_string, "fdde:ad00:beef:0:0:ff:fe00:%x", routerInfo.mRloc16);
                    otIp6AddressFromString(ipv6rloc_string, &ipv6rloc);
                    NRF_LOG_INFO("Sending diag get to address %s", nrf_log_push(ipv6rloc_string));
    
                    otThreadSendDiagnosticGet(thread_ot_instance_get(), &ipv6rloc, tlvTypes, 1);
                    m_diag_request = true;
                    nextRouterId++;
                }
                else
                {
                    nextRouterId = 0;
                    nrf_delay_ms(5000); // No more routers to request. Wait 5 seconds before next run
                }
            }
    
            if (NRF_LOG_PROCESS() == false)
            {
                thread_sleep();
            }
        }
    }
    
    /**
     *@}
     **/
    

Related