Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Set a device name in beacon example SDK 15

Hello,

I'm working with PCA10040 EVB.

I've followed this FAQ that shows how to add a device name.

But function sd_ble_gap_adv_set_configure() (called at the end of advertising_init()) returns NRF_ERROR_INVALID_ADDR (16).

When I increased APP_BEACON_INFO_LENGTH from 0x17 to 0x1B, and APP_ADV_DATA_LENGTH from 0x15 to 0x19 (4 bytes for "Test"), function ble_advdata_encode()  (called at the end of advertising_init()) returns NRF_ERROR_DATA_SIZE (12).

The main file includes the following definitions:

#define APP_BLE_CONN_CFG_TAG            1                                  /**< A tag identifying the SoftDevice BLE configuration. */
#define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
#define APP_BEACON_INFO_LENGTH          0x17                               /**< Total length of information advertised by the Beacon. */
#define APP_ADV_DATA_LENGTH             0x15                               /**< Length of manufacturer specific data in the advertisement. */
#define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
#define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
#define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
#define APP_MAJOR_VALUE                 0x01, 0x02                         /**< Major value used to identify Beacons. */
#define APP_MINOR_VALUE                 0x03, 0x04                         /**< Minor value used to identify Beacons. */
#define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                        0x45, 0x56, 0x67, 0x78, \
                                        0x89, 0x9a, 0xab, 0xbc, \
                                        0xcd, 0xde, 0xef, 0xf0             /**< Proprietary UUID for Beacon. */
#define DEAD_BEEF                       0xDEADBEEF                         /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */

I've included, defined and declared as follows:

#include "ble_advdata.h" // In order to add device name
#define BLE_GAP_ADV_TYPE_ADV_SCAN_IND 0x02 // In order to add device name
#define DEVICE_NAME   "Test"

static uint8_t              m_enc_srdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded scan set. */

I've added these lines between "ble_stack_init()" and "advertising_init()":

    ret_code_t err_code;
    ble_gap_conn_sec_mode_t sec_mode;
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    err_code = sd_ble_gap_device_name_set(&sec_mode,
                                     (const uint8_t *)DEVICE_NAME,
                                      strlen(DEVICE_NAME));
    APP_ERROR_CHECK(err_code);

I've changed m_adv_data.scan_rsp_data field from:

.scan_rsp_data =
    {
        .p_data = NULL,
        .len    = 0
    }

to:

.scan_rsp_data =
    {
        .p_data = m_enc_srdata,
        .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    }

The advertising_init() function is:

static void advertising_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    
    ble_advdata_t srdata; // This line was added !!!
    
    uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;

    ble_advdata_manuf_data_t manuf_specific_data;

    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;

#if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
    // UICR instead of using the default values. The major and minor values obtained from the UICR
    // are encoded into advertising data in big endian order (MSB First).
    // To set the UICR used by this example to a desired value, write to the address 0x10001080
    // using the nrfjprog tool. The command to be used is as follows.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
    // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
    // the following command should be used.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
    uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
    uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);

    uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;

    m_beacon_info[index++] = MSB_16(major_value);
    m_beacon_info[index++] = LSB_16(major_value);

    m_beacon_info[index++] = MSB_16(minor_value);
    m_beacon_info[index++] = LSB_16(minor_value);
#endif

    manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
    manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));
    
    //advdata.name_type             = BLE_ADVDATA_NO_NAME; // This line was commented !!!
    
    advdata.flags                 = flags;
    advdata.p_manuf_specific_data = &manuf_specific_data;

/********************** Added code ************************/
    // Build and set scan response data.
    memset(&srdata, 0, sizeof(srdata));
    srdata.name_type             = BLE_ADVDATA_FULL_NAME;

    err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
    APP_ERROR_CHECK(err_code);
/**********************************************************/
    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    m_adv_params.properties.type = BLE_GAP_ADV_TYPE_ADV_SCAN_IND;                               // This line was added
    //m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;   // This line was commented

    m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
    m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
    m_adv_params.duration        = 0;       // Never time out.
    
    err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
    APP_ERROR_CHECK(err_code);
}

Please help me to understand what I'm doing wrong or missing.

Thanks in advance for your help!

  • Hi,

    I found the root cause to be BLE_GAP_ADV_TYPE_ADV_SCAN_IND. The value that you have chosen for this define is 0x02, but that corresponds to BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY. Rather it looks like you should have used BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED. I suggest using that define directly instead of defining it on your own, just as BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED was used directly in the original example. You can find all the available advertising type definitions in ble_gap.h.

    Fixing the above, and keeping everything else as you posted it (still keeping APP_BEACON_INFO_LENGTH and APP_ADV_DATA_LENGTH at 0x17 and 0x15 respectively) the example runs without issue, and it advertises as "Test" in the scan response data.

    The reason why increasing APP_BEACON_INFO_LENGTH and APP_ADV_DATA_LENGTH gives an NRF_ERROR_DATA_SIZE error is that those defines control the size of the "manufacturer specific data", which is one of the advertising types that can be part of an advertising packet. This is the advertising data type used for storing the beacon data, and the beacon data itself is formatted into the m_beacon_info uint8_t array. You simply made that array too long to fit within the advertising packet, which made ble_advdata_encode() return with that error. The device name, on the other hand, is stored in another advertising type and has nothing to do with the manufacturer specific data.

    One further comment: Commenting out the line
    advdata.name_type             = BLE_ADVDATA_NO_NAME;
    actually makes no difference, as the BLE_ADVDATA_NO_NAME enum value is 0. It is better to keep it there, so that you are explicitly stating that there is no device name included in advdata.

    Please note that using scannable advertising uses more power (sending advertising data, listening for scan requests, then maybe sending scan response data) than nonscannable advertising (sending advertising data.) Also note that the beacon example is made for easily being modified to conform to the iBeacon specification (obtainable from mfi.apple.com.) Changing to scannable and/or changing the format of the beacon data in the manufacturer specific data may break with that specification. If you are not planning on following the iBeacon specification then you are of course free to do those changes.

    Regards,
    Terje

  • Hello Terje,

    Thank you very much for your quick reply and detailed explanation.

    It works fine. The nRF Connect recognizes the device as "Test".

    Best regards,

    Ratson

  • can you please share complete stack/code you made changes to set beacon device name.it would be really helpful

  • also  #if defined(USE_UICR_FOR_MAJ_MIN_VALUES) is not highlited in beacon stack...so it can not use major minor valuse ...what could be the reason

  • Below is the complete main.c file that can replace the ble_app_beacon main.c file inside of examples\ble_peripheral\ble_app_beacon in nRF5 SDK v15.0.0. This implements the changes suggested by Terje in his response above and creates a beacon advertising with the name "Nordic_Beacon".

    /**
     * Copyright (c) 2014 - 2018, 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_app_beacon_main main.c
     * @{
     * @ingroup ble_sdk_app_beacon
     * @brief Beacon Transmitter Sample Application main file.
     *
     * This file contains the source code for an Beacon transmitter sample application.
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "nordic_common.h"
    #include "bsp.h"
    #include "nrf_soc.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "ble_advdata.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define DEVICE_NAME                     "Nordic_Beacon"
    
    #define APP_BLE_CONN_CFG_TAG            1                                  /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    
    #define APP_BEACON_INFO_LENGTH          0x17                               /**< Total length of information advertised by the Beacon. */
    #define APP_ADV_DATA_LENGTH             0x15                               /**< Length of manufacturer specific data in the advertisement. */
    #define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
    #define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
    #define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
    #define APP_MAJOR_VALUE                 0x01, 0x02                         /**< Major value used to identify Beacons. */
    #define APP_MINOR_VALUE                 0x03, 0x04                         /**< Minor value used to identify Beacons. */
    #define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                            0x45, 0x56, 0x67, 0x78, \
                                            0x89, 0x9a, 0xab, 0xbc, \
                                            0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */
    
    #define DEAD_BEEF                       0xDEADBEEF                         /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    #define MAJ_VAL_OFFSET_IN_BEACON_INFO   18                                 /**< Position of the MSB of the Major Value in m_beacon_info array. */
    #define UICR_ADDRESS                    0x10001080                         /**< Address of the UICR register used by this example. The major and minor versions to be encoded into the advertising data will be picked up from this location. */
    #endif
    
    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. */
    static uint8_t              m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded advertising set. */
    static uint8_t              m_enc_srdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded scan set. */
    
    /**@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 = m_enc_srdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        }
    };
    
    
    static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
    {
        APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                             // implementation.
        APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                             // manufacturer specific data in this implementation.
        APP_BEACON_UUID,     // 128 bit UUID value.
        APP_MAJOR_VALUE,     // Major arbitrary value that can be used to distinguish between Beacons.
        APP_MINOR_VALUE,     // Minor arbitrary value that can be used to distinguish between Beacons.
        APP_MEASURED_RSSI    // Manufacturer specific information. The Beacon's measured TX power in
                             // this implementation.
    };
    
    
    /**@brief Callback function for asserts in the SoftDevice.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in]   line_num   Line number of the failing ASSERT call.
     * @param[in]   file_name  File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    /**@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 advertising_init(void)
    {
        uint32_t      err_code;
        ble_advdata_t advdata;
        
        ble_advdata_t srdata;
    
        uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
    
        ble_advdata_manuf_data_t manuf_specific_data;
    
        manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
        // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
        // UICR instead of using the default values. The major and minor values obtained from the UICR
        // are encoded into advertising data in big endian order (MSB First).
        // To set the UICR used by this example to a desired value, write to the address 0x10001080
        // using the nrfjprog tool. The command to be used is as follows.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
        // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
        // the following command should be used.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
        uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
        uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);
    
        uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;
    
        m_beacon_info[index++] = MSB_16(major_value);
        m_beacon_info[index++] = LSB_16(major_value);
    
        m_beacon_info[index++] = MSB_16(minor_value);
        m_beacon_info[index++] = LSB_16(minor_value);
    #endif
    
        manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
        manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type             = BLE_ADVDATA_NO_NAME;
        advdata.flags                 = flags;
        advdata.p_manuf_specific_data = &manuf_specific_data;
    
        // Build and set scan response data.
        memset(&srdata, 0, sizeof(srdata));
        srdata.name_type             = BLE_ADVDATA_FULL_NAME;
    
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED; //Beacon needs to be scannable to receive scan response
        m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
        m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
        m_adv_params.duration        = 0;       // Never time out.
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
        APP_ERROR_CHECK(err_code);
    
        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 starting advertising.
     */
    static void 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 the BLE stack.
     *
     * @details 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 logging. */
    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 LEDs. */
    static void leds_init(void)
    {
        ret_code_t err_code = bsp_init(BSP_INIT_LEDS, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing timers. */
    static void timers_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@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 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)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        // Initialize.
        log_init();
        timers_init();
        leds_init();
        power_management_init();
        ble_stack_init();
    
        ret_code_t err_code;
        ble_gap_conn_sec_mode_t sec_mode;
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                         (const uint8_t *)DEVICE_NAME,
                                          strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        advertising_init();
    
        // Start execution.
        NRF_LOG_INFO("Beacon example started.");
        advertising_start();
    
        // Enter main loop.
        for (;; )
        {
            idle_state_handle();
        }
    }
    
    
    /**
     * @}
     */
    

Related