Indoor positioning using nRF52832 + beacons [RSSI, DEVICE NAME, UUID, ADDRESS]

I am developing a nRF52832 based project where I want to position people indoor using an smartband (where the nRF52832 is placed). I was planning to use beacons so I can change their names and say, for example, BEACON_1, BEACON_2, etc.. The idea is that the smartband reads the nearby beacons, get its RSSI and DEVICE NAME (or UUID, address, still no idea..) and send this information from the smartband to the Internet (using other technologies). 

I started with the ble_appp_multilink_central_pca10040_s132 example using the nRF5_SDK_15.3.0 and I modified it a little bit:

First I modified the static void scan_init(void){} function so the device doesn't connect if NAME filter matches.

 

init_scan.connect_if_match = false;   //NO AUTOMATIC CONNECT IF MATCH

I am constantly scaning devices that matches the first part of its name with "BEACON_". To do so I looked on another post and modified the ble_advdata.c (lines 688-691):, specially these lines from:

if (   (data_offset != 0)
        && (parsed_name_len != 0)
        && (strlen(p_target_name) == parsed_name_len)
        && (memcmp(p_target_name, p_parsed_name, parsed_name_len) == 0))*/  //MATCH ALL NAME

To: 

if (   (data_offset != 0)
        && (parsed_name_len != 0)
        && (parsed_name_len >= strlen(p_target_name))
        && (memcmp(p_target_name, p_parsed_name, strlen(p_target_name)) == 0))  //JUST MATCH FIRST PART OF THE NAME

I'm simulating beacons using the nRFConnect app (from iPhone 13) and creating three different ADVERTISEMENTS beacons (BEACON_1, BEACON_2, BEACON_3). It definitely works and they match correctly with the filter. If I change its name into another, lets say BAACON_1, it doesn't match.

I am printing all this staff through the UART in the scan_-evt_handler(...){}:

static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
    ret_code_t err_code;

    switch(p_scan_evt->scan_evt_id)
    {   
        case NRF_BLE_SCAN_EVT_FILTER_MATCH: //CASE ADDED
        {
            int read_rssi = p_scan_evt->params.filter_match.p_adv_report->rssi;
            
            /*NRF_LOG_INFO("Received advertising from: %02x:%02x:%02x:%02x:%02x:%02x:%02x", p_scan_evt->params.p_not_found->peer_addr.addr[0], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[1], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[2], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[3], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[4], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[5]);*/

            //PRINTS PEER ID OF THE CURRENT SCAN
            NRF_LOG_RAW_INFO("PEER ID = ")
            for (int i = 0; i < BLE_GAP_ADDR_LEN; i++){
                NRF_LOG_RAW_INFO("%02x", p_scan_evt->params.connected.p_connected->peer_addr.addr[i]);
            }
            NRF_LOG_RAW_INFO("\r\n");
            
            //PRINTS RSSI VALUE
            NRF_LOG_RAW_INFO("RSSI = %d", read_rssi);
            NRF_LOG_RAW_INFO("\r\n");
            NRF_LOG_RAW_INFO("\r\n");
            
            
            //NRF_LOG_INFO("RSSI = %d", read_rssi);
            break;
        }
        case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
        {
            err_code = p_scan_evt->params.connecting_err.err_code;
            APP_ERROR_CHECK(err_code);
        } break;

        default:
            break;
    }
}

I want the full device name, uuid or device address (whatever I need) to be read in the scan_-evt_handler(...){} so I can know which beacon is the one I am receiving from. My plan is to buy cheap beacons from Amazon, AliExpress... and change its Device Name, UUID or whatever its the easiest (here I am open to new ideas...).

Hope everything is well explained. I am new to the BLE world (and also of nRF52 family, ofc) so I don't have much idea between difference in scan, advertisings, services, GAT and all that stuff. I post my entire main.c so you can check it out:

/**
 * 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.
 *
 */
/**
 * @brief BLE LED Button Service central and client application main file.
 *
 * This example can be a central for up to 8 peripherals.
 * The peripheral is called ble_app_blinky and can be found in the ble_peripheral
 * folder.
 */

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "app_timer.h"
#include "bsp_btn_ble.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "ble_db_discovery.h"
#include "ble_lbs_c.h"
#include "ble_conn_state.h"
#include "nrf_ble_gatt.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_ble_scan.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"


#define APP_BLE_CONN_CFG_TAG      1                                     /**< Tag that refers to the BLE stack configuration that is set with @ref sd_ble_cfg_set. The default tag is @ref APP_BLE_CONN_CFG_TAG. */
#define APP_BLE_OBSERVER_PRIO     3                                     /**< BLE observer priority of the application. There is no need to modify this value. */

#define CENTRAL_SCANNING_LED      BSP_BOARD_LED_0
#define CENTRAL_CONNECTED_LED     BSP_BOARD_LED_1
#define LEDBUTTON_LED             BSP_BOARD_LED_2                       /**< LED to indicate a change of state of the Button characteristic on the peer. */

#define LEDBUTTON_BUTTON          BSP_BUTTON_0                          /**< Button that writes to the LED characteristic of the peer. */
#define BUTTON_DETECTION_DELAY    APP_TIMER_TICKS(50)                   /**< Delay from a GPIOTE event until a button is reported as pushed (in number of timer ticks). */

NRF_BLE_GATT_DEF(m_gatt);                                               /**< GATT module instance. */
BLE_LBS_C_ARRAY_DEF(m_lbs_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT);           /**< LED button client instances. */
BLE_DB_DISCOVERY_ARRAY_DEF(m_db_disc, NRF_SDH_BLE_CENTRAL_LINK_COUNT);  /**< Database discovery module instances. */
NRF_BLE_SCAN_DEF(m_scan);                                               /**< Scanning Module instance. */

static char const m_target_periph_name[] = "BEACON_";             /**< Name of the device to try to connect to. This name is searched for in the scanning report data. */


/**@brief Function for handling asserts in the SoftDevice.
 *
 * @details This function is called in case of an assert in the SoftDevice.
 *
 * @warning This handler is only an example and is not meant for the final product. You need to analyze
 *          how your product is supposed to react in case of an 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] p_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(0xDEADBEEF, line_num, p_file_name);
}


/**@brief Function for initializing the LEDs.
 *
 * @details Initializes all LEDs used by the application.
 */
static void leds_init(void)
{
    bsp_board_init(BSP_INIT_LEDS);
}


static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
    ret_code_t err_code;

    switch(p_scan_evt->scan_evt_id)
    {   
        case NRF_BLE_SCAN_EVT_FILTER_MATCH: //CASE ADDED
        {
            int read_rssi = p_scan_evt->params.filter_match.p_adv_report->rssi;
            
            /*NRF_LOG_INFO("Received advertising from: %02x:%02x:%02x:%02x:%02x:%02x:%02x", p_scan_evt->params.p_not_found->peer_addr.addr[0], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[1], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[2], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[3], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[4], 
                                                                                          p_scan_evt->params.p_not_found->peer_addr.addr[5]);*/

            //PRINTS PEER ID OF THE CURRENT SCAN
            NRF_LOG_RAW_INFO("PEER ID = ")
            for (int i = 0; i < BLE_GAP_ADDR_LEN; i++){
                NRF_LOG_RAW_INFO("%02x", p_scan_evt->params.connected.p_connected->peer_addr.addr[i]);
            }
            NRF_LOG_RAW_INFO("\r\n");
            
            //PRINTS RSSI VALUE
            NRF_LOG_RAW_INFO("RSSI = %d", read_rssi);
            NRF_LOG_RAW_INFO("\r\n");
            NRF_LOG_RAW_INFO("\r\n");
            
            
            //NRF_LOG_INFO("RSSI = %d", read_rssi);
            break;
        }
        case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
        {
            err_code = p_scan_evt->params.connecting_err.err_code;
            APP_ERROR_CHECK(err_code);
        } break;

        default:
            break;
    }
}


/**@brief Function for initializing the scanning and setting the filters.
 */
static void scan_init(void)
{
    ret_code_t          err_code;
    nrf_ble_scan_init_t init_scan;

    memset(&init_scan, 0, sizeof(init_scan));

    init_scan.connect_if_match = false;   //NO AUTOMATIC CONNECT IF MATCH
    init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;

    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, m_target_periph_name);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_NAME_FILTER, false);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for starting scanning. */
static void scan_start(void)
{
    ret_code_t ret;

    NRF_LOG_INFO("Start scanning for device name %s.", (uint32_t)m_target_periph_name);
    ret = nrf_ble_scan_start(&m_scan);
    APP_ERROR_CHECK(ret);
    // Turn on the LED to signal scanning.
    bsp_board_led_on(CENTRAL_SCANNING_LED);
}


/**@brief Handles events coming from the LED Button central module.
 *
 * @param[in] p_lbs_c     The instance of LBS_C that triggered the event.
 * @param[in] p_lbs_c_evt The LBS_C event.
 */
static void lbs_c_evt_handler(ble_lbs_c_t * p_lbs_c, ble_lbs_c_evt_t * p_lbs_c_evt)
{
    switch (p_lbs_c_evt->evt_type)
    {
        case BLE_LBS_C_EVT_DISCOVERY_COMPLETE:
        {
            ret_code_t err_code;

            NRF_LOG_INFO("LED Button Service discovered on conn_handle 0x%x",
                         p_lbs_c_evt->conn_handle);

            err_code = app_button_enable();
            APP_ERROR_CHECK(err_code);

            // LED Button Service discovered. Enable notification of Button.
            err_code = ble_lbs_c_button_notif_enable(p_lbs_c);
            APP_ERROR_CHECK(err_code);
        } break; // BLE_LBS_C_EVT_DISCOVERY_COMPLETE

        case BLE_LBS_C_EVT_BUTTON_NOTIFICATION:
        {
            NRF_LOG_INFO("Link 0x%x, Button state changed on peer to 0x%x",
                         p_lbs_c_evt->conn_handle,
                         p_lbs_c_evt->params.button.button_state);

            if (p_lbs_c_evt->params.button.button_state)
            {
                bsp_board_led_on(LEDBUTTON_LED);
            }
            else
            {
                bsp_board_led_off(LEDBUTTON_LED);
            }
        } break; // BLE_LBS_C_EVT_BUTTON_NOTIFICATION

        default:
            // No implementation needed.
            break;
    }
}


/**@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)
{
    ret_code_t err_code;

    // For readability.
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
        // Upon connection, check which peripheral is connected, initiate DB
        // discovery, update LEDs status, and resume scanning, if necessary.
        case BLE_GAP_EVT_CONNECTED:
        {
            NRF_LOG_INFO("Connection 0x%x established, starting DB discovery.",
                         p_gap_evt->conn_handle);

            APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < NRF_SDH_BLE_CENTRAL_LINK_COUNT);

            err_code = ble_lbs_c_handles_assign(&m_lbs_c[p_gap_evt->conn_handle],
                                                p_gap_evt->conn_handle,
                                                NULL);
            APP_ERROR_CHECK(err_code);

            err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle],
                                              p_gap_evt->conn_handle);
            if (err_code != NRF_ERROR_BUSY)
            {
                APP_ERROR_CHECK(err_code);
            }

            // Update LEDs status and check whether it is needed to look for more
            // peripherals to connect to.
            bsp_board_led_on(CENTRAL_CONNECTED_LED);
            if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
            {
                bsp_board_led_off(CENTRAL_SCANNING_LED);
            }
            else
            {
                // Resume scanning.
                bsp_board_led_on(CENTRAL_SCANNING_LED);
                scan_start();
            }
        } break; // BLE_GAP_EVT_CONNECTED

        // Upon disconnection, reset the connection handle of the peer that disconnected, update
        // the LEDs status and start scanning again.
        case BLE_GAP_EVT_DISCONNECTED:
        {
            NRF_LOG_INFO("LBS central link 0x%x disconnected (reason: 0x%x)",
                         p_gap_evt->conn_handle,
                         p_gap_evt->params.disconnected.reason);

            if (ble_conn_state_central_conn_count() == 0)
            {
                err_code = app_button_disable();
                APP_ERROR_CHECK(err_code);

                // Turn off the LED that indicates the connection.
                bsp_board_led_off(CENTRAL_CONNECTED_LED);
            }

            // Start scanning.
            scan_start();

            // Turn on the LED for indicating scanning.
            bsp_board_led_on(CENTRAL_SCANNING_LED);

        } break;

        case BLE_GAP_EVT_TIMEOUT:
        {
            // Timeout for scanning is not specified, so only the connection requests can time out.
            if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
            {
                NRF_LOG_DEBUG("Connection request timed out.");
            }
        } break;

        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST.");
            // Accept parameters requested by peer.
            err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                        &p_gap_evt->params.conn_param_update_request.conn_params);
            APP_ERROR_CHECK(err_code);
        } 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_GATTC_EVT_TIMEOUT:
        {
            // Disconnect on GATT client timeout event.
            NRF_LOG_DEBUG("GATT client timeout.");
            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.
            NRF_LOG_DEBUG("GATT server timeout.");
            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 LED Button collector initialization. */
static void lbs_c_init(void)
{
    ret_code_t       err_code;
    ble_lbs_c_init_t lbs_c_init_obj;

    lbs_c_init_obj.evt_handler = lbs_c_evt_handler;

    for (uint32_t i = 0; i < NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
    {
        err_code = ble_lbs_c_init(&m_lbs_c[i], &lbs_c_init_obj);
        APP_ERROR_CHECK(err_code);
    }
}


/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupts.
 */
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);

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}


/**@brief Function for writing to the LED characteristic of all connected clients.
 *
 * @details Based on whether the button is pressed or released, this function writes a high or low
 *          LED status to the server.
 *
 * @param[in] button_action The button action (press or release).
 *            Determines whether the LEDs of the servers are ON or OFF.
 *
 * @return If successful, NRF_SUCCESS is returned. Otherwise, returns the error code from @ref ble_lbs_led_status_send.
 */
static ret_code_t led_status_send_to_all(uint8_t button_action)
{
    ret_code_t err_code;

    for (uint32_t i = 0; i< NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
    {
        err_code = ble_lbs_led_status_send(&m_lbs_c[i], button_action);
        if (err_code != NRF_SUCCESS &&
            err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
            err_code != NRF_ERROR_INVALID_STATE)
        {
            return err_code;
        }
    }
        return NRF_SUCCESS;
}


/**@brief Function for handling events from the button handler module.
 *
 * @param[in] pin_no        The pin that the event applies to.
 * @param[in] button_action The button action (press or release).
 */
static void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
    ret_code_t err_code;

    switch (pin_no)
    {
        case LEDBUTTON_BUTTON:
            err_code = led_status_send_to_all(button_action);
            if (err_code == NRF_SUCCESS)
            {
                NRF_LOG_INFO("LBS write LED state %d", button_action);
            }
            break;

        default:
            APP_ERROR_HANDLER(pin_no);
            break;
    }
}


/**@brief Function for initializing the button handler module.
 */
static void buttons_init(void)
{
    ret_code_t err_code;

   // The array must be static because a pointer to it is saved in the button handler module.
    static app_button_cfg_t buttons[] =
    {
        {LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler}
    };

    err_code = app_button_init(buttons, ARRAY_SIZE(buttons), BUTTON_DETECTION_DELAY);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling database discovery events.
 *
 * @details This function is a callback function to handle events from the database discovery module.
 *          Depending on the UUIDs that are discovered, this function forwards the events
 *          to their respective services.
 *
 * @param[in] p_event  Pointer to the database discovery event.
 */
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
    NRF_LOG_DEBUG("call to ble_lbs_on_db_disc_evt for instance %d and link 0x%x!",
                  p_evt->conn_handle,
                  p_evt->conn_handle);

    ble_lbs_on_db_disc_evt(&m_lbs_c[p_evt->conn_handle], p_evt);
}


/** @brief Database discovery initialization.
 */
static void db_discovery_init(void)
{
    ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
    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 This function handles any pending log operations, then sleeps until the next event occurs.
 */
static void idle_state_handle(void)
{
    if (NRF_LOG_PROCESS() == false)
    {
        nrf_pwr_mgmt_run();
    }
}


/** @brief Function for initializing the log module.
 */
static void log_init(void)
{
    ret_code_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();
}


/** @brief Function for initializing the timer.
 */
static void timer_init(void)
{
    ret_code_t err_code = app_timer_init();
    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);
}


int main(void)
{
    // Initialize.
    log_init();
    timer_init();
    leds_init();
    buttons_init();
    power_management_init();
    ble_stack_init();
    gatt_init();
    db_discovery_init();
    lbs_c_init();
    ble_conn_state_init();
    scan_init();

    // Start execution.
    NRF_LOG_INFO("Multilink example started.");
    scan_start();

    for (;;)
    {
        idle_state_handle();
    }
}

Thank you in advance,

Toni

  • Hello Toni,

    So you got your filter working. That is great!

    The rest of the parameters are set up in the advertisement. It is not certain that all the fields are populated, and some may be populated in the scan response instead of the initial advertisement pack. But I suggest that you start looking into how the advertising packet is built up. I don't remember by heart, but I believe that all advertising packets consists of one or more "chunks" where every chunk will consist of one byte saying what type this chunk is, and the next byte indicates what length that chunk has, and the remaining length of the chunk is the payload for that chunk such as the name. What does the advertisement from your peripheral look like at this point in time?

    I see that you are struggling a bit with printing the data in the filter match event. Try something like this:

    NRF_LOG_INFO("filter match: %02x:%02x:%02x:%02x:%02x:%02x", p_adv_report->peer_addr.addr[0],
                                                                p_adv_report->peer_addr.addr[0],
                                                                p_adv_report->peer_addr.addr[0],
                                                                p_adv_report->peer_addr.addr[0],
                                                                p_adv_report->peer_addr.addr[0],
                                                                p_adv_report->peer_addr.addr[0]);
    
    NRF_LOG_INFO("advertising packet:");
    
    for (uint16_t i=0; i<p_adv_report->data.len; i++)
    {
        NRF_LOG_RAW_INFO("%02x:", p_adv_report->data.p_data[i]);
    }

    This will print the address and the raw data. If it contains the name (which it does), try printing the advertisement data using "%c", ...p_data[i] as well, and it will try to print the ascii values for the same data.

    Best regards,

    Edvin

  • Hi Edvin,

    Thanks for your time. I tried printing the data in the filter match event using both %02x (raw data) and %c (ascii values).

    The beacon I bought from Amazon is called "Jinou_Beacon". I think this version its not editable (cannot change the name) but I saw one that is editable, will buy it probably.

    As I told I have two different types of beacon (right now). 

    1) Jinou_Beacon (from Amazon):

        1.1) Stuff received in Ascii:

       

    <info> app: filter match: 11:79:7B:45:3D:E8
    <info> app: advertising packet:
    :       :J:i:n:o:u:_:B:e:a:c:o:n:
    Length= 14
    PEER ID = 000011797B45
    RSSI = -64
    

       1.2) Stuff received in Raw:

        

    <info> app: filter match: 11:79:7B:45:3D:E8
    <info> app: advertising packet:
    0D:09:4A:69:6E:6F:75:5F:42:65:61:63:6F:6E:
    Length= 14
    PEER ID = 000011797B45
    RSSI = -71
    

    2) Simulated Beacon (from iPhone13):

        Name: Jinou_Beacon_1

        2.1) Stuff received in Ascii:

        

    <info> app: filter match: A1:2D:F6:74:56:6F
    <info> app: advertising packet:
    ::::
    ::      :J:i:n:o:u:_:B:e:a:c:o:n:_:1:
    Length= 22
    PEER ID = 0004A12DF674
    RSSI = -46
    

        2.2) Stuff received in Raw:

        

    <info> app: filter match: A1:2D:F6:74:56:6F
    <info> app: advertising packet:
    02:01:1A:02:0A:08:0F:09:4A:69:6E:6F:75:5F:42:65:61:63:6F:6E:5F:31:
    Length= 22
    PEER ID = 0004A12DF674
    RSSI = -48
    

    _____

    I guess that I don't have yet predefined which Beacon I will use and therefore how the name will be allocated in that data array. Probably, if I have stock problems in a future of a specific Beacon I will buy another and I don't want my system to be dependent to one kind of data array distribution (hope I'm explaining well...).

    What's your idea for finding the full name of the Beacon I am reading from?

    Example: 

    char* find_becon_full_name(ble_gap_evt_adv_report_t const * p_adv_report){
        //Process here the p_adv_report data somehow and return the name
        //"Jinou_Beacon", "Jinou_Beacon_1", etc..
    }

    I post again my scan_evt_handler(...) function so you are aligned with me:

    static void scan_evt_handler(scan_evt_t const * p_scan_evt)
    {
        ret_code_t err_code;
    
        switch(p_scan_evt->scan_evt_id)
        {   
            case NRF_BLE_SCAN_EVT_FILTER_MATCH: //CASE ADDED
            {
                ble_gap_evt_adv_report_t const * p_adv_report;
                p_adv_report = p_scan_evt->params.filter_match.p_adv_report;
    
                int read_rssi = p_adv_report->rssi;
                
                /*NRF_LOG_INFO("Received advertising from: %02x:%02x:%02x:%02x:%02x:%02x:%02x", p_scan_evt->params.p_not_found->peer_addr.addr[0], 
                                                                                              p_scan_evt->params.p_not_found->peer_addr.addr[1], 
                                                                                              p_scan_evt->params.p_not_found->peer_addr.addr[2], 
                                                                                              p_scan_evt->params.p_not_found->peer_addr.addr[3], 
                                                                                              p_scan_evt->params.p_not_found->peer_addr.addr[4], 
                                                                                              p_scan_evt->params.p_not_found->peer_addr.addr[5]);*/
                //NRF_LOG_INFO("NAME = %02x\n", p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr[0]);
                
    
                NRF_LOG_INFO("filter match: %02x:%02x:%02x:%02x:%02x:%02x", p_adv_report->peer_addr.addr[0],
                                                                p_adv_report->peer_addr.addr[1],
                                                                p_adv_report->peer_addr.addr[2],
                                                                p_adv_report->peer_addr.addr[3],
                                                                p_adv_report->peer_addr.addr[4],
                                                                p_adv_report->peer_addr.addr[5]);
    
                NRF_LOG_INFO("advertising packet:");
    
                for (uint16_t i=0; i<p_adv_report->data.len; i++)
                {
                    NRF_LOG_RAW_INFO("%c:", p_adv_report->data.p_data[i]);
                }
                NRF_LOG_RAW_INFO("\r\nLength= %d ", p_adv_report->data.len);    
                  
                            //PRINTS PEER ID OF THE CURRENT SCAN
                NRF_LOG_RAW_INFO("\r\nPEER ID = ")
                for (int i = 0; i < BLE_GAP_ADDR_LEN; i++){
                    NRF_LOG_RAW_INFO("%02x", p_scan_evt->params.connected.p_connected->peer_addr.addr[i]);
                }
                NRF_LOG_RAW_INFO("\r\n");
                
                //PRINTS RSSI VALUE
                NRF_LOG_RAW_INFO("RSSI = %d", read_rssi);
                NRF_LOG_RAW_INFO("\r\n");
                NRF_LOG_RAW_INFO("\r\n");
                
                
                //NRF_LOG_INFO("RSSI = %d", read_rssi);
                break;
            }
            case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
            {
                err_code = p_scan_evt->params.connecting_err.err_code;
                APP_ERROR_CHECK(err_code);
            } break;
    
            default:
                break;
        }
    }

    Again, thanks a lot for your time and effort.

    Cheers,

    Toni

  • Hello Toni,

    The advertisements are a bit more complex than only the names. You can see from your raw data that the characters in the name are present, but there is some more data as well.

    There is a good blogpost written by novelbits, which you can find here. If you look at figure 11.1 you will see a descriptive figure of the advertising packets. 

    In your case, let us use the jinou beacon as the example:

    0D:09:4A:69:6E:6F:75:5F:42:65:61:63:6F:6E

    So the first byte/octed is 0x0D = 13, so the advertising structure is 13 bytes long.

    The next octet is 0x09, which refers to the advertising data type. These are probably found in the Bluetooth specification somewhere, but you can look them up in ble_gap.h (SDK\components\softdevice\s132\headers\ble_gap.h)

    We can see that 0x09 is the BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME (search for that string in the file, and you will find the rest).

    So this means that this structure contains the name. 

    The remainder of the packet:

    4A:69:6E:6F:75:5F:42:65:61:63:6F:6E

    translates directly to "Jinou_Beacon" (you can look it up in an online hex -> ascii converter: https://www.rapidtables.com/convert/number/hex-to-ascii.html)

    and the length of the name is 13-1 = 12

    the -1 is because of the byte containing the advertising data type (0x09). 

    Just be aware that not all advertisements contains a name, and if it does, it is not necessarily in the beginning of the packet. So you need to parse the advertisement packet element by element. If the second byte is not 09, then skip n bytes, where n is the first bytes, and repeat.

    This is the background. If you look into the example SDK\examples\ble_central\ble_app_hrs_c, you can see that it ads an advertising name in the scan filter. Then you can see how this filter is implemented in nrf_ble_scan.c, in the on_adv_report() function.

    Particularly the function:

    adv_name_compare(p_adv_report, p_scan_ctx) -> 
    ble_advdata_name_find(p_adv_report->data.p_data,
                          data_len,
                          p_name_filter->target_name[index])) ->
    parsed_name_len = ble_advdata_search(p_encoded_data,
                     data_len,
                     &data_offset,
                     BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);

    which will search through the advertising packet, and look for the advertising name. Perhaps you can modify this to search for only part of the name. At least here you have some theory on how the advertising packet is put together, and what you can look for, and it is up to you to decide what you want your scanner to look for. 

    If you know that the advertising name is always present, and always in the same location in the advertiing packet from your beacons, it is a lot simpler, because you don't need to parse the entire packet. Just check that very location in the advertising packet to see if it matches the name you are looking for.

    BR,
    Edvin

Related