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

BLE Scan with filtering - how to get the content of filtered advertisement messages

Hello guys,

We are performing BLE Scan with filtering by using the device name as a filter.

We are aware of the following facts:

  1. All the advertising packets will be forwarded to the application from the SoftDevice. Not only advertising packets from filtered devices (link).
  2. When advertising packet is received, BLE_GAP_EVT_ADV_REPORT BLE event is triggered (link). Advertising data can be extracted from  p_ble_evt->evt.gap_evt.params.adv_report.data structure.
  3. When scan filter matches, NRF_BLE_SCAN_EVT_FILTER_MATCH scan event is triggered inside scan_evt_handler() function (link).

Now, in our application code, we would like to extract the content only of the advertising packets that match the scan filter (i.e. advertisement packets from BLE devices with particular name).

How can we actually do it? We can successfully detect both BLE_GAP_EVT_ADV_REPORT and NRF_BLE_SCAN_EVT_FILTER_MATCH events but what is the connection between those? Should I set some flag when NRF_BLE_SCAN_EVT_FILTER_MATCH event occurs and extract advertisement data when next BLE_GAP_EVT_ADV_REPORT event happens?

Thanks in advance for your time and efforst.

Cheers,

Bojan.

Parents
  • Hello Bojan,

    The the adv. report pointer is included in the event structure for the NRF_BLE_SCAN_EVT_FILTER_MATCH event, so you don't need to handle the "unfiltered"  BLE_GAP_EVT_ADV_REPORT event separately. I've tried to illustrate this with the code snippet below. Let me know if something is still unclear.

    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:
             {
                 ble_gap_evt_adv_report_t const * p_adv_report;
                 
                adv. report from a device that passed the filter criteria
                 p_adv_report = p_scan_evt->params.filter_match.p_adv_report;
                 
                 //TODO: parse adv report data with "Advertising data encoder" module. Ref. https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.2/group__ble__sdk__lib__advdata.html
             }
             break;
        ...
    ...

    Cheers,

    Vidar

  • Hey, .

    Just tried the approach and it seems to work well! Raised hands

    I just extracted raw data from p_adv_report->data.p_data structure still did not play with Advertising Data Encoder to see how this thing can make my life easier.

    I have a few additional questions here...

    1. When we set a scan filter, does it apply to Scan Response packets as well? In other words, can we use the same approach to extract only desired Scan Response advertising packets?

    2.  According to the theory, when scannable advertising packet is received, Scan Request is automatically sent and Scan Response advertising packet is received. Do we ALWAYS receive Scan Response packet righ after the first BLE Advertising Data packet or it can happen that we receive some nested BLE Advertising Data packets from other devices between Advertising Data and Scan Response data packets of one device?

    Regards,

    Bojan.

  • Just tried and it seems the same scan filter applies to both Advertising Data and Scan Response packets! That's great!

    Concerning question 2, I noticed while printing debug messages that the Scan Response packet ALWAYS comes right after appropriate Advertising Data packet even though some other devices were advertising at the same time. I am not sure though if this is just a coincidence or a rule of operation. Thinking

    I have a hard time though to set a scan filter and include both long name and short name of the device (SCAN_NAME_FILTER and SCAN_SHORT_NAME_FILTER flags) in a scan filter!

    I am doing it this way:

       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 (strlen(m_target_periph_short_name) != 0)
        {
            err_code = nrf_ble_scan_filter_set(&m_scan, 
                                               SCAN_SHORT_NAME_FILTER, 
                                               m_target_periph_short_name);
            APP_ERROR_CHECK(err_code);
        }
    
        err_code = nrf_ble_scan_filters_enable(&m_scan, 
                                               NRF_BLE_SCAN_NAME_FILTER | SCAN_SHORT_NAME_FILTER, 
                                               false);
    
        APP_ERROR_CHECK(err_code);

    However it seems that the funciton:

            err_code = nrf_ble_scan_filter_set(&m_scan, 
                                               SCAN_SHORT_NAME_FILTER, 
                                               m_target_periph_short_name);

    throws an error!

    Do you have any idea what I am doing wrong?

    Thanks in advance!

    Regards,

    Bojan.

  • It seems that we need to specify the min_length of the short name and pass it together with the pointer to short name when setting up the scan filter:

    static const nrf_ble_scan_short_name_t m_target_periph_short_name = {"Test", 4};
    
    err_code = nrf_ble_scan_filter_set(&m_scan, 
                                       SCAN_SHORT_NAME_FILTER, 
                                       &m_target_periph_short_name);
    APP_ERROR_CHECK(err_code);

    The function does not throw any error now but the advertisement message still does not appear under NRF_BLE_SCAN_EVT_FILTER_MATCH events. Any advice?

  • Looks like you are doing it correctly. Are you able to debug the app and verify that the peripheral device is indeed advertising the short name "Test"?

  • I am using nRF Connect for Desktop to specify the content of both Advertising and Scan Response packets. I put full name in one packet and short name in another but I am only able to read Advertising data packet.

    Anyway, I found the workaround for that. I will scan only for full names and, once NRF_BLE_SCAN_EVT_FILTER_MATCH is triggered, I will check with p_adv_report->type.scan_response flag if it is Advertising packet or Scan Response packet. In the case of Scan Response packet

    p_adv_report->type.scan_response = 0x01

Reply
  • I am using nRF Connect for Desktop to specify the content of both Advertising and Scan Response packets. I put full name in one packet and short name in another but I am only able to read Advertising data packet.

    Anyway, I found the workaround for that. I will scan only for full names and, once NRF_BLE_SCAN_EVT_FILTER_MATCH is triggered, I will check with p_adv_report->type.scan_response flag if it is Advertising packet or Scan Response packet. In the case of Scan Response packet

    p_adv_report->type.scan_response = 0x01

Children
No Data
Related