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

THE EVENT NRF_BLE_SCAN_EVT_WHITELIST_REQUEST DOES NOT OCCUR

Good morning,

I am developing an application that needs to match a central with a specific peripheral.
For this, the first time they connect, the address must be saved and from now on it will only be possible to connect with that peripheral.
I have preferred to use the whitelist for possible future changes.
After using the treatment that the application "ble_app_hrs_c" does with the whitelist, I have not been able to make my application work.
Using a filter by name and without the whitelist, it does work. The problem seems to be that there is no way to get the event "NRF_BLE_SCAN_EVT_WHITELIST_REQUEST" to occur, since the message "Whitelist Request." does not appear.
However in the application "ble_app_hrs_c", it does.

I've been trying for many hours to make it work but it has been impossible.
I enclose part of the application related to the aforementioned.
TaskMain() is where scan_start() and idle_state_handle() are called depending on certain conditions.
I also send a screenshot of the debugger.
I'm using:

- nRF5 SDK v17.0.2
- nRF52832
- S132 SoftDevice

Please, can you help me with this problem?
Thanks in advance.



#define SEC_PARAM_BOND              1                                   /**< Perform bonding. */
#define SEC_PARAM_MITM              0                                   /**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC              0                                   /**< LE Secure Connections enabled. */
#define SEC_PARAM_KEYPRESS          0                                   /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES   BLE_GAP_IO_CAPS_NONE                /**< No I/O capabilities. */
#define SEC_PARAM_OOB               0                                   /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE      7                                   /**< Minimum encryption key size in octets. */
#define SEC_PARAM_MAX_KEY_SIZE      16                                  /**< Maximum encryption key size in octets. */

NRF_BLE_SCAN_DEF(m_scan);                                       /**< Scanning module instance. */
BLE_LBS_C_DEF(m_ble_lbs_c);                                     /**< Main structure used by the LBS client module. */
NRF_BLE_GATT_DEF(m_gatt);                                       /**< GATT module instance. */
BLE_DB_DISCOVERY_DEF(m_db_disc);                                /**< DB discovery module instance. */
NRF_BLE_GQ_DEF(m_ble_gatt_queue,                                /**< BLE GATT Queue instance. */
               NRF_SDH_BLE_CENTRAL_LINK_COUNT,
               NRF_BLE_GQ_QUEUE_SIZE);

static bool     m_whitelist_enabled;                            /**< False if whitelist has been temporarily disabled. */
static bool     m_memory_access_in_progress;                    /**< Flag to keep track of ongoing operations on persistent memory. */
static INT8U    statusBLE = INIT;
static INT8U    taskMotor = 0;
static INT8U    input = 0xff;
static INT16U   timeFlush = 0;
static INT16U   degreeFlush = 0;

// POSIBILIDADES DE SCANNIG
static char const m_target_periph_name[] = DEVICE_NAME;         /**< Name of the device we try to connect to. This name is searched in the scan report data*/
//static char const m_target_periph_name[] = "";		/**< If you want to connect to a peripheral using a given advertising name, type its name here. */

static bool is_connect_per_addr = false;			/**< If you want to connect to a peripheral with a given address, set this to true and put the correct address in the variable below. */
static ble_gap_addr_t const m_target_periph_addr =		/**< ** IMPORTANT ** modify NRF_BLE_SCAN_ADDRESS_CNT = 1 (as example) in sdk_config.h. ** IMPORTANT ** Set it to 0 if don't use it*/
{
    /* Possible values for addr_type:
       BLE_GAP_ADDR_TYPE_PUBLIC,
       BLE_GAP_ADDR_TYPE_RANDOM_STATIC,
       BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE,
       BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */
    .addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC,
    //.addr      = {0x8D, 0xFE, 0x23, 0x86, 0x77, 0xD9}
    //.addr      = {0xF1, 0x09, 0x50, 0x03, 0xEA, 0xDE}
    .addr      = {0x64, 0x97, 0xDC, 0x18, 0x75, 0xD7}
};

static bool is_connect_per_uuid = false;			/**< If you want to connect to a peripheral with UUID, set this to true and put the correct UUID data in the variable below. */
#define TARGET_UUID         BLE_UUID_HEART_RATE_SERVICE         /**< Target device uuid that application is looking for. */
ble_uuid_t uuid =
{ 
    .uuid = TARGET_UUID,
    /* Possible values for Types of UUID:
       BLE_UUID_TYPE_UNKNOWN,	    Invalid UUID type
       BLE_UUID_TYPE_BLE,	    Bluetooth SIG UUID (16-bit)
       BLE_UUID_TYPE_VENDOR_BEGIN   Vendor UUID types start at this index (128-bit)*/
    .type = BLE_UUID_TYPE_BLE,
};


// Function to start scanning.
static void scan_start (void)
{
    ret_code_t err_code;

    if (nrf_fstorage_is_busy(NULL)) {
        m_memory_access_in_progress = true;
        return;
    }

    NRF_LOG_INFO("Starting scan.");

    err_code = nrf_ble_scan_start(&m_scan);         // A partir de aqui se producira un NRF_BLE_SCAN_EVT_WHITELIST_REQUEST
    APP_ERROR_CHECK(err_code);

    statusBLE = SCANNING;
}

/** @brief Clear bonding information from persistent storage
 */
static void delete_bonds (void)
{
    ret_code_t err_code;

    NRF_LOG_INFO("Erase bonds!");

    err_code = pm_peers_delete();
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for starting a scan, or instead trigger it from peer manager (after
 *        deleting bonds).
 *
 * @param[in] p_erase_bonds Pointer to a bool to determine if bonds will be deleted before scanning.
 */
void scanning_start (bool erase_bonds)
{
    // Start scanning for peripherals and initiate connection
    // with devices that advertise GATT Service UUID.
    if (erase_bonds == true) {
        // Scan is started by the PM_EVT_PEERS_DELETE_SUCCEEDED event.
        delete_bonds();
    } else {
        scan_start();
    }
}


/**@brief Function for handling Peer Manager events.
 *
 * @param[in] p_evt  Peer Manager event.
 */
static void pm_evt_handler(pm_evt_t const * p_evt)
{
    pm_handler_on_pm_evt(p_evt);
    pm_handler_flash_clean(p_evt);

    NRF_LOG_INFO("Peer event");
    switch (p_evt->evt_id) {
        case PM_EVT_CONN_SEC_SUCCEEDED:
            //m_peer_id = p_evt->peer_id;
            break;
        case PM_EVT_PEERS_DELETE_SUCCEEDED:
            // Bonds are deleted. Start scanning.
            NRF_LOG_INFO("Peers Deleted Succeeded");
            scan_start();
            break;
 /*       case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
            if (p_evt->params.peer_data_update_succeeded.flash_changed
                 && (p_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_BONDING))
            {
                NRF_LOG_INFO("New Bond, add the peer to the whitelist if possible");
                // Note: You should check on what kind of white list policy your application should use.

                whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR);
            }
            break;
*/
        default:
            break;
    }
}


static void peer_manager_init(void)
{
    ble_gap_sec_params_t sec_param;
    ret_code_t err_code;

    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures.
    sec_param.bond           = SEC_PARAM_BOND;
    sec_param.mitm           = SEC_PARAM_MITM;
    sec_param.lesc           = SEC_PARAM_LESC;
    sec_param.keypress       = SEC_PARAM_KEYPRESS;
    sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
    sec_param.oob            = SEC_PARAM_OOB;
    sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
    sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
    sec_param.kdist_own.enc  = 1;
    sec_param.kdist_own.id   = 1;
    sec_param.kdist_peer.enc = 1;
    sec_param.kdist_peer.id  = 1;

    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);

    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_INFO("Peer Manager Init");
}


// Function for handling Scaning events.
// param[in]   p_scan_evt   Scanning event.
static void scan_evt_handler (scan_evt_t const * p_scan_evt)
{
    ret_code_t err_code;

    NRF_LOG_INFO("Scan event");
    switch(p_scan_evt->scan_evt_id) {
        case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
            NRF_LOG_INFO("Connecting Error");
            err_code = p_scan_evt->params.connecting_err.err_code;
            APP_ERROR_CHECK(err_code);
            break;
        case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
            NRF_LOG_INFO("Whitelist Request.");
            on_whitelist_req();
            m_whitelist_enabled = true;
            break;
         case NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT:
            NRF_LOG_INFO("Whitelist Adv Report.");
            //sd_ble_gap_connect(....);             // No porque connect_if_match = true. Lo hace automaticamente
            break;
        case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
            NRF_LOG_INFO("Scan timed out.");
            scan_start();
            break;
        case NRF_BLE_SCAN_EVT_FILTER_MATCH:
            break;
        default:
            break;
    }
}


// Function to set scanning parameters
static void scan_init (void)
{
    ret_code_t		    err_code;
    nrf_ble_scan_init_t	    init_scan;
    ble_gap_scan_params_t   * p_scan_param; // BLE GAP scan parameters required to initialize the module. Can be initialized as NULL. 
					    // If NULL, the parameters required to initialize the module are loaded from the static configuration
    // Setting parameters for scanning.
    p_scan_param->active	= 1;
    p_scan_param->interval	= SCAN_INTERVAL;    //default = NRF_BLE_SCAN_SCAN_INTERVAL;
    p_scan_param->window	= SCAN_WINDOW;	    //default = NRF_BLE_SCAN_SCAN_WINDOW;
    p_scan_param->filter_policy = BLE_GAP_SCAN_FP_WHITELIST; 
    p_scan_param->timeout	= 3000;                 //SCAN_DURATION;    //default = NRF_BLE_SCAN_SCAN_DURATION;
    p_scan_param->scan_phys	= BLE_GAP_PHY_1MBPS;

    // Save memory for scanning parameters
    memset(&init_scan, 0, sizeof(init_scan));

    init_scan.connect_if_match	= true;             // Conecta automaticamente si filter o whitelist coinciden
    init_scan.conn_cfg_tag	= APP_BLE_CONN_CFG_TAG;
    init_scan.p_scan_param	= p_scan_param;

    //m_scan.scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL;
    //m_scan.scan_params.active = false;

    // Setting other parameters for scanning.
    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
    APP_ERROR_CHECK(err_code);

    if (is_connect_per_uuid) {
        err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_UUID_FILTER, &uuid);
        if (err_code != NRF_SUCCESS)
            NRF_LOG_INFO("Scan Filter Set Error");
        APP_ERROR_CHECK(err_code);
    }

    if (strlen(m_target_periph_name) != 0) {
        err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, m_target_periph_name);
        APP_ERROR_CHECK(err_code);
    }

    if (is_connect_per_addr) {
       err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, m_target_periph_addr.addr);
       APP_ERROR_CHECK(err_code);
    }

    // Setting filters for scanning by name and other.
    err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ALL_FILTER, false);
    APP_ERROR_CHECK(err_code);
}

/****************************************************************************************
*    MAIN FUNCTION
*****************************************************************************************/
int main (void)
{
    INT32U err_code;

    // Initialize.
    log_init();

    initDrivers();

    gpio_init();
    power_management_init();
    ble_stack_init();

    gatt_init();
    peer_manager_init();
    db_discovery_init();
    lbs_c_init();

    scan_init();                 // Scan-Init 

    // Start execution.
    NRF_LOG_INFO("CentralMotor started.");

    // Enter main loop.
    for (;;) {
        taskMain();
    }
}

 
Parents
  • Hi,

    I notice this part of your code especially:

        ble_gap_scan_params_t   * p_scan_param; // BLE GAP scan parameters required to initialize the module. Can be initialized as NULL. 
    					    // If NULL, the parameters required to initialize the module are loaded from the static configuration
        // Setting parameters for scanning.
        p_scan_param->active	= 1;
        p_scan_param->interval	= SCAN_INTERVAL;    //default = NRF_BLE_SCAN_SCAN_INTERVAL;
        ...

    This is certainly a problem your p_scan_param pointer is not initialized, so it will point to random memory and you use it. So basically anything could happen. This needs to be fixed so that you write to an actualy struct and then point to that struct in init_scan.p_scan_param. It could be as simple as this instead:

    static void scan_init (void)
    {
        ret_code_t		    err_code;
        nrf_ble_scan_init_t	    init_scan;
        static ble_gap_scan_params_t   scan_param = {}; // BLE GAP scan parameters required to initialize the module. Can be initialized as NULL. 
    					    // If NULL, the parameters required to initialize the module are loaded from the static configuration
        // Setting parameters for scanning.
        scan_param.active	= 1;
        scan_param.interval	= SCAN_INTERVAL;    //default = NRF_BLE_SCAN_SCAN_INTERVAL;
        scan_param.window	= SCAN_WINDOW;	    //default = NRF_BLE_SCAN_SCAN_WINDOW;
        scan_param.filter_policy = BLE_GAP_SCAN_FP_WHITELIST; 
        scan_param.timeout	= 3000;                 //SCAN_DURATION;    //default = NRF_BLE_SCAN_SCAN_DURATION;
        scan_param.scan_phys	= BLE_GAP_PHY_1MBPS;
    
        // Save memory for scanning parameters
        memset(&init_scan, 0, sizeof(init_scan));
    
        init_scan.connect_if_match	= true;             // Conecta automaticamente si filter o whitelist coinciden
        init_scan.conn_cfg_tag	= APP_BLE_CONN_CFG_TAG;
        init_scan.p_scan_param	= &scan_param;
    ...

  • Hi,

    The project runs on a client card, but for the purpose of checking the peer I suppose
    there will be no problem with it running on a DK.

    Initially, it started with the ble_app_blinky_c application to operate various
    devices (motor, LEDs, beeper, I2C, motorSensor, whitelist, etc.) as a way of learning,
    but when everything works, the idea is to make it work as a UART and send-receive
    control commands.

    you can see that the reception in lbs_c_evt_handler() was changed to 2 bytes.

    SENSOR_M_s132.rar

  • I do not see anything that sticks out. Dou you have peripheral code that runs on a DK as well? Also, can you upload the log from the central when you test, including initial scanning, initial connection, connection, pairing, disconnect, scanning (where it should have been with whitelist)?

  • SENSOR_S_s132.rar

    Hi Einar,

    Attached is the peripheral project that works with a position sensor.
    I also send you a screenshot of the debugger.
    As you can see, arrow 1 indicates that initially the whitelist is deactivated and the whitelist counters are at 0.
    From the second connection the counters continue at 0 and the whitelist is activated.
  • Hi,

    You do not do pairing (the peer manager is not even initialized on your peripheral device), so there is no way to get a whitelist from the bonding information. I suggest you add a bit more logging for instance when bonding (and potentially also reading out number of bonds with pm_peer_count() when you generate the whitelist) to see this more clearly while you are working with it.

    You can populate the whitelist without bonding and without the peer manager as well if you want to, but if you intend to use bonding (as you write), then you should fix this and then you will get whitelisting for free by just doing exactly as the example application.

Reply
  • Hi,

    You do not do pairing (the peer manager is not even initialized on your peripheral device), so there is no way to get a whitelist from the bonding information. I suggest you add a bit more logging for instance when bonding (and potentially also reading out number of bonds with pm_peer_count() when you generate the whitelist) to see this more clearly while you are working with it.

    You can populate the whitelist without bonding and without the peer manager as well if you want to, but if you intend to use bonding (as you write), then you should fix this and then you will get whitelisting for free by just doing exactly as the example application.

Children
Related