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

DFU project

I try to create coap server project and it should by  updateable by DFU. I merge project simple coap server and thread dfu client, and I keep  instructions in documentation to build it and run DFU. But Server doesnt response to coap requests and when I start multicast DFU process server is not updated. and when I try to start unicast DFU it waiting to promote a router. 

Parents
  • I am folowing this instructions:

    first version

    D:
    cd IS\nRF5_SDK_for_Thread_and_Zigbee_v3.1.0_c7c4730\examples\thread\dfu_client
    make -C dfu_client_coap_server\pca10056\blank\armgcc
    nrfutil settings generate --family NRF52840 --application dfu_client_coap_server\pca10056\blank\armgcc\_build\nrf52840_xxaa.hex --application-version 1 --bootloader-version 1 --bl-settings-version 1 settings.hex
    mergehex -m dfu_client_coap_server\pca10056\blank\armgcc\_build\nrf52840_xxaa.hex settings.hex -o dfu_client.hex
    nrfjprog -f nrf52 --eraseall
    nrfjprog -f nrf52 -r --program ..\..\..\components\softdevice\mbr\nrf52840\hex\mbr_nrf52_2.4.1_mbr.hex --chiperase
    nrfjprog -f nrf52 -r --program bootloader\pca10056\blank\armgcc\_build\nrf52840_xxaa_mbr.hex
    nrfjprog -f nrf52 -r --program dfu_client.hex --sectorerase


    code change

    next version
    make -C dfu_client_coap_server\pca10056\blank\armgcc
    nrfutil pkg generate --hw-version 52 --sd-req 0x00 --application-version 2 --application dfu_client_coap_server\pca10056\blank\armgcc\_build\nrf52840_xxaa.hex --key-file key.pem app_dfu_package.zip


    DFU multicast
    nrfutil dfu thread -f -pkg app_dfu_package.zip -p COM14 --channel 11 --panid 43981 -r 4 -rs 5000 -a FF03::1

    DFU unicast
    nrfutil dfu thread -f -pkg app_dfu_package.zip -p COM14 --channel 11 --panid 43981
    nrfutil dfu thread -f -pkg app_dfu_package.zip -p COM14 --channel 11 --panid 43981 -a fdde:ad00:beef:0:65ab:b4da:9355:117b

  • Hi,

    Can you post the log output? Have you tried to run the DFU client application without the coap server and see if everything works? Can you post your project folder so we can reproduce it?

    Best regards,

    Marjeris

  • We wanna use it for thousands devices an update firmware without DFU will not possible. 

  • If I understand it, I should use coap library which is used in DFU project? 

  • Hi Fran,

    That's the buildt-in OpenThread coap library, the external coap library (the one used by the thread DFU client) is this one: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.iotsdk.v0.9.0%2Flib_iot_coap.html

  • I use nRF5_SDK_for_Thread_and_Zigbee_v3.2.0_9fade31

    I try example to DFU thread client and I add turn on LED. DFU was sucessfull. Next I add CoAP resources to code and it not start.

    This is terminal output:

    D:\IS\nRF5_SDK_for_Thread_and_Zigbee_v3.2.0_9fade31\examples\thread\dfu>nrfutil dfu thread -f -pkg app_dfu_package.zip -p COM12 --channel 11 --panid 43981
    Address not specified. Using ff03::1 (all Thread nodes)
    Using connectivity board at serial port: COM12
    Flashing connectivity firmware...
    Connectivity firmware flashed.
    Waiting for NCP to promote to a router...
    Thread DFU server is running... Press <Ctrl + D> to stop.

    edited file: coap_dfu.c

    added code:

    #define MY_APP_RESOURCE_HELLO "hello"
    coap_resource_t coap_resource_hello;
    
    #define MY_APP_RESOURCE_READ "read"
    coap_resource_t coap_resource_read;
    
    #define MY_APP_RESOURCE_WRITE "write"
    coap_resource_t coap_resource_write;
    
    static void hello_request_callback(coap_resource_t * p_resource, coap_message_t * p_request)
    {
    NRF_LOG_INFO("Hello packet");
    
    coap_message_t * p_response = NULL;
    
    if (!is_addr_multicast(&p_request->local))
    {
    p_response = empty_reset_response_create(p_request);
    }
    
    // Send response, if created.
    if (p_response != NULL)
    {
    coap_dfu_message_send(p_response);
    }
    
    }
    
    static void read_request_callback(coap_resource_t * p_resource, coap_message_t * p_request)
    {
    NRF_LOG_INFO("Read packet");
    
    coap_message_t * p_response = NULL;
    
    if (!is_addr_multicast(&p_request->local))
    {
    p_response = empty_reset_response_create(p_request);
    }
    
    // Send response, if created.
    if (p_response != NULL)
    {
    coap_dfu_message_send(p_response);
    }
    
    }
    
    static void write_request_callback(coap_resource_t * p_resource, coap_message_t * p_request)
    {
    NRF_LOG_INFO("Write packet");
    
    coap_message_t * p_response = NULL;
    
    if (!is_addr_multicast(&p_request->local))
    {
    p_response = empty_reset_response_create(p_request);
    }
    
    // Send response, if created.
    if (p_response != NULL)
    {
    coap_dfu_message_send(p_response);
    }
    
    }
    
    
    static uint32_t MyAppCoapResource_init()
    {
        uint32_t err_code = NRF_SUCCESS;
        
        do
        {
            err_code = coap_resource_create(&coap_resource_hello, MY_APP_RESOURCE_HELLO);
            err_code = coap_resource_create(&coap_resource_read, MY_APP_RESOURCE_READ);
            err_code = coap_resource_create(&coap_resource_write, MY_APP_RESOURCE_WRITE);
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            coap_resource_hello.permission = (COAP_PERM_POST | COAP_PERM_GET);
            coap_resource_hello.callback = hello_request_callback;
    
            coap_resource_read.permission = (COAP_PERM_POST | COAP_PERM_GET);
            coap_resource_read.callback = read_request_callback;
    
            coap_resource_write.permission = (COAP_PERM_POST | COAP_PERM_GET);
            coap_resource_write.callback = write_request_callback;
    
            NRF_LOG_INFO("Endpoints initialized");
    
        } while (0);
    
        return err_code;
    }
    
    //upgrade this existing function
    
    uint32_t coap_dfu_init(const void * p_context)
    {
        uint32_t err_code;
    
        do
        {
            memset(&m_coap_dfu_ctx, 0 , sizeof(m_coap_dfu_ctx));
    
            err_code = coap_protocol_init(p_context);
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            err_code = MyAppCoapResource_init();
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            err_code = endpoints_init(&m_coap_dfu_ctx);
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            nrf_dfu_settings_init(false);
            nrf_dfu_req_handler_init(dfu_observer);
    
            background_dfu_state_init(&m_dfu_ctx);
    
            app_timer_create(&m_send_timer, APP_TIMER_MODE_SINGLE_SHOT, delayed_send_handler);
            app_timer_create(&m_reset_timer, APP_TIMER_MODE_SINGLE_SHOT, delayed_reset_handler);
            app_timer_create(&m_coap_delayed_error_handling_timer, APP_TIMER_MODE_SINGLE_SHOT, coap_delayed_error_handler);
    
            APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
        } while (0);
    
        return err_code;
    }
    

Reply
  • I use nRF5_SDK_for_Thread_and_Zigbee_v3.2.0_9fade31

    I try example to DFU thread client and I add turn on LED. DFU was sucessfull. Next I add CoAP resources to code and it not start.

    This is terminal output:

    D:\IS\nRF5_SDK_for_Thread_and_Zigbee_v3.2.0_9fade31\examples\thread\dfu>nrfutil dfu thread -f -pkg app_dfu_package.zip -p COM12 --channel 11 --panid 43981
    Address not specified. Using ff03::1 (all Thread nodes)
    Using connectivity board at serial port: COM12
    Flashing connectivity firmware...
    Connectivity firmware flashed.
    Waiting for NCP to promote to a router...
    Thread DFU server is running... Press <Ctrl + D> to stop.

    edited file: coap_dfu.c

    added code:

    #define MY_APP_RESOURCE_HELLO "hello"
    coap_resource_t coap_resource_hello;
    
    #define MY_APP_RESOURCE_READ "read"
    coap_resource_t coap_resource_read;
    
    #define MY_APP_RESOURCE_WRITE "write"
    coap_resource_t coap_resource_write;
    
    static void hello_request_callback(coap_resource_t * p_resource, coap_message_t * p_request)
    {
    NRF_LOG_INFO("Hello packet");
    
    coap_message_t * p_response = NULL;
    
    if (!is_addr_multicast(&p_request->local))
    {
    p_response = empty_reset_response_create(p_request);
    }
    
    // Send response, if created.
    if (p_response != NULL)
    {
    coap_dfu_message_send(p_response);
    }
    
    }
    
    static void read_request_callback(coap_resource_t * p_resource, coap_message_t * p_request)
    {
    NRF_LOG_INFO("Read packet");
    
    coap_message_t * p_response = NULL;
    
    if (!is_addr_multicast(&p_request->local))
    {
    p_response = empty_reset_response_create(p_request);
    }
    
    // Send response, if created.
    if (p_response != NULL)
    {
    coap_dfu_message_send(p_response);
    }
    
    }
    
    static void write_request_callback(coap_resource_t * p_resource, coap_message_t * p_request)
    {
    NRF_LOG_INFO("Write packet");
    
    coap_message_t * p_response = NULL;
    
    if (!is_addr_multicast(&p_request->local))
    {
    p_response = empty_reset_response_create(p_request);
    }
    
    // Send response, if created.
    if (p_response != NULL)
    {
    coap_dfu_message_send(p_response);
    }
    
    }
    
    
    static uint32_t MyAppCoapResource_init()
    {
        uint32_t err_code = NRF_SUCCESS;
        
        do
        {
            err_code = coap_resource_create(&coap_resource_hello, MY_APP_RESOURCE_HELLO);
            err_code = coap_resource_create(&coap_resource_read, MY_APP_RESOURCE_READ);
            err_code = coap_resource_create(&coap_resource_write, MY_APP_RESOURCE_WRITE);
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            coap_resource_hello.permission = (COAP_PERM_POST | COAP_PERM_GET);
            coap_resource_hello.callback = hello_request_callback;
    
            coap_resource_read.permission = (COAP_PERM_POST | COAP_PERM_GET);
            coap_resource_read.callback = read_request_callback;
    
            coap_resource_write.permission = (COAP_PERM_POST | COAP_PERM_GET);
            coap_resource_write.callback = write_request_callback;
    
            NRF_LOG_INFO("Endpoints initialized");
    
        } while (0);
    
        return err_code;
    }
    
    //upgrade this existing function
    
    uint32_t coap_dfu_init(const void * p_context)
    {
        uint32_t err_code;
    
        do
        {
            memset(&m_coap_dfu_ctx, 0 , sizeof(m_coap_dfu_ctx));
    
            err_code = coap_protocol_init(p_context);
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            err_code = MyAppCoapResource_init();
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            err_code = endpoints_init(&m_coap_dfu_ctx);
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            nrf_dfu_settings_init(false);
            nrf_dfu_req_handler_init(dfu_observer);
    
            background_dfu_state_init(&m_dfu_ctx);
    
            app_timer_create(&m_send_timer, APP_TIMER_MODE_SINGLE_SHOT, delayed_send_handler);
            app_timer_create(&m_reset_timer, APP_TIMER_MODE_SINGLE_SHOT, delayed_reset_handler);
            app_timer_create(&m_coap_delayed_error_handling_timer, APP_TIMER_MODE_SINGLE_SHOT, coap_delayed_error_handler);
    
            APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
        } while (0);
    
        return err_code;
    }
    

Children
  • Hi Fran,

    I am so sorry but I am going out on vacation so I will not be able to review your code before the 7th of October. Sorry for the inconvenience and thanks for your patience.

    Best regards,

    Marjeris

  • now it write this output:

    Traceback (most recent call last):
    File "C:\Python27\lib\site-packages\nrfutil-4.0.0-py2.7.egg\nordicsemi\thread\tncp.py", line 130, in _wpan_receive
    receiver.receive(payload, src, dst)
    File "build\bdist.win-amd64\egg\piccata\core.py", line 541, in receive
    self._message_layer.receive(data, remote, local)
    File "build\bdist.win-amd64\egg\piccata\core.py", line 206, in receive
    self._transaction_layer.receive_message(message, remote, local)
    File "build\bdist.win-amd64\egg\piccata\core.py", line 428, in receive_message
    self._process_response(message)
    File "build\bdist.win-amd64\egg\piccata\core.py", line 359, in _process_response
    self._finish_transaction(response.token, remote, RESULT_SUCCESS, response)
    File "build\bdist.win-amd64\egg\piccata\core.py", line 305, in _finish_transaction
    self._handle_app_callback(callback, result, request, response)
    File "build\bdist.win-amd64\egg\piccata\core.py", line 274, in _handle_app_callback
    cb(result, request, response, *args, **kw)
    File "C:\Python27\lib\site-packages\nrfutil-4.0.0-py2.7.egg\nordicsemi\thread\dfu_server.py", line 217, in _handle_trigger_response
    assert (result == piccata.constants.RESULT_TIMEOUT)
    AssertionError

  • Hi Fran,

    Sorry for the late answer here, I was on vacation. I have taken a closer look at the thread coap dfu example and the iot coap library. The coap dfu example already runs a coap server along coap client and the resources are registered in the endpoints_init function in coap_dfu.c.

    Using the 'coap_resource_create' and 'coap_resource_child_add' APIs it should be possible to register custom resources. The endpoints_init function in coap_dfu.c can be extended to add the extra resources you need.

    From what I see in your code you were on the right track but I think you forgot to call 'coap_resource_child_add'.

    Keep in mind that usually one wants to avoid modifying the nordic libraries in the SDK, so directly modifying coap_dfu.c isn't the best approach... but since we can only have one instance of CoAP with IoT CoAP implementation we need to share some resources (i.e. the resource root), so what you could do is to add a function to the CoAP DFU API (coap_dfu.c) allowing to optain a pointer to the root resource of the current CoAP instance. This will allow you to add resources directly from your main application, minimizing CoAP DFU interference and keeping the design as neat as possible.

    To help you on the way I have modified the coap_dfu example to include a light resource so I can test the coap dfu example using the simple_coap_client example commands for on/off (BSP_BUTTON_1). I used the iot coap server example in nRF5_SDK/examples/iot/coap/ipv6/server as a reference.

    (Note: I didn't implement pairing and toggle, which are also included in the original simple coap server/client example, so my example only supports messages send by BSP_BUTTON_1 on the simple coap client(light cmd on/off), nothing will happen when pressing BPS_BUTTON_0 or BPS_BUTTON_2).

    In coap_dfu.c add the following function:

    coap_resource_t * get_resources_root(void){
    	return &(m_coap_dfu_ctx.root); 
    }
    

    And also add it in coap_dfu.h:

    coap_resource_t * get_resources_root(void);

    Then in main.c you can add any number of resources after coap_dfu_init have been called, and add them to the root resource using the function above. See the attached main.c file:

    /**
     * Copyright (c) 2017 - 2019, 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_secure_dfu_example_main main.c
     * @{
     * @ingroup thread_secure_dfu_example
     * @brief Thread Secure DFU Example Application main file.
     *
     */
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include <string.h>
    
    #include "app_scheduler.h"
    #include "app_util.h"
    #include "app_timer.h"
    #include "boards.h"
    #include "bsp_thread.h"
    #include "nrf_delay.h"
    #include "mem_manager.h"
    #include "nrf_assert.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "sdk_config.h"
    #include "nrf_dfu_utils.h"
    #include "coap_dfu.h"
    #include "background_dfu_state.h"
    
    #include "thread_utils.h"
    
    #include <openthread/diag.h>
    #include <openthread/cli.h>
    #include <openthread/thread.h>
    #include <openthread/platform/alarm-micro.h>
    #include <openthread/platform/alarm-milli.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. */
    
    
    /* Add light resource */ 
    static coap_resource_t light;
    
    /**@brief Enumeration describing light commands. */
    typedef enum
    {
        THREAD_COAP_UTILS_LIGHT_CMD_OFF = '0',
        THREAD_COAP_UTILS_LIGHT_CMD_ON,
        THREAD_COAP_UTILS_LIGHT_CMD_TOGGLE
    } thread_coap_utils_light_command_t;
    
    
    extern const app_timer_id_t nrf_dfu_inactivity_timeout_timer_id;
    void handle_dfu_command(int argc, char *argv[]);
    
    APP_TIMER_DEF(m_coap_tick_timer);    /**< Timer used by this module. */
    
    static otCliCommand m_user_commands[] =
    {
        {
            .mName = "dfu",
            .mCommand = handle_dfu_command
        }
    };
    
    
    __WEAK bool nrf_dfu_button_enter_check(void)
    {
        // Dummy function for Keil compilation. This should not be called.
        return false;
    }
    
    
    __WEAK void nrf_bootloader_app_start(uint32_t start_addr)
    {
        (void)start_addr;
        // Dummy function for Keil compilation. This should not be called.
    }
    
    
    void handle_dfu_command(int argc, char *argv[])
    {
        if (argc == 0)
        {
            otCliAppendResult(OT_ERROR_PARSE);
            return;
        }
    
        if (strcmp(argv[0], "diag") == 0)
        {
            struct background_dfu_diagnostic diag;
            coap_dfu_diagnostic_get(&diag);
            otCliOutputFormat("build_id: 0x%08x, "
                                  "state: %d, "
                                  "prev_state: %d, ",
                                  diag.build_id,
                                  diag.state,
                                  diag.prev_state);
            otCliOutputFormat("\r\n");
            otCliAppendResult(OT_ERROR_NONE);
        }
    }
    
    
    void coap_dfu_handle_error(void)
    {
        coap_dfu_reset_state();
    }
    
    
    static void address_print(const otIp6Address *addr)
    {
        char ipstr[40];
        snprintf(ipstr, sizeof(ipstr), "%x:%x:%x:%x:%x:%x:%x:%x",
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 0)),
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 1)),
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 2)),
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 3)),
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 4)),
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 5)),
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 6)),
                 uint16_big_decode((uint8_t *)(addr->mFields.m16 + 7)));
    
        NRF_LOG_INFO("%s\r\n", (uint32_t)ipstr);
    }
    
    
    static void addresses_print(otInstance * aInstance)
    {
        for (const otNetifAddress *addr = otIp6GetUnicastAddresses(aInstance); addr; addr = addr->mNext)
        {
            address_print(&addr->mAddress);
        }
    }
    
    /**@brief Function for initializing scheduler module.
     */
    static void scheduler_init(void)
    {
        APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    }
    
    static void state_changed_callback(uint32_t aFlags, void *aContext)
    {
        if (aFlags & OT_CHANGED_THREAD_NETDATA)
        {
            addresses_print(thread_ot_instance_get());
        }
    
        otDeviceRole role = otThreadGetDeviceRole(thread_ot_instance_get());
        NRF_LOG_INFO("New role: %d\r\n", role);
    
        if (aFlags & OT_CHANGED_THREAD_ROLE)
        {
            switch(role)
            {
                case OT_DEVICE_ROLE_CHILD:
                case OT_DEVICE_ROLE_ROUTER:
                case OT_DEVICE_ROLE_LEADER:
                    coap_dfu_trigger(NULL);
                    break;
    
                case OT_DEVICE_ROLE_DISABLED:
                case OT_DEVICE_ROLE_DETACHED:
                default:
                    break;
            }
        }
    }
    
    /**@brief Handle events from m_coap_tick_timer.
     */
    static void nrf_coap_time_tick_handler(void * p_context)
    {
        UNUSED_VARIABLE(p_context);
        coap_time_tick();
    }
    
    
    /**@brief Function for creating coap tick timer.
     */
    static ret_code_t coap_tick_timer_create(void)
    {
         ret_code_t ret_code = app_timer_create(&m_coap_tick_timer,
                                               APP_TIMER_MODE_REPEATED,
                                               nrf_coap_time_tick_handler);
        if (ret_code != NRF_SUCCESS)
        {
            return ret_code;
        }
    
        return app_timer_start(m_coap_tick_timer, APP_TIMER_TICKS(1000), NULL);
    }
    
    
    /**@brief Function for initializing the Thread Board Support Package.
     */
    static void thread_bsp_init(void)
    {
        uint32_t err_code = bsp_init(BSP_INIT_LEDS, NULL);
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_thread_init(thread_ot_instance_get());
        APP_ERROR_CHECK(err_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,
        };
    
        thread_init(&thread_configuration);
        thread_cli_init();
        thread_state_changed_callback_set(state_changed_callback);
    
        otCliSetUserCommands(m_user_commands, sizeof(m_user_commands) / sizeof(otCliCommand));
    }
    
    
    /**@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();
    }
    
    static void light_request_callback(coap_resource_t * p_resource, coap_message_t * p_request)
    {
    		NRF_LOG_INFO("Light resource packet");
    	
    		coap_message_conf_t response_config;
        memset(&response_config, 0x00, sizeof(coap_message_conf_t));
    
        if (p_request->header.type == COAP_TYPE_NON)
        {
    				NRF_LOG_INFO("Coap packet type non");
            response_config.type = COAP_TYPE_NON;
        }
        else if (p_request->header.type == COAP_TYPE_CON)
        {
    				NRF_LOG_INFO("Coap packet type ack");
            response_config.type = COAP_TYPE_ACK;
        }
    	    // PIGGY BACKED RESPONSE
        response_config.code = COAP_CODE_405_METHOD_NOT_ALLOWED;
        // Copy message ID.
        response_config.id = p_request->header.id;
        // Set local port number to use.
        response_config.port.port_number = DFU_UDP_PORT;
        // Copy token.
        memcpy(&response_config.token[0], &p_request->token[0], p_request->header.token_len);
        // Copy token length.
        response_config.token_len = p_request->header.token_len;
    
        coap_message_t * p_response;
        uint32_t err_code = coap_message_new(&p_response, &response_config);
        APP_ERROR_CHECK(err_code);
    		
    		err_code = coap_message_remote_addr_set(p_response, &p_request->remote);
        APP_ERROR_CHECK(err_code);
    		
    
    		// Handle request.
        switch (p_request->header.code)
        {
            case COAP_CODE_GET:
            {
                break;
            }
    
            case COAP_CODE_PUT:
            {
                p_response->header.code = COAP_CODE_204_CHANGED;
    
                // Change LED state according to request.
                switch (p_request->p_payload[0])
                {
                    case THREAD_COAP_UTILS_LIGHT_CMD_ON:
                    {
    									NRF_LOG_INFO("LED command ON received");
                        LEDS_ON(BSP_LED_3_MASK);
                        break;
                    }
                    case THREAD_COAP_UTILS_LIGHT_CMD_OFF:
                    {
    										NRF_LOG_INFO("LED command OFF received");
                        LEDS_OFF(BSP_LED_3_MASK);
                        break;
                    }
                    case THREAD_COAP_UTILS_LIGHT_CMD_TOGGLE:
                    {
    										NRF_LOG_INFO("LED command toggle received");
                        //LEDS_INVERT(led_mask);
                        break;
                    }
                    default:
                    {
                        p_response->header.code = COAP_CODE_400_BAD_REQUEST;
                        break;
                    }
                }
                break;
            }
    
            default:
            {
                p_response->header.code = COAP_CODE_405_METHOD_NOT_ALLOWED;
                break;
            }
        }
        uint32_t msg_handle;
        err_code = coap_message_send(&msg_handle, p_response);
        APP_ERROR_CHECK(err_code);
    
        err_code = coap_message_delete(p_response);
        APP_ERROR_CHECK(err_code);
    }
    
    static uint32_t my_endpoints_init(){
    
    		uint32_t err_code = NRF_SUCCESS;
    		
    		do {
    
    			err_code = coap_resource_create(&light, "light");
    			if (err_code != NRF_SUCCESS)
           {
               break;
           }
    			
    			light.permission = (COAP_PERM_GET | COAP_PERM_PUT);
          light.callback = light_request_callback;
    			
    			//Add light resource 
    			err_code = coap_resource_child_add(get_resources_root(), &light);
          if (err_code != NRF_SUCCESS)
          {
              break;
          }
    		 
    		  NRF_LOG_INFO("My custom endpoints initialized");
        } while (0);
    		
    		return err_code;
    }
    
    /***************************************************************************************************
     * @section Main
     **************************************************************************************************/
    
    int main(int argc, char *argv[])
    {
        log_init();
    
        uint32_t err_code = nrf_mem_init();
        APP_ERROR_CHECK(err_code);
    
        scheduler_init();
    
        err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        thread_instance_init();
    	
    
        err_code = coap_dfu_init(thread_ot_instance_get());
        APP_ERROR_CHECK(err_code);
    	
    	  err_code = my_endpoints_init();
        APP_ERROR_CHECK(err_code);
    	
        
    		thread_bsp_init();
    
        coap_tick_timer_create();
    		//LEDS_ON(BSP_LED_1_MASK);
    	
        while (true)
        {
            coap_dfu_process();
    
            thread_process();
            app_sched_execute();
    
            NRF_LOG_PROCESS();
        }
    }
    
    /** @} */
    

    You can then test the application using simple_coap_client to toggle LED4 on and off, and change LED 2 on/off when performing DFU with another board.

    Best regards,

    Marjeris

  • Is exist any option how to debug dfu client project? 

Related