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

Minimum Requirements for Scanning Filters

Hi,

I am currently trying to implement a beacon scanner alongside peripheral mode BLE on an nRF52832. As I am only scanning for beacons, I was hoping I would not need to include any code other than "nrf_ble_scan.c" and ignore the rest of the central libraries.

My code is working well, expect the filters aren't firing, even though there is definitely a match. I tested this by setting my beacon UUID to that of the NUS service and ran the "ble_nus_c" example before running my custom code. The "ble_nus_c" worked well with my beacon and correctly gave me an NRF_BLE_SCAN_EVT_FILTER_MATCH event. However, in my custom code, this event never fires. I am initialising the scanning module in exactly the same way as the example. Code Below:

static ble_uuid_t const m_beacon_uuid = { .uuid = 0x0001, .type = BLE_UUID_TYPE_VENDOR_BEGIN };

NRF_BLE_SCAN_DEF( m_scan );

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_SCAN_TIMEOUT:
{
NRF_LOG_INFO( "Scan timed out." );
scan_start( );
}
break;

case NRF_BLE_SCAN_EVT_FILTER_MATCH:
{
NRF_LOG_INFO( "Filter Match" );
} break;

case NRF_BLE_SCAN_EVT_NOT_FOUND:
{
NRF_LOG_INFO( "%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] );
}break;

default:
break;
}
}

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;

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_UUID_FILTER, &m_beacon_uuid );
APP_ERROR_CHECK( err_code );

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

static void scan_start( void )
{
ret_code_t ret;

ret = nrf_ble_scan_start( &m_scan );
APP_ERROR_CHECK( ret );
}

Does the "nrf_ble_scan" module also require "db_discovery" or similar to be initialised in order to allow these filters to work?

Thanks!

EDIT: To clarify, the scanning module correctly starts scanning, and using the NRF_LOG_INFO() in the BLE_SCAN_EVT_NOT_FOUND event I can see my central is scanning and finding devices, including the one that should cause a filter match, but the filter is never returning as true

Parents Reply Children
  • Hi Ben, 

    These filters are intended to decide what device to connect to. You can see how they are used in nrf_ble_scan.c, in the nrf_ble_scan_on_adv_report() function.

    The softdevice doesn't filter based on these filter settings. It is up to the application (nrf_ble_scan.c). Depending on whether all_filter_mode is true or false, you need to match all the set filters, or only one in order to trigger the NRF_BLE_SCAN_EVT_FILTER_MATCH event or not. 

    It will also call nrf_ble_scan_connect_with_target() which will connect to the target in case of NRF_BLE_SCAN_EVT_FILTER_MATCH if .connect_if_match is true.

    So the assumption that the softdevice will filter out the advertisements and only pass the filter matched advertisements to BLE_GAP_EVT_ADV_REPORT event is not true. All advertisements will be forwarded to BLE_GAP_EVT_ADV_REPORT, but only the filter matches will be passed onto the NRF_BLE_SCAN_EVT_FILTER_MATCH event.

    Is your code able to get inside the nrf_ble_scan_on_adv_report()? Does it match all the set filters? 

    -Amanda H.

Related