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();
}
}