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

Thread Border Router networking fail

Hello Nordic Taam:

I follow the WEB steps below

https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_tz_v4.1.0%2Fthread_ot_performance_measurement.html

Software Development Kit > nRF5 SDK for Thread and Zigbee v4.1.0 > Thread > Thread tools > Thread Border Router

nRF52840 DK Version:nRF5_SDK_for_Thread_and_Zigbee_v4.1.0_32ce5f8\examples\thread\ncp\ftd\uart\hex

Raspberry Pi 3 Version:RaspPi_OT_Border_Router_Demo_v4.1.0-1.alpha

Use nRF52840 DK UART connect Raspberry Pi 3 to get the following information

wpan0 => [
"NCP:State" => "associating"
"Daemon:Enabled" => true
"NCP:Version" => "OPENTHREAD/20191113-00534-gc6a258e3; NRF52840; Apr 5 2020 21:51:18"
"Daemon:Version" => "0.08.00d (; Apr 21 2020 19:11:43)"
"Config:NCP:DriverName" => "spinel"
"NCP:HardwareAddress" => [F4CE363EC3C45B0E]
]


pi@raspberrypi:~ $ sudo wpanctl status
wpan0 => [
"NCP:State" => "uninitialized"
"Daemon:Enabled" => true
"NCP:Version" => ""
"Daemon:Version" => "0.08.00d (; Apr 21 2020 19:11:43)"
"Config:NCP:DriverName" => "spinel"
"NCP:HardwareAddress" => [F4CE363EC3C45B0E]
]

If I have the wrong steps or have not completed, please give me some pointers, thank you.

Also, can you teach me how to set up the Thread Border Router successfully on Raspberry Pi 3?

Best Regards

Rick.

Parents
  • Hi,

    The instructions on Thread Border Router is the latest and should be correct. It also looks like you are using the correct versions of the firmware and border router image. 

    I have tested this multiple times before, and have not had any issues with getting the network up and running.

    Are you using a revision 1 DK or later? Did you have the DK connected to the RPi before you booted it? Did you run 'erase all' command on the DK before flashing the NCP FW? You did not run any other commands on the border router prior to the "sudo wpanctl status" command?

    If nothing works, I would suggest that you start over and flash the DK and border router image again to the devices to see if that solves any issues.

    Best regards,
    Jørgen

  • Hi Jørgen:

    How are you today!

    Is there any update?

    Pls kindly help advise how to solve it?

    Best Regards,

    Rick.

  • Hi Jørgen:

    1. I try to do the DNS resolve command from the CLI, to check if you are able to get the IP from thethings.IO cloud solution, but it fails too.
    it is somehow blocked?
    Pls kindly help advise how to solve it?

    2. I need your help for me, assistance to double-check, My IP address support IPv4 or IPv6??

    3. I need your help for me, assistance to double-check, My Border Router can support IPv6 assign global IPv6 to the device?

    4. If I want to use CoAP sned get resource data of thething.io server from example thethings_io_coap, how I can modify it?
    I want to timer get resource data.

       

    Best Regards,

    Rick.

  • Hi Rick,

    1. Yes, it looks like there is something blocking you from reaching the address. Can you try to ping it (coap.thethings.io) from a computer in the same network?

    2. Since you are able to ping the 64:ff9b::0808:0808 address, you have IPv4 connectivity. You do not have global IPv6 connectivity, since you do not get a 200x:: address on the end nodes. This is either caused by the ISP not providing IPv6 address with large enough scope to allow subnetting to the required Thread /64 prefix, or the network equipment/router is preventing you from getting the correct prefix on the border router (you can see that the wlan0 from your ifconfig shows that you have a global address with /64 prefix, this needs to be /62 or lower to allow IPv6 connectivity to the Thread nodes).

    3. This is not something we can help you with. You need to check in your router/modem if you are assigned a large enough scope from your ISP, or you need to check with the manufacturer of the network equipment how you can configure it to assign larger prefix address to the border router.

    Best regards,
    Jørgen

  • Hi Jørgen,

    Thank you for your reply.

    1. I go to try to ping it (coap.thethings.io) from my computer and Raspberry Pi, it is successfully.
    What next step should do?

    2. If I want to use CoAP sned get resource data of thething.io server from example thethings_io_coap, how I can modify it?
    I want to timer get resource data.

    Best Regards,

    Rick.

  • Hi Rick,

    1. That is strange. Could be that the DNS is not able to resolve the address then. Are you able to resolve other addresses from the Thread CLI, for instance:

    dns resolve ipv4.google.com fdaa:bb:1::2

    2. We do not have any examples showing that, but you need to at least change the type from OT_COAP_CODE_POST to OT_COAP_CODE_GET in the otCoapMessageInit() call. I also believe that the resource name should be added to the CLOUD_URI_PATH. Further, I believe that the calls to otCoapMessageAppendContentFormatOption(), otCoapMessageSetPayloadMarker(), and otMessageAppend() can be removed. You also need to pass a response handler to the 4th parameter of the call to otCoapSendRequest(), which is where you will get the data when you receive the response from the cloud.

    Best regards,
    Jørgen

  • Hi Jørgen,

    Thank you for your reply.

    1. I use "fdaa:bb:1::2", can resolve other addresses from the Thread CLI. but "fdaa:bb:1::1" not can.
    "fdaa:bb:1::2" and "fdaa:bb:1::1" have any difference?

    2. I modify the CoAP code, but receive I got is not my topic data.

    I want to get my temp and counter data of CoAP topic.

    Pls kindly help advise how to solve it?

    /**
     * Copyright (c) 2019 - 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 thread_thethings_io_coap_client_example_main main.c
     * @{
     * @ingroup thread_thethings_io_coap_client_example_example
     * @brief Simple Cloud CoAP Client Example Application main file.
     *
     * @details This example demonstrates a CoAP client application that sends the
     *          counter and temperature values to the thethings.io cloud.
     *          Example uses NAT64 on the Nordic's Thread Border Router soulution
     *          for IPv4 connectivity.
     *
     */
    
    #include "app_scheduler.h"
    #include "app_timer.h"
    #include "bsp_thread.h"
    #include "nrf_temp.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log.h"
    #include "nrf_log_default_backends.h"
    
    #include "thread_dns_utils.h"
    #include "thread_utils.h"
    
    #include <openthread/coap.h>
    #include <openthread/ip6.h>
    #include <openthread/thread.h>
    
    /***************************************************************************************************
     * Put your Things's token in place of {THING-TOKEN} in the define below and uncomment it.
     **************************************************************************************************/
    #define CLOUD_URI_PATH                    "v2/things/GITM86uZNPu9Ukmja16PM-X-enajMxP01PODgS3tYVI"           /**< URI path of the thing resource. */
    
    #ifndef CLOUD_URI_PATH
    #error "Please define CLOUD_URI_PATH with the proper thethings.io token."
    #endif
    
    #define CLOUD_HOSTNAME                      "coap.thethings.io"                 /**< Hostname of the thethings.io cloud. */
    #define CLOUD_THING_RESOURCE_COUNTER        "counter"                           /**< Thing counter resource name. */
    #define CLOUD_THING_RESOURCE_TEMPERATURE    "temp"                              /**< Thing temperature resource name. */
    
    #define COUNTER_MIN                         0                                   /**< Minimal possible counter value. */
    #define COUNTER_MAX                         15                                  /**< Maximum possible counter value. */
    
    #define TEMP_MEASUREMENT_INTERVAL           5000                                /**< Temperature measurement interval in milliseconds. */
    
    #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. */
    
    APP_TIMER_DEF(m_temp_timer);
    
    static uint16_t     m_counter       = COUNTER_MIN;
    static int32_t      m_temperature   = 0;
    static otIp6Address m_cloud_address = {0};
    static bool         m_associated    = false;
    
    static void dns_response_handler(void               * p_context,
                                     const char         * p_hostname,
                                     const otIp6Address * p_resolved_address,
                                     uint32_t           ttl,
                                     otError            error)
    {
        if (error != OT_ERROR_NONE)
        {
            NRF_LOG_INFO("DNS response error %d.\r\n", error);
            return;
        }
    
        m_cloud_address = *p_resolved_address;
    }
    
    /**@brief CoAP response handler. */
    #define BUFFER_LENGTH                         512
    #define CONFIG_LED1 "LED1"
    #define CONFIG_LED2 "LED2"
    #define CONFIG_LED3 "LED3"
    #define CONFIG_LED4 "LED4"
    static void coap_response_handler(void                * p_context,
                                      otMessage           * p_message,
                                      const otMessageInfo * p_message_info,
                                      otError               result)
    {
        (void)p_message_info;
    
        // Handle payload only if its response for config option.
       // if (strncmp(p_context, GCP_COAP_IOT_CORE_CONFIG, strlen(GCP_COAP_IOT_CORE_CONFIG)) == 0)
        {
            do
            {
                if (otCoapMessageGetType(p_message) != OT_COAP_TYPE_NON_CONFIRMABLE)
                {
                    break;
                }
    
                if (otCoapMessageGetCode(p_message) != OT_COAP_CODE_CONTENT)
                {
                    break;
                }
    
                char     config[BUFFER_LENGTH];
                uint16_t config_length = 0;
    
                if ((config_length = otMessageRead(p_message, otMessageGetOffset(p_message), config, BUFFER_LENGTH - 1)) == 0)
                {
                    NRF_LOG_INFO("Config includes incorrect data\r\n");
                    break;
                }
    						NRF_LOG_INFO("%s, %d, length = %d, message = %s\r\n",__FUNCTION__,__LINE__,config_length,&config);
                ASSERT(config_length < BUFFER_LENGTH);
                config[config_length] = 0;
    
                LEDS_OFF(LEDS_MASK);
    
                if (strncmp(config, CONFIG_LED1, strlen(CONFIG_LED1)) == 0)
                {
                    LEDS_ON(BSP_LED_0_MASK);
                }
                else if (strncmp(config, CONFIG_LED2, strlen(CONFIG_LED2)) == 0)
                {
                    LEDS_ON(BSP_LED_1_MASK);
                }
                else if (strncmp(config, CONFIG_LED3, strlen(CONFIG_LED3)) == 0)
                {
                    LEDS_ON(BSP_LED_2_MASK);
                }
                else if (strncmp(config, CONFIG_LED4, strlen(CONFIG_LED4)) == 0)
                {
                    LEDS_ON(BSP_LED_3_MASK);
                }
            } while (false);
        }
    }
    
    /***************************************************************************************************
     * @section TheThings.io
     **************************************************************************************************/
    
    static void coap_client_cloud_update(void)
    {
        char            payload_buffer[128];
        otError         error;
        otMessage     * p_request;
        otMessageInfo   message_info;
        otInstance    * p_instance = thread_ot_instance_get();
    
        if (m_associated == false)
        {
            return;
        }
    
        // If IPv6 address of the cloud is unspecified try to resolve hostname.
        if (otIp6IsAddressUnspecified(&m_cloud_address))
        {
            error = thread_dns_utils_hostname_resolve(CLOUD_HOSTNAME,
                                                      dns_response_handler,
                                                      NULL);
            ASSERT(error == OT_ERROR_NONE);
            return;
        }
    
        // Construct JSON object acceptable by TheThings.io cloud.
        UNUSED_RETURN_VALUE(snprintf(payload_buffer, sizeof(payload_buffer),
                            "{\"values\":[{\"key\":\"%s\",\"value\":\"%d\"},{\"key\":\"%s\",\"value\":\"%ld\"}]}",
                            CLOUD_THING_RESOURCE_COUNTER, m_counter, CLOUD_THING_RESOURCE_TEMPERATURE, m_temperature));
    
        do
        {
            p_request = otCoapNewMessage(p_instance, NULL);
            if (p_request == NULL)
            {
                NRF_LOG_INFO("Failed to allocate message for CoAP Request\r\n");
                break;
            }
    
            otCoapMessageInit(p_request, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_GET);
            otCoapMessageGenerateToken(p_request, 4);
    
            error = otCoapMessageAppendUriPathOptions(p_request, CLOUD_URI_PATH);
            ASSERT(error == OT_ERROR_NONE);
    
            /*error = otCoapMessageAppendContentFormatOption(p_request, OT_COAP_OPTION_CONTENT_FORMAT_JSON);
            ASSERT(error == OT_ERROR_NONE);
    
            error = otCoapMessageSetPayloadMarker(p_request);
            ASSERT(error == OT_ERROR_NONE);
    
            error = otMessageAppend(p_request, payload_buffer, strlen(payload_buffer));
            if (error != OT_ERROR_NONE)
            {
                break;
            }
    */
            memset(&message_info, 0, sizeof(message_info));
            message_info.mPeerPort = OT_DEFAULT_COAP_PORT;
            message_info.mPeerAddr = m_cloud_address;
    
            error = otCoapSendRequest(p_instance, p_request, &message_info, coap_response_handler, NULL);
    
        } while (false);
    
        if ((error != OT_ERROR_NONE) && (p_request != NULL))
        {
            NRF_LOG_INFO("Failed to send CoAP Request: %d\r\n", error);
            otMessageFree(p_request);
        }
    }
    
    
    /***************************************************************************************************
     * @section Buttons
     **************************************************************************************************/
    
    static void bsp_event_handler(bsp_event_t event)
    {
        switch (event)
        {
            case BSP_EVENT_KEY_2:
                if (m_counter == COUNTER_MIN)
                {
                    // The minimal counter value has been already reached.
                    break;
                }
    
                // Decrement the counter value.
                m_counter -= 1;
    
                coap_client_cloud_update();
                break;
    
            case BSP_EVENT_KEY_3:
                if (m_counter == COUNTER_MAX)
                {
                    // The maximum counter value has been already reached.
                    break;
                }
    
                // Increment the counter value.
                m_counter += 1;
    
                coap_client_cloud_update();
                break;
    
            default:
                return; // no implementation needed
        }
    }
    
    /***************************************************************************************************
     * @section Callbacks
     **************************************************************************************************/
    
    static void thread_state_changed_callback(uint32_t flags, void * p_context)
    {
        otError      error      = OT_ERROR_NONE;
        otInstance * p_instance = thread_ot_instance_get();
    
        UNUSED_PARAMETER(p_context);
    
        if (flags & OT_CHANGED_THREAD_ROLE)
        {
            switch (otThreadGetDeviceRole(p_instance))
            {
                case OT_DEVICE_ROLE_CHILD:
                case OT_DEVICE_ROLE_ROUTER:
                case OT_DEVICE_ROLE_LEADER:
                    m_associated = true;
    
                    APP_ERROR_CHECK(app_timer_start(m_temp_timer, APP_TIMER_TICKS(TEMP_MEASUREMENT_INTERVAL), NULL));
    
                    error = thread_dns_utils_hostname_resolve(CLOUD_HOSTNAME,
                                                              dns_response_handler,
                                                              NULL);
                    ASSERT(error == OT_ERROR_NONE);
                    break;
    
                case OT_DEVICE_ROLE_DISABLED:
                case OT_DEVICE_ROLE_DETACHED:
                    m_associated = false;
    
                    APP_ERROR_CHECK(app_timer_stop(m_temp_timer));
    
                    // Clear IPv6 address of the TheThings.io cloud.
                    memset(&m_cloud_address, 0, sizeof(m_cloud_address));
                    break;
    
                default:
                    break;
            }
        }
    
        NRF_LOG_INFO("State changed! Flags: 0x%08x Current role: %d\r\n", flags,
                     otThreadGetDeviceRole(p_instance));
    }
    
    /**@brief Temperature measurement timer handler. */
    static void temp_timer_handler(void * p_context)
    {
        (void)p_context;
    
        NRF_TEMP->TASKS_START = 1;
        /* Busy wait while temperature measurement is not finished. */
        while (NRF_TEMP->EVENTS_DATARDY == 0)
        {
            // Do nothing.
        }
        NRF_TEMP->EVENTS_DATARDY = 0;
    
        int32_t temp = nrf_temp_read() / 4;
    
        NRF_TEMP->TASKS_STOP = 1;
    
        if (m_temperature != temp)
        {
            m_temperature = temp;
            coap_client_cloud_update();
        }
    }
    
    /***************************************************************************************************
     * @section Initialization
     **************************************************************************************************/
    
     /**@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 Application Timer Module
     */
    static void timer_init(void)
    {
        uint32_t error_code = app_timer_init();
        APP_ERROR_CHECK(error_code);
    
        error_code = app_timer_create(&m_temp_timer,
                                      APP_TIMER_MODE_REPEATED,
                                      temp_timer_handler);
        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 Stack
     */
    static void thread_instance_init(void)
    {
        thread_configuration_t thread_configuration =
        {
            .radio_mode        = THREAD_RADIO_MODE_RX_ON_WHEN_IDLE,
            .autocommissioning = true,
        };
    
        thread_init(&thread_configuration);
        thread_cli_init();
        thread_state_changed_callback_set(thread_state_changed_callback);
    }
    
    
    /**@brief Default handler for unhandled CoAP requests.
     */
    static void coap_default_handler(void                * p_context,
                                     otMessage           * p_message,
                                     const otMessageInfo * p_message_info)
    {
        (void)p_context;
        (void)p_message;
        (void)p_message_info;
    
        NRF_LOG_INFO("Received CoAP message that does not match any request or resource\r\n");
    }
    
    
    /**@brief Function for initializing CoAP client module.
     */
    static void coap_client_init(void)
    {
        otInstance * p_instance = thread_ot_instance_get();
    
        otError error = otCoapStart(p_instance, OT_DEFAULT_COAP_PORT);
        ASSERT(error == OT_ERROR_NONE);
    
        otCoapSetDefaultHandler(p_instance, coap_default_handler, NULL);
    }
    
    
    /**@brief Function for initializing scheduler module.
     */
    static void scheduler_init(void)
    {
        APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    }
    
    /***************************************************************************************************
     * @section Main
     **************************************************************************************************/
    
    int main(int argc, char * argv[])
    {
        log_init();
        scheduler_init();
        timer_init();
        nrf_temp_init();
    
        thread_instance_init();
        thread_bsp_init();
    
        coap_client_init();
    
        while (true)
        {
            thread_process();
            app_sched_execute();
    
            if (NRF_LOG_PROCESS() == false)
            {
                thread_sleep();
            }
        }
    }
    
    /**
     *@}
     **/
    

    Best Regards,

    Rick

Reply
  • Hi Jørgen,

    Thank you for your reply.

    1. I use "fdaa:bb:1::2", can resolve other addresses from the Thread CLI. but "fdaa:bb:1::1" not can.
    "fdaa:bb:1::2" and "fdaa:bb:1::1" have any difference?

    2. I modify the CoAP code, but receive I got is not my topic data.

    I want to get my temp and counter data of CoAP topic.

    Pls kindly help advise how to solve it?

    /**
     * Copyright (c) 2019 - 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 thread_thethings_io_coap_client_example_main main.c
     * @{
     * @ingroup thread_thethings_io_coap_client_example_example
     * @brief Simple Cloud CoAP Client Example Application main file.
     *
     * @details This example demonstrates a CoAP client application that sends the
     *          counter and temperature values to the thethings.io cloud.
     *          Example uses NAT64 on the Nordic's Thread Border Router soulution
     *          for IPv4 connectivity.
     *
     */
    
    #include "app_scheduler.h"
    #include "app_timer.h"
    #include "bsp_thread.h"
    #include "nrf_temp.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log.h"
    #include "nrf_log_default_backends.h"
    
    #include "thread_dns_utils.h"
    #include "thread_utils.h"
    
    #include <openthread/coap.h>
    #include <openthread/ip6.h>
    #include <openthread/thread.h>
    
    /***************************************************************************************************
     * Put your Things's token in place of {THING-TOKEN} in the define below and uncomment it.
     **************************************************************************************************/
    #define CLOUD_URI_PATH                    "v2/things/GITM86uZNPu9Ukmja16PM-X-enajMxP01PODgS3tYVI"           /**< URI path of the thing resource. */
    
    #ifndef CLOUD_URI_PATH
    #error "Please define CLOUD_URI_PATH with the proper thethings.io token."
    #endif
    
    #define CLOUD_HOSTNAME                      "coap.thethings.io"                 /**< Hostname of the thethings.io cloud. */
    #define CLOUD_THING_RESOURCE_COUNTER        "counter"                           /**< Thing counter resource name. */
    #define CLOUD_THING_RESOURCE_TEMPERATURE    "temp"                              /**< Thing temperature resource name. */
    
    #define COUNTER_MIN                         0                                   /**< Minimal possible counter value. */
    #define COUNTER_MAX                         15                                  /**< Maximum possible counter value. */
    
    #define TEMP_MEASUREMENT_INTERVAL           5000                                /**< Temperature measurement interval in milliseconds. */
    
    #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. */
    
    APP_TIMER_DEF(m_temp_timer);
    
    static uint16_t     m_counter       = COUNTER_MIN;
    static int32_t      m_temperature   = 0;
    static otIp6Address m_cloud_address = {0};
    static bool         m_associated    = false;
    
    static void dns_response_handler(void               * p_context,
                                     const char         * p_hostname,
                                     const otIp6Address * p_resolved_address,
                                     uint32_t           ttl,
                                     otError            error)
    {
        if (error != OT_ERROR_NONE)
        {
            NRF_LOG_INFO("DNS response error %d.\r\n", error);
            return;
        }
    
        m_cloud_address = *p_resolved_address;
    }
    
    /**@brief CoAP response handler. */
    #define BUFFER_LENGTH                         512
    #define CONFIG_LED1 "LED1"
    #define CONFIG_LED2 "LED2"
    #define CONFIG_LED3 "LED3"
    #define CONFIG_LED4 "LED4"
    static void coap_response_handler(void                * p_context,
                                      otMessage           * p_message,
                                      const otMessageInfo * p_message_info,
                                      otError               result)
    {
        (void)p_message_info;
    
        // Handle payload only if its response for config option.
       // if (strncmp(p_context, GCP_COAP_IOT_CORE_CONFIG, strlen(GCP_COAP_IOT_CORE_CONFIG)) == 0)
        {
            do
            {
                if (otCoapMessageGetType(p_message) != OT_COAP_TYPE_NON_CONFIRMABLE)
                {
                    break;
                }
    
                if (otCoapMessageGetCode(p_message) != OT_COAP_CODE_CONTENT)
                {
                    break;
                }
    
                char     config[BUFFER_LENGTH];
                uint16_t config_length = 0;
    
                if ((config_length = otMessageRead(p_message, otMessageGetOffset(p_message), config, BUFFER_LENGTH - 1)) == 0)
                {
                    NRF_LOG_INFO("Config includes incorrect data\r\n");
                    break;
                }
    						NRF_LOG_INFO("%s, %d, length = %d, message = %s\r\n",__FUNCTION__,__LINE__,config_length,&config);
                ASSERT(config_length < BUFFER_LENGTH);
                config[config_length] = 0;
    
                LEDS_OFF(LEDS_MASK);
    
                if (strncmp(config, CONFIG_LED1, strlen(CONFIG_LED1)) == 0)
                {
                    LEDS_ON(BSP_LED_0_MASK);
                }
                else if (strncmp(config, CONFIG_LED2, strlen(CONFIG_LED2)) == 0)
                {
                    LEDS_ON(BSP_LED_1_MASK);
                }
                else if (strncmp(config, CONFIG_LED3, strlen(CONFIG_LED3)) == 0)
                {
                    LEDS_ON(BSP_LED_2_MASK);
                }
                else if (strncmp(config, CONFIG_LED4, strlen(CONFIG_LED4)) == 0)
                {
                    LEDS_ON(BSP_LED_3_MASK);
                }
            } while (false);
        }
    }
    
    /***************************************************************************************************
     * @section TheThings.io
     **************************************************************************************************/
    
    static void coap_client_cloud_update(void)
    {
        char            payload_buffer[128];
        otError         error;
        otMessage     * p_request;
        otMessageInfo   message_info;
        otInstance    * p_instance = thread_ot_instance_get();
    
        if (m_associated == false)
        {
            return;
        }
    
        // If IPv6 address of the cloud is unspecified try to resolve hostname.
        if (otIp6IsAddressUnspecified(&m_cloud_address))
        {
            error = thread_dns_utils_hostname_resolve(CLOUD_HOSTNAME,
                                                      dns_response_handler,
                                                      NULL);
            ASSERT(error == OT_ERROR_NONE);
            return;
        }
    
        // Construct JSON object acceptable by TheThings.io cloud.
        UNUSED_RETURN_VALUE(snprintf(payload_buffer, sizeof(payload_buffer),
                            "{\"values\":[{\"key\":\"%s\",\"value\":\"%d\"},{\"key\":\"%s\",\"value\":\"%ld\"}]}",
                            CLOUD_THING_RESOURCE_COUNTER, m_counter, CLOUD_THING_RESOURCE_TEMPERATURE, m_temperature));
    
        do
        {
            p_request = otCoapNewMessage(p_instance, NULL);
            if (p_request == NULL)
            {
                NRF_LOG_INFO("Failed to allocate message for CoAP Request\r\n");
                break;
            }
    
            otCoapMessageInit(p_request, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_GET);
            otCoapMessageGenerateToken(p_request, 4);
    
            error = otCoapMessageAppendUriPathOptions(p_request, CLOUD_URI_PATH);
            ASSERT(error == OT_ERROR_NONE);
    
            /*error = otCoapMessageAppendContentFormatOption(p_request, OT_COAP_OPTION_CONTENT_FORMAT_JSON);
            ASSERT(error == OT_ERROR_NONE);
    
            error = otCoapMessageSetPayloadMarker(p_request);
            ASSERT(error == OT_ERROR_NONE);
    
            error = otMessageAppend(p_request, payload_buffer, strlen(payload_buffer));
            if (error != OT_ERROR_NONE)
            {
                break;
            }
    */
            memset(&message_info, 0, sizeof(message_info));
            message_info.mPeerPort = OT_DEFAULT_COAP_PORT;
            message_info.mPeerAddr = m_cloud_address;
    
            error = otCoapSendRequest(p_instance, p_request, &message_info, coap_response_handler, NULL);
    
        } while (false);
    
        if ((error != OT_ERROR_NONE) && (p_request != NULL))
        {
            NRF_LOG_INFO("Failed to send CoAP Request: %d\r\n", error);
            otMessageFree(p_request);
        }
    }
    
    
    /***************************************************************************************************
     * @section Buttons
     **************************************************************************************************/
    
    static void bsp_event_handler(bsp_event_t event)
    {
        switch (event)
        {
            case BSP_EVENT_KEY_2:
                if (m_counter == COUNTER_MIN)
                {
                    // The minimal counter value has been already reached.
                    break;
                }
    
                // Decrement the counter value.
                m_counter -= 1;
    
                coap_client_cloud_update();
                break;
    
            case BSP_EVENT_KEY_3:
                if (m_counter == COUNTER_MAX)
                {
                    // The maximum counter value has been already reached.
                    break;
                }
    
                // Increment the counter value.
                m_counter += 1;
    
                coap_client_cloud_update();
                break;
    
            default:
                return; // no implementation needed
        }
    }
    
    /***************************************************************************************************
     * @section Callbacks
     **************************************************************************************************/
    
    static void thread_state_changed_callback(uint32_t flags, void * p_context)
    {
        otError      error      = OT_ERROR_NONE;
        otInstance * p_instance = thread_ot_instance_get();
    
        UNUSED_PARAMETER(p_context);
    
        if (flags & OT_CHANGED_THREAD_ROLE)
        {
            switch (otThreadGetDeviceRole(p_instance))
            {
                case OT_DEVICE_ROLE_CHILD:
                case OT_DEVICE_ROLE_ROUTER:
                case OT_DEVICE_ROLE_LEADER:
                    m_associated = true;
    
                    APP_ERROR_CHECK(app_timer_start(m_temp_timer, APP_TIMER_TICKS(TEMP_MEASUREMENT_INTERVAL), NULL));
    
                    error = thread_dns_utils_hostname_resolve(CLOUD_HOSTNAME,
                                                              dns_response_handler,
                                                              NULL);
                    ASSERT(error == OT_ERROR_NONE);
                    break;
    
                case OT_DEVICE_ROLE_DISABLED:
                case OT_DEVICE_ROLE_DETACHED:
                    m_associated = false;
    
                    APP_ERROR_CHECK(app_timer_stop(m_temp_timer));
    
                    // Clear IPv6 address of the TheThings.io cloud.
                    memset(&m_cloud_address, 0, sizeof(m_cloud_address));
                    break;
    
                default:
                    break;
            }
        }
    
        NRF_LOG_INFO("State changed! Flags: 0x%08x Current role: %d\r\n", flags,
                     otThreadGetDeviceRole(p_instance));
    }
    
    /**@brief Temperature measurement timer handler. */
    static void temp_timer_handler(void * p_context)
    {
        (void)p_context;
    
        NRF_TEMP->TASKS_START = 1;
        /* Busy wait while temperature measurement is not finished. */
        while (NRF_TEMP->EVENTS_DATARDY == 0)
        {
            // Do nothing.
        }
        NRF_TEMP->EVENTS_DATARDY = 0;
    
        int32_t temp = nrf_temp_read() / 4;
    
        NRF_TEMP->TASKS_STOP = 1;
    
        if (m_temperature != temp)
        {
            m_temperature = temp;
            coap_client_cloud_update();
        }
    }
    
    /***************************************************************************************************
     * @section Initialization
     **************************************************************************************************/
    
     /**@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 Application Timer Module
     */
    static void timer_init(void)
    {
        uint32_t error_code = app_timer_init();
        APP_ERROR_CHECK(error_code);
    
        error_code = app_timer_create(&m_temp_timer,
                                      APP_TIMER_MODE_REPEATED,
                                      temp_timer_handler);
        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 Stack
     */
    static void thread_instance_init(void)
    {
        thread_configuration_t thread_configuration =
        {
            .radio_mode        = THREAD_RADIO_MODE_RX_ON_WHEN_IDLE,
            .autocommissioning = true,
        };
    
        thread_init(&thread_configuration);
        thread_cli_init();
        thread_state_changed_callback_set(thread_state_changed_callback);
    }
    
    
    /**@brief Default handler for unhandled CoAP requests.
     */
    static void coap_default_handler(void                * p_context,
                                     otMessage           * p_message,
                                     const otMessageInfo * p_message_info)
    {
        (void)p_context;
        (void)p_message;
        (void)p_message_info;
    
        NRF_LOG_INFO("Received CoAP message that does not match any request or resource\r\n");
    }
    
    
    /**@brief Function for initializing CoAP client module.
     */
    static void coap_client_init(void)
    {
        otInstance * p_instance = thread_ot_instance_get();
    
        otError error = otCoapStart(p_instance, OT_DEFAULT_COAP_PORT);
        ASSERT(error == OT_ERROR_NONE);
    
        otCoapSetDefaultHandler(p_instance, coap_default_handler, NULL);
    }
    
    
    /**@brief Function for initializing scheduler module.
     */
    static void scheduler_init(void)
    {
        APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    }
    
    /***************************************************************************************************
     * @section Main
     **************************************************************************************************/
    
    int main(int argc, char * argv[])
    {
        log_init();
        scheduler_init();
        timer_init();
        nrf_temp_init();
    
        thread_instance_init();
        thread_bsp_init();
    
        coap_client_init();
    
        while (true)
        {
            thread_process();
            app_sched_execute();
    
            if (NRF_LOG_PROCESS() == false)
            {
                thread_sleep();
            }
        }
    }
    
    /**
     *@}
     **/
    

    Best Regards,

    Rick

Children
  • Hi Rick,

    1. "fdaa:bb:1::2" is he address of the NAT64 interface, which redirects the dns request to the DNS64 service. See your ifconfig output:

    nat64: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
            inet 192.168.255.1  netmask 255.255.255.255  destination 192.168.255.1
            inet6 fe80::8370:ba52:f49e:93f6  prefixlen 64  scopeid 0x20<link>
            inet6 fdaa:bb:1::2  prefixlen 128  scopeid 0x0<global>
            unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)
            RX packets 264  bytes 31313 (30.5 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 268  bytes 31457 (30.7 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    2. Looks like the URI also needs to include "/resources/". I checked that this code works for getting the counter-value from thethings.io cloud by pressing button 4 (make sure to input your token ID):

    /**
     * Copyright (c) 2019 - 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 thread_thethings_io_coap_client_example_main main.c
     * @{
     * @ingroup thread_thethings_io_coap_client_example_example
     * @brief Simple Cloud CoAP Client Example Application main file.
     *
     * @details This example demonstrates a CoAP client application that sends the
     *          counter and temperature values to the thethings.io cloud.
     *          Example uses NAT64 on the Nordic's Thread Border Router soulution
     *          for IPv4 connectivity.
     *
     */
    
    #include "app_scheduler.h"
    #include "app_timer.h"
    #include "bsp_thread.h"
    #include "nrf_temp.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log.h"
    #include "nrf_log_default_backends.h"
    
    #include "thread_dns_utils.h"
    #include "thread_utils.h"
    
    #include <openthread/coap.h>
    #include <openthread/ip6.h>
    #include <openthread/thread.h>
    
    /***************************************************************************************************
     * Put your Things's token in place of {THING-TOKEN} in the define below and uncomment it.
     **************************************************************************************************/
    #define CLOUD_URI_PATH                    "v2/things/{THINGS_TOKEN}/resources/counter"           /**< URI path of the thing resource. */
    
    #ifndef CLOUD_URI_PATH
    #error "Please define CLOUD_URI_PATH with the proper thethings.io token."
    #endif
    
    #define CLOUD_HOSTNAME                      "coap.thethings.io"                 /**< Hostname of the thethings.io cloud. */
    #define CLOUD_THING_RESOURCE_COUNTER        "counter"                           /**< Thing counter resource name. */
    #define CLOUD_THING_RESOURCE_TEMPERATURE    "temp"                              /**< Thing temperature resource name. */
    
    #define COUNTER_MIN                         0                                   /**< Minimal possible counter value. */
    #define COUNTER_MAX                         15                                  /**< Maximum possible counter value. */
    
    #define TEMP_MEASUREMENT_INTERVAL           5000                                /**< Temperature measurement interval in milliseconds. */
    
    #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. */
    
    APP_TIMER_DEF(m_temp_timer);
    
    static uint16_t     m_counter       = COUNTER_MIN;
    static int32_t      m_temperature   = 0;
    static otIp6Address m_cloud_address = {0};
    static bool         m_associated    = false;
    
    static void dns_response_handler(void               * p_context,
                                     const char         * p_hostname,
                                     const otIp6Address * p_resolved_address,
                                     uint32_t           ttl,
                                     otError            error)
    {
        if (error != OT_ERROR_NONE)
        {
            NRF_LOG_INFO("DNS response error %d.\r\n", error);
            return;
        }
    
        m_cloud_address = *p_resolved_address;
    }
    
    /***************************************************************************************************
     * @section TheThings.io
     **************************************************************************************************/
    
    
    static void provisioning_response_handler(void                * p_context,
                                              otMessage           * p_message,
                                              const otMessageInfo * p_message_info,
                                              otError               result)
    {
        UNUSED_PARAMETER(p_context);
    
        // Restore the polling period back to initial slow value.
        //poll_period_restore();
    
        if (result == OT_ERROR_NONE)
        {
            uint8_t json_buffer[128] = {0};
            UNUSED_RETURN_VALUE(otMessageRead(p_message,
                                              otMessageGetOffset(p_message),
                                              json_buffer,
                                              sizeof(json_buffer)));
            NRF_LOG_INFO("Received CoAP data: %s", NRF_LOG_PUSH(json_buffer));
        }
        else
        {
            NRF_LOG_INFO("Provisioning failed: %d\r\n", result);
        }
    }
    
    
    static void coap_client_cloud_update(void)
    {
        char            payload_buffer[128];
        otError         error;
        otMessage     * p_request;
        otMessageInfo   message_info;
        otInstance    * p_instance = thread_ot_instance_get();
    
        if (m_associated == false)
        {
            return;
        }
    
        // If IPv6 address of the cloud is unspecified try to resolve hostname.
        if (otIp6IsAddressUnspecified(&m_cloud_address))
        {
            error = thread_dns_utils_hostname_resolve(CLOUD_HOSTNAME,
                                                      dns_response_handler,
                                                      NULL);
            ASSERT(error == OT_ERROR_NONE);
            return;
        }
    
        // Construct JSON object acceptable by TheThings.io cloud.
    //    UNUSED_RETURN_VALUE(snprintf(payload_buffer, sizeof(payload_buffer),
    //                        "{\"values\":[{\"key\":\"%s\",\"value\":\"%d\"},{\"key\":\"%s\",\"value\":\"%ld\"}]}",
    //                        CLOUD_THING_RESOURCE_COUNTER, m_counter, CLOUD_THING_RESOURCE_TEMPERATURE, m_temperature));
    
        do
        {
            p_request = otCoapNewMessage(p_instance, NULL);
            if (p_request == NULL)
            {
                NRF_LOG_INFO("Failed to allocate message for CoAP Request\r\n");
                break;
            }
    
            otCoapMessageInit(p_request, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_GET);
            otCoapMessageGenerateToken(p_request, 4);
    
            error = otCoapMessageAppendUriPathOptions(p_request, CLOUD_URI_PATH);
            ASSERT(error == OT_ERROR_NONE);
    
    //        error = otCoapMessageAppendContentFormatOption(p_request, OT_COAP_OPTION_CONTENT_FORMAT_JSON);
    //        ASSERT(error == OT_ERROR_NONE);
    //
    //        error = otCoapMessageSetPayloadMarker(p_request);
    //        ASSERT(error == OT_ERROR_NONE);
    //
    //        error = otMessageAppend(p_request, payload_buffer, strlen(payload_buffer));
    //        if (error != OT_ERROR_NONE)
    //        {
    //            break;
    //        }
    
            memset(&message_info, 0, sizeof(message_info));
            message_info.mPeerPort = OT_DEFAULT_COAP_PORT;
            message_info.mPeerAddr = m_cloud_address;
    
            error = otCoapSendRequest(p_instance, p_request, &message_info, provisioning_response_handler, p_instance);
    
        } while (false);
    
        if ((error != OT_ERROR_NONE) && (p_request != NULL))
        {
            NRF_LOG_INFO("Failed to send CoAP Request: %d\r\n", error);
            otMessageFree(p_request);
        }
    }
    
    
    /***************************************************************************************************
     * @section Buttons
     **************************************************************************************************/
    
    static void bsp_event_handler(bsp_event_t event)
    {
        switch (event)
        {
            case BSP_EVENT_KEY_2:
                if (m_counter == COUNTER_MIN)
                {
                    // The minimal counter value has been already reached.
                    break;
                }
    
                // Decrement the counter value.
                m_counter -= 1;
    
                coap_client_cloud_update();
                break;
    
            case BSP_EVENT_KEY_3:
                if (m_counter == COUNTER_MAX)
                {
                    // The maximum counter value has been already reached.
                    break;
                }
    
                // Increment the counter value.
                m_counter += 1;
    
                coap_client_cloud_update();
                break;
    
            default:
                return; // no implementation needed
        }
    }
    
    /***************************************************************************************************
     * @section Callbacks
     **************************************************************************************************/
    
    static void thread_state_changed_callback(uint32_t flags, void * p_context)
    {
        otError      error      = OT_ERROR_NONE;
        otInstance * p_instance = thread_ot_instance_get();
    
        UNUSED_PARAMETER(p_context);
    
        if (flags & OT_CHANGED_THREAD_ROLE)
        {
            switch (otThreadGetDeviceRole(p_instance))
            {
                case OT_DEVICE_ROLE_CHILD:
                case OT_DEVICE_ROLE_ROUTER:
                case OT_DEVICE_ROLE_LEADER:
                    m_associated = true;
    
                    //APP_ERROR_CHECK(app_timer_start(m_temp_timer, APP_TIMER_TICKS(TEMP_MEASUREMENT_INTERVAL), NULL));
    
                    error = thread_dns_utils_hostname_resolve(CLOUD_HOSTNAME,
                                                              dns_response_handler,
                                                              NULL);
                    ASSERT(error == OT_ERROR_NONE);
                    break;
    
                case OT_DEVICE_ROLE_DISABLED:
                case OT_DEVICE_ROLE_DETACHED:
                    m_associated = false;
    
                    //APP_ERROR_CHECK(app_timer_stop(m_temp_timer));
    
                    // Clear IPv6 address of the TheThings.io cloud.
                    memset(&m_cloud_address, 0, sizeof(m_cloud_address));
                    break;
    
                default:
                    break;
            }
        }
    
        NRF_LOG_INFO("State changed! Flags: 0x%08x Current role: %d\r\n", flags,
                     otThreadGetDeviceRole(p_instance));
    }
    
    /**@brief Temperature measurement timer handler. */
    static void temp_timer_handler(void * p_context)
    {
        (void)p_context;
    
        NRF_TEMP->TASKS_START = 1;
        /* Busy wait while temperature measurement is not finished. */
        while (NRF_TEMP->EVENTS_DATARDY == 0)
        {
            // Do nothing.
        }
        NRF_TEMP->EVENTS_DATARDY = 0;
    
        int32_t temp = nrf_temp_read() / 4;
    
        NRF_TEMP->TASKS_STOP = 1;
    
        if (m_temperature != temp)
        {
            m_temperature = temp;
            coap_client_cloud_update();
        }
    }
    
    /***************************************************************************************************
     * @section Initialization
     **************************************************************************************************/
    
     /**@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 Application Timer Module
     */
    static void timer_init(void)
    {
        uint32_t error_code = app_timer_init();
        APP_ERROR_CHECK(error_code);
    
        //error_code = app_timer_create(&m_temp_timer,
        //                              APP_TIMER_MODE_REPEATED,
        //                              temp_timer_handler);
        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 Stack
     */
    static void thread_instance_init(void)
    {
        thread_configuration_t thread_configuration =
        {
            .radio_mode        = THREAD_RADIO_MODE_RX_ON_WHEN_IDLE,
            .autocommissioning = true,
        };
    
        thread_init(&thread_configuration);
        thread_cli_init();
        thread_state_changed_callback_set(thread_state_changed_callback);
    }
    
    
    /**@brief Default handler for unhandled CoAP requests.
     */
    static void coap_default_handler(void                * p_context,
                                     otMessage           * p_message,
                                     const otMessageInfo * p_message_info)
    {
        (void)p_context;
        (void)p_message;
        (void)p_message_info;
    
        NRF_LOG_INFO("Received CoAP message that does not match any request or resource\r\n");
    }
    
    
    /**@brief Function for initializing CoAP client module.
     */
    static void coap_client_init(void)
    {
        otInstance * p_instance = thread_ot_instance_get();
    
        otError error = otCoapStart(p_instance, OT_DEFAULT_COAP_PORT);
        ASSERT(error == OT_ERROR_NONE);
    
        otCoapSetDefaultHandler(p_instance, coap_default_handler, NULL);
    }
    
    
    /**@brief Function for initializing scheduler module.
     */
    static void scheduler_init(void)
    {
        APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    }
    
    /***************************************************************************************************
     * @section Main
     **************************************************************************************************/
    
    int main(int argc, char * argv[])
    {
        log_init();
        scheduler_init();
        timer_init();
        nrf_temp_init();
    
        thread_instance_init();
        thread_bsp_init();
    
        coap_client_init();
    
        while (true)
        {
            thread_process();
            app_sched_execute();
    
            if (NRF_LOG_PROCESS() == false)
            {
                thread_sleep();
            }
        }
    }
    
    /**
     *@}
     **/
    

    <info> app: Received CoAP data: [{"key":"counter","value":"4","datetime":"2020-09-17T14:34:55.098Z"}]
    <info> app: Received CoAP data: [{"key":"counter","value":"6","datetime":"2020-09-17T14:38:05.843Z"}]
    <info> app: Received CoAP data: [{"key":"counter","value":"7","datetime":"2020-09-17T14:38:08.157Z"}]
    <info> app: Received CoAP data: [{"key":"counter","value":"8","datetime":"2020-09-17T14:38:20.912Z"}]

    I used another board running the original example, to post updated counter values.

    Best regards,
    Jørgen

  • Hi Jørgen,

    Thank you for your reply.

    It can work.

    now  I try this example  "Thread MQTT-SN Example".

    after i compile the code than i do the step below

    1.Build the example according to the instructions in Building examples.
    2.Turn the MQTT-SN gateway on according to the instructions in Thread Border Router.
    3.Program a development board with the MQTT-SN Subscriber application.
    4.Program another development board with the MQTT-SN Publisher application.
    5.Let the clients find the MQTT-SN gateway by pressing Button 2 on both boards.

    one of the FTD get kick out , when i do the 5 step

    and the error message show up
    "0> <error> app: Message of unsupported type has been received.
    0>
    0> <error> app: MQTT-SN message could not be processed."

    so the border router seems to be can only connect to one FTD

    if i connect two devices in the same time one of FTD will be kick of

    is there any reason may cause that? Or i miss some step need to be done?

    Please help me,thanks

    Best Regards,

    Rick.

  • Can you check which message type you are receiving when this problem occurs, for instance by printing it in mqttsn_packet_receiver.c:949:

    NRF_LOG_ERROR("Message of unsupported type has been received: %d.\r\n", message_type);

  • Hi Jørgen,

    I get the message_type is 1.

    both are the same.

    Pls kindly help advise how to solve it?

    Best Regards,

    Rick.

  • Hi Jørgen:

    How are you today!

    Are you have any advice? and are you have the same issue?

    Pls kindly help advise how to solve it?

    Best Regards,

    Rick.

Related