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

How to update advertisement packet SDK 15.0.0 ?

Dear all,

I am trying to develop an application that reads data from a sensor (accelerometer) and I want to be able to update the advertisement packet with the measurement I obtain from it.

So far I am able to read the values from the sensor. Using this example as a basis I can transmit a single value, but I am unable to update the content of the package in order to be able to read the right value. Is there any idea, how I can do this update?

I am using SDK 15.0.0.0. From what I have seen in the forum there is no straight forward way to do this, but I wonder, if someone has the same issue and if it is possible to share some sample code with me.

Kind regards

  • Hi Jimmy. I took your code and I reduced to the minimum code necessary to simply update the advertisement package. I really want to thank you for your example and your code. I am posting the code bellow:

    /**
     * Copyright (c) 2014 - 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 ble_sdk_uart_over_ble_main main.c
     * @{
     * @ingroup  ble_sdk_app_nus_eval
     * @brief    UART over BLE application main file.
     *
     * This file contains the source code for a sample application that uses the Nordic UART service.
     * This application uses the @ref srvlib_conn_params module.
     */
    
    #include "nordic_common.h"
    #include "nrf.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_ble_qwr.h"
    
    #include "bsp_btn_ble.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define APP_BLE_CONN_CFG_TAG            1                                           /**< A tag identifying the SoftDevice BLE configuration. */
    #define APP_BLE_OBSERVER_PRIO           3                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    #define APP_ADV_DURATION                0                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    
    
    #define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(1000, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    
    #define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
    
    static uint8_t m_hardcode_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX] =
    {
            0x02, 0x01, 0x04, //flags
            0x08, 0x09, 'G', 'i', 'a', 'n', 'n', 'i', 's',
            0x12, 0xFF, 0x59,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
    };
    
    #define INCREMENT_INTERVAL         APP_TIMER_TICKS(1000)                   /**< Increment interval (ticks). */
    
    #define DEAD_BEEF                       0xDEADBEEF                                  /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    static ble_gap_adv_params_t m_adv_params;                                  /**< Parameters to be passed to the stack when starting advertising. */
    static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;              /**< Advertising handle used to identify an advertising set. */
    
    NRF_BLE_QWR_DEF(m_qwr);                                                             /**< Context for the Queued Write module.*/
    BLE_ADVERTISING_DEF(m_advertising);                                                 /**< Advertising module instance. */
    
    
    static uint16_t m_conn_handle          = BLE_CONN_HANDLE_INVALID;                   /**< Handle of the current connection. */
    
    static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX] =
    {
            02, 0x01, 0x04, //flags
            0x11, 0xFF, 0x59,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
            0x00, 0x01, 0x02, 0x03,
    };
    
    
    /**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
            .adv_data =
            {
                    .p_data = m_enc_advdata,
                    .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
            },
            .scan_rsp_data =
            {
                    .p_data = NULL,
                    .len    = 0
    
            }
    };
    
    /**@brief Function for initializing the timer module.
     */
    static void timers_init(void)
    {
            ret_code_t err_code = app_timer_init();
            APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling errors from the Connection Parameters module.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
            APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
            uint32_t err_code;
    
            switch (p_ble_evt->header.evt_id)
            {
            case BLE_GAP_EVT_CONNECTED:
                    NRF_LOG_INFO("Connected");
                    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                    APP_ERROR_CHECK(err_code);
                    m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                    err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                    APP_ERROR_CHECK(err_code);
                    break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                    NRF_LOG_INFO("Disconnected");
                    // LED indication will be changed when advertising starts.
                    m_conn_handle = BLE_CONN_HANDLE_INVALID;
                    break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                    NRF_LOG_DEBUG("PHY update request.");
                    ble_gap_phys_t const phys =
                    {
                            .rx_phys = BLE_GAP_PHY_AUTO,
                            .tx_phys = BLE_GAP_PHY_AUTO,
                    };
                    err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                    APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                    // Pairing not supported
                    err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
                    APP_ERROR_CHECK(err_code);
                    break;
    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                    // No system attributes have been stored.
                    err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                    APP_ERROR_CHECK(err_code);
                    break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                    // Disconnect on GATT Client timeout event.
                    err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                     BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                    APP_ERROR_CHECK(err_code);
                    break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                    // Disconnect on GATT Server timeout event.
                    err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                     BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                    APP_ERROR_CHECK(err_code);
                    break;
    
            default:
                    // No implementation needed.
                    break;
            }
    }
    
    
    /**@brief Function for the SoftDevice initialization.
     *
     * @details This function initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing the Advertising functionality.
     *
     * @details Encodes the required advertising data and passes it to the stack.
     *          Also builds a structure to be passed to the stack when starting advertising.
     */
    static void non_connectable_advertising_init(void)
    {
            uint32_t err_code;
            m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
            m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
            m_adv_params.duration        = APP_ADV_DURATION;
    
            NRF_LOG_DEBUG("non_connectable_advertising_init");
    
    
            m_adv_data.adv_data.p_data = m_hardcode_enc_advdata;
            m_adv_data.adv_data.len    = 0x1F; // hardcode to 31 bytes
    
            err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
            APP_ERROR_CHECK(err_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 power management.
     */
    static void power_management_init(void)
    {
            ret_code_t err_code;
            err_code = nrf_pwr_mgmt_init();
            APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for placing the application in low power state while waiting for events.
     */
    #define FPU_EXCEPTION_MASK 0x0000009F
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
            __set_FPSCR(__get_FPSCR()  & ~(FPU_EXCEPTION_MASK));
            (void) __get_FPSCR();
            NVIC_ClearPendingIRQ(FPU_IRQn);
    
            while(NRF_LOG_PROCESS());
            //UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
            nrf_pwr_mgmt_run();
    }
    
    /**@brief Function for starting advertising.
     */
    static void non_connect_advertising_start(void)
    {
            ret_code_t err_code;
    
            err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
            APP_ERROR_CHECK(err_code);
    
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing Radio Notification Software Interrupts.
     */
    uint32_t radio_notification_init(uint32_t irq_priority, uint8_t notification_type, uint8_t notification_distance)
    {
        uint32_t err_code;
    
        err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        // Configure the event
        return sd_radio_notification_cfg_set(notification_type, notification_distance);
    }
    
    /**@brief Software interrupt 1 IRQ Handler, handles radio notification interrupts.
     */
    void SWI1_IRQHandler(bool radio_evt)
    {
        if (radio_evt)
        {   
            nrf_gpio_pin_toggle(BSP_LED_2); //Toggle the status of the LED on each radio notification event
             m_hardcode_enc_advdata[30]++;
        }
    }
    
    
    /**@brief Application main function.
     */
    int main(void)
    {
            bool erase_bonds;
            bool connect_mode_enter = false;
            uint32_t err_code = NRF_SUCCESS;
            log_init();
            timers_init();
    
            //buttons_init();
            power_management_init();
            ble_stack_init();
            err_code = radio_notification_init(3, NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE, NRF_RADIO_NOTIFICATION_DISTANCE_NONE);
            //application_timer_start();
    
            non_connectable_advertising_init();
            non_connect_advertising_start();
    
            NRF_LOG_INFO("Non-Connected Advertising!");
    
    
            // Enter main loop.
            for (;;)
            {
                   idle_state_handle();
                   
            }
    }
    
    
    /**
     * @}
     */
    

    I hope this will clear things out for people. Also this code doesn't do the update job in SDK 15.0.0, but 15.3.0.

    Again thank you very much Jimmy.

  • Hello Jimmy,

    Your example code really helped me to move on with my project.

    Currently I also need to be able to update the response packet. But if actually put a length to the scan_rsp_data that is not 0 the code brakes.

    Do you have any idea why this is happening?

  • Hi Giannis,

    I think it is same approach.  You only need to set the data pointer to the scan response payload.

  • Hi there Jimmy.

    I tried to replicate the same actions for the scan response package, but I keep getting an error.

    This is how I have changed the code:

    static ble_gap_adv_data_t m_adv_data =
    {
            .adv_data =
            {
                    .p_data = m_enc_advdata,
                    .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
            },
            .scan_rsp_data =
            {
                    .p_data = m_enc_advdata,
                    .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
            }
    };

    Created another array:

    static uint8_t m_hardcode_enc_rspdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX] =
    {
            0x02, 0x01, 0x04, //flags
            0x1B, 0xFF, 0x59,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0xAA, 0xBB, 0xCC,
    };

    And passed the pointer to the pointer the same way you do:

    m_adv_data.scan_rsp_data.p_data   = m_hardcode_enc_rspdata;
    m_adv_data.scan_rsp_data.len = 0x1F;

    When I run the code in debug, I end up getting an error.

    Any ideas?

Related