Ble eddystone and ibeacon simultaneously nrf52832

Hello, I am working on a project that consists of sending Eddystone and ibeacon packets simultaneously, to begin with, I started by sending one package of each separately, it was a success but the problem is that when I send both packages through my uc button,

it sends only the first packet while the second one is never sent, here's a screenshot for a better understanding :

I want to stop sending the first package (ibeacon) by pressing the button_1 (it works).

I want to send the second package (Eddystone) by pressing the button_2 (this one doesn't work) and yet it detects the button press.



Ps : the button is on a chip nordic nrf52832.

Parents Reply Children
  • I send them simultaneously because I wanted to send a message, let's say advertising, to both android and apple users. If I send only Eddystone for example, I will only reach android users, likewise for ibeacon, I will only reach apple users. Whereas if I send both, I could reach both. Here is the code if you want to see how it looks like.

  • /**
                                                      main.c
                                               here i mixed the ibeacon and Eddystone code
    APP     : Eddystone
    Version : 1
    
    **/
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "bsp.h"
    #include "ble_conn_params.h"
    #include "ble_advertising.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "es_app_config.h"
    #include "app_scheduler.h"
    #include "nrf_ble_es.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_pwr_mgmt.h"
    
    //LOG
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    //Bottonless DFU sans BUTTON
    #include "ble_dfu.h"
    #include "nrf_bootloader_info.h"
    #include "nrf_dfu_ble_svci_bond_sharing.h"
    #include "nrf_power.h"
    #include "nrf_svci_async_function.h"
    #include "nrf_svci_async_handler.h"
    
    //Power management wants to reset to DFU mode
    #define m_ready_for_reset 1
    
    //
    #include "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.h"
    
    #define DEAD_BEEF                       0xDEADBEEF          //!< Value used as error code on stack dump, can be used to identify stack location on stack unwind.
    #define NON_CONNECTABLE_ADV_LED_PIN     BSP_BOARD_LED_0     //!< Toggles when non-connectable advertisement is sent.
    #define CONNECTED_LED_PIN               BSP_BOARD_LED_1     //!< Is on when device has connected.
    #define CONNECTABLE_ADV_LED_PIN         BSP_BOARD_LED_2     //!< Is on when device is advertising connectable advertisements.
    
    #define CONNECTABLE_ADV_LED_PIN_3       BSP_BOARD_LED_3     //!< Is on when button 4 is pressed.        --MOI--
    
    /**@brief   Priority of the application BLE event handler.
     * @note    You shouldn't need to modify this value.
     */
    #define APP_BLE_OBSERVER_PRIO 3
    
    
    NRF_BLE_GATT_DEF(m_gatt); //!< GATT module instance.
    NRF_BLE_QWR_DEF(m_qwr);             /**< Context for the Queued Write module.*/
    
    //add dfu buttonless
    static void ble_dfu_buttonless_evt_handler(ble_dfu_buttonless_evt_type_t event) {
    
      switch (event) {
      case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
        NRF_LOG_INFO("Device is preparing to enter bootloader mode\r\n");
        break;
    
      case BLE_DFU_EVT_BOOTLOADER_ENTER:
        NRF_LOG_INFO("Device will enter bootloader mode\r\n");
        break;
    
      case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
        NRF_LOG_ERROR("Device will enter bootloader mode\r\n");
        break;
      default:
        NRF_LOG_INFO("Unknown event from ble_dfu.\r\n");
        break;
      }
    }
    
    /**@brief Function for handling Queued Write Module errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error) {
      APP_ERROR_HANDLER(nrf_error);
    }
    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void) {
      ret_code_t err_code;
      nrf_ble_qwr_init_t qwr_init = {0};
    
      // Initialize Queued Write Module.
      qwr_init.error_handler = nrf_qwr_error_handler;
    
      err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
      APP_ERROR_CHECK(err_code);
    
      // Initialize DFU Service.
      ble_dfu_buttonless_init_t dfus_init =
          {
              .evt_handler = ble_dfu_buttonless_evt_handler};
    
      err_code = ble_dfu_buttonless_init(&dfus_init);
      APP_ERROR_CHECK(err_code);
    
    }
    
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.common_evt.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(p_ble_evt->evt.common_evt.conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_CONNECTED:
                bsp_board_led_on(CONNECTED_LED_PIN);
                bsp_board_led_off(CONNECTABLE_ADV_LED_PIN);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                // LED indication will be changed when advertising starts.
                break;
    
            case BLE_GAP_EVT_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;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for the GAP initialization.
    *
    * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
    *          the device. It also sets the permissions and appearance.
    */
    static void gap_params_init(void)
    {
       ret_code_t              err_code;
       ble_gap_conn_params_t   gap_conn_params;
       ble_gap_conn_sec_mode_t sec_mode;
       uint8_t                 device_name[] = APP_DEVICE_NAME;
    
       BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
       err_code = sd_ble_gap_device_name_set(&sec_mode,
                                             device_name,
                                             strlen((const char *)device_name));
       APP_ERROR_CHECK(err_code);
    
       memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
       gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
       gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
       gap_conn_params.slave_latency     = SLAVE_LATENCY;
       gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
       err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    
       APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    #define APP_BLE_CONN_CFG_TAG            0
    /**@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);
    
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_app_ram_start_get(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Overwrite some of the default configurations for the BLE stack.
        ble_cfg_t ble_cfg;
    
        // Configure the maximum number of connections.
        memset(&ble_cfg, 0, sizeof(ble_cfg));
        ble_cfg.gap_cfg.role_count_cfg.periph_role_count  = 1;
    #if !defined (S112)
        ble_cfg.gap_cfg.role_count_cfg.central_role_count = 0;
        ble_cfg.gap_cfg.role_count_cfg.central_sec_count  = 0;
    #endif // !defined (S112)
        err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = false;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void) {
      nrf_pwr_mgmt_init();
    }
    
    /**@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) {
      app_sched_execute();
      nrf_pwr_mgmt_run();
    }
    
    /**@brief Function for handling Eddystone events.
     *
     * @param[in] evt Eddystone event to handle.
     */
    static void on_es_evt(nrf_ble_es_evt_t evt)
    {
        switch (evt)
        {
            case NRF_BLE_ES_EVT_ADVERTISEMENT_SENT:
                bsp_board_led_invert(NON_CONNECTABLE_ADV_LED_PIN);
                printf("je suis dans le 1er cas \n");
                break;
    
            case NRF_BLE_ES_EVT_CONNECTABLE_ADV_STARTED:
                bsp_board_led_on(CONNECTABLE_ADV_LED_PIN);
                printf("je suis dans le 2em cas \n");
                break;
    
            case NRF_BLE_ES_EVT_CONNECTABLE_ADV_STOPPED:
                bsp_board_led_off(CONNECTABLE_ADV_LED_PIN);
                printf("je suis dans le 3em cas \n");
                break;
    
            default:
                break;  //au debut c'etait break;
        }
    }
    
    #define APP_BLE_CONN_CFG_TAG            0 // au debut ct a 1                                 
    
    #define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_0_625_MS)  
    
    #define APP_BEACON_INFO_LENGTH          0x17                            
    #define APP_ADV_DATA_LENGTH             0x15                              
    #define APP_DEVICE_TYPE                 0x02                               
    #define APP_MEASURED_RSSI               0xC3                               
    #define APP_COMPANY_IDENTIFIER          0x004C                             
    #define APP_MAJOR_VALUE                 0x01, 0x02                         
    #define APP_MINOR_VALUE                 0x03, 0x04                        
    #define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                            0x45, 0x56, 0x67, 0x78, \
                                            0x89, 0x9a, 0xab, 0xbc, \
                                            0xcd, 0xde, 0xef, 0xf0            
    
    #define DEAD_BEEF                       0xDEADBEEF                         
    
    #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. */
    
    /**@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
    
        }
    };
    
    
    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.
    };
    
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    static void advertising_init(void)
    {
        uint32_t      err_code;
        ble_advdata_t advdata;
        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;
    
        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;
    
        // 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_NONSCANNABLE_UNDIRECTED;
        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);
    }
    
    
    /**@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);
    
    
    }
    
    /**@brief Function for stoping advertising.
     */
    static void advertising_stop(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_stop(m_adv_handle);
        APP_ERROR_CHECK(err_code);
    
    }
    
    /**@brief Function for handling button events from app_button IRQ
     *
     * @param[in] pin_no        Pin of the button for which an event has occured
     * @param[in] button_action Press or Release
     */
    static void button_evt_handler(uint8_t pin_no, uint8_t button_action) {
    
      if (button_action == APP_BUTTON_PUSH && pin_no == BUTTON_1) {  
        //nrf_ble_es_on_start_connectable_advertising();
        //adv_stop();
        advertising_stop();
        printf("Stop Ibeacon \n");
      
      }
      if (button_action == APP_BUTTON_PUSH && pin_no == BUTTON_3) {
        printf("Start Eddystone\n");
        nrf_ble_es_init(on_es_evt);
       // es_adv_start_connectable_adv();                                                // le start 
      }
      
      
    }
    
    /**
     * @brief Function for initializing the registation button
     *
     * @retval Values returned by @ref app_button_init
     * @retval Values returned by @ref app_button_enable
     */
    static void button_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {BUTTON_1, false, BUTTON_PULL,  button_evt_handler},
            {BUTTON_3, false, BUTTON_PULL, button_evt_handler},
            {BUTTON_4, false, BUTTON_PULL, button_evt_handler}  //declaration button_4 --MOI--
    
        };
    
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                  APP_TIMER_TICKS(100));
        APP_ERROR_CHECK(err_code);
    
        err_code = app_button_enable();
        APP_ERROR_CHECK(err_code);
    }
    
    
    static void timers_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    static void leds_init(void)
    {
        ret_code_t err_code = bsp_init(BSP_INIT_LEDS, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    
    static void scheduler_init(void)
    {
        APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    }
    
    /**@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 application main entry.
     */
    int main(void)
    {
        // Initialize.
        //log_init();
        timers_init();
        leds_init();
        button_init();
        scheduler_init();
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        conn_params_init();
        advertising_init();
        advertising_start();
        printf("Eddystone App Started\n");
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }
    
    
    /**
     * @}
     */

  • Hi Abdullah_M,

    I am fairly sure that there are just some APIs not being called yet and/or not being called in the correct order.

    However, before we proceed further, do you know that Eddystone is no longer supported by Android?

    Knowing that, do you still wish to explore what is wrong here?

    See:
    android - Is Google deprecating beacon service? Their announcement is ambiguous - Stack Overflow
    and
    Get Beacon Messages  |  Nearby Messages API for Android  |  Google Developers

    Best regards,

    Hieu

  • Hi Hieu,

    Yes, I want to keep exploring this, I'm a beginners in BLE, by the way Could you help me find which API hasn't been called yet and/or hasn't been called in the right order please?

    I read the first article in the first link, i understood that even if i my code is correct, my devices may not receive the packages from Eddystone because Google ended their beacon service? is that right?

    sorry for my english because im not very good.

    Regards.

    Abdullah

  • Hi Abdullah,

    Your English is just fine, please don't worry.

    Sorry for the long wait. The past couple of days I have spent a bit of time to look into the Eddystone specs and our Eddystone library. I found that it is not trivial to fully understand the library at all, mainly due to the security features associated with Eddystone-EID.

    On the other hand, the nRF5 SDK is in maintenance mode (no update, bug fix) since Aug 2021, and all platforms related to Eddystone is completely shut down. That means that further investigation on this is not very beneficial for either of us; and I cannot afford more time than I have.

    So instead of showing you how toggling to an Eddystone advertising packet using the SDK's library can be done, I can show you how to build an Eddystone-UID and/or an Eddystone-URL packet from the ground up; and I can show you how to toggle between them and an iBeacon.

    I'm sorry for the long wait and disappointment, but how does this sound to you?

    By the way, as you are new to the technology and are probably not bound to any specific SDK, what do you think about getting started on the nRF Connect SDK  (NCS) instead? That is our new SDK that is being actively working on. Newer generation chips from Nordic will also be supported on NCS, like the nRF53 that is otherwise not supported in the nRF5 SDK.

    Best regards,

    Hieu

Related