Looking for MBED BLE Scanner (Central Function) with filter scanning

I am having a hard time finding a MBED OS BLE central function example. If anyone knows of a suitable example that can provide filter scanning (i.e. filter for a specific advertising service UUID), in particular, please let me know.

What I’ve seen so far on the MBED GitHub repository is not great. Most examples are for peripheral device functionality. The closest if this BLE GAP example, but this example simply rotates through different GAP modes and only provides GAP type information on duration and interval data, as per this output:

Starting next GAP demo mode
DEVICE MAC ADDRESS: :::::

Scanning started (interval: 100ms, window: 62ms, timeout: 3000ms).
Stopped scanning early due to timeout parameter
We have scanned for 3182ms with an interval of 160 timeslots and a window of 100 timeslots
We have been listening on the radio for at least 1937ms

Starting next GAP demo mode
DEVICE MAC ADDRESS: :::::

Scanning started (interval: 100ms, window: 25ms, timeout: 0ms).
We have scanned for 5999ms with an interval of 160 timeslots and a window of 40 timeslots
We have been listening on the radio for at least 1475ms

Starting next GAP demo mode
DEVICE MAC ADDRESS: :::::

Scanning started (interval: 312ms, window: 6ms, timeout: 0ms).
We have scanned for 5999ms with an interval of 500 timeslots and a window of 10 timeslots
We have been listening on the radio for at least 118ms

Starting next GAP demo mode
DEVICE MAC ADDRESS: :::::

Advertising started (type: 0x0, interval: [25 : 50]ms)
We have advertised for 5999ms with an interval of at least 80 timeslots
We created at least 0 tx and rx events

Starting next GAP demo mode
DEVICE MAC ADDRESS: :::::

Advertising started (type: 0x2, interval: [62 : 125]ms)
Advertiser xAdvertising started (type: 0x2, interval: [62 : 125]ms)

… etc.

It’s also rather difficult to actually work out how to get the MBED BLE central function firmware to connect to a peripheral device and bond, if necessary.

But for now I simply wish to parse out scan results and analyse UUID and UUID data/payload (e.g. create a Beacon scanner).

After trawling through the BLE_GAP example code, I see that this example does in fact provide scan result data via the virtual void onAdvertisingReport ( const AdvertisingReportEvent & event ) function but that the example code had used an arbitrary condition, which meant that I did not see any results

if (event.getRssi() < -65) { return; }

Then there is another function called AdvertisingDataParser which will parse out the payload.

It is still not clear from this where I find the advertising UUID. I assume it is somewhere in the
ble::AdvertisingDataParser::element_t field = adv_parser.next();

Any idea?

As no one else has contributed, thought to share further discoveries as I make them.

I found that within the onAdvertisingReport function we can make some changes.

First change I made is to let the routine while (adv_parser.hasNext()) { ... } loop through all the “fields”.

Then I can apply this check, or equivalent:

if (field.type == ble::adv_data_type_t::INCOMPLETE_LIST_16BIT_SERVICE_IDS) { ... }

That check seems to at least confirm if a 16bit SSID exists etc.

Next challenge is to actually check the SSID value…

EDIT: Which it turns out is very easy to get using field.value[x]

If you use field.value.size() to confirm you’ll find this to be divisible by 2, depending on how many 16 bit UUID’s are listed etc.

1 Like

Hi Gerriko, how are you, I am currently working on something similar, but it seems i am missing something, would you be able to share with me your implementation?

It’s implemented as described, so I’m not sure what you mean by “it seems I am missing something”. I suggest you show your code and maybe I/we can spot what’s missing.

1 Like

So inside of my onAdvertising report function this is what I have

Blockquote
void BleScanner::onAdvertisingReport(const ble::AdvertisingReportEvent &event)
{
ble::AdvertisingDataParser adv_parser(event.getPayload())

while (adv_parser.hasNext()) {
 }
  if (field.type == ble::adv_data_type_t::COMPLETE_LOCAL_NAME) { ... }

Blockquote

So I want to be able to check is the Complete_local name Test_Ble is contained in the packet then thats only when i can read the whole packet, so earlier on you said you can loop through all the fields? Is that how you also implemented it, because it not working on my side currently

thanks

That looks correct (MbedOS v6.15 Reference for adv_data_type_t).

When you say “it is not working on my side” what do you mean.

For example, are you getting a compile error, a runtime error, or simply that the “if” function is never triggered. If the latter, have you tried any of the other adv_data_type data types to check that that function works as intended.

1 Like

So basically i am scanning for a specific device and i want to be able to read an advertising packet once i get a packet from that device, so in the data types, i know the device complete local name, manufacturer data and service data uuid16, so i was hoping that if i check for those i can get to my device, so there is no error thrown at all, but what i cannot see is the data typesit seems like its not even getting to my device at all…

It sounds like you have a problem with your code logic.

It would help if you share your code.

void BleScanner::onAdvertisingReport(const ble::AdvertisingReportEvent &event)

{

ble::AdvertisingDataParser adv_parser(event.getPayload());

ble::AdvertisingDataParser::element_t field;

while (adv_parser.hasNext()) {

 }

field = adv_parser.next();

if (field.type != ble::adv_data_type_t::MANUFACTURER_SPECIFIC_DATA ||

        field.type != ble::adv_data_type_t::SERVICE_DATA ||

        field.type != ble::adv_data_type_t::SERVICE_DATA_16BIT_ID ||

        !GapAdvertisingData::LE_GENERAL_DISCOVERABLE ) {

            adv_parser.reset();

            return;

    }

   _event_queue.cancel(_on_duration_end_id);

    printf("We found our device\r\n");

    ble_error_t error = _ble.gap().connect(

                            event.getPeerAddressType(),

                            event.getPeerAddress(),

                            ble::ConnectionParameters() // use the default connection parameters

                        );

    if (error) {

        printf("Error caused by Gap::connect");

        /* since no connection will be attempted end the mode */

        _event_queue.call(this, &BleScanner::end_scan_mode);

        return;

    }

    adv_parser.reset();

    /* we may have already scan events waiting

     * to be processed so we need to remember

     * that we are already connecting and ignore them */

    _is_connecting = true;

    return;

}

there is my function.

Have a look at the Mbed’s BLE Gap example on Github: mbed-os-example-ble/main.cpp at development · ARMmbed/mbed-os-example-ble · GitHub

On line 294 there is the relevant function:
ble::AdvertisingDataParser adv_parser(event.getPayload());

You should notice the difference. This function contains the parsing code within the while loop. You don’t have that, hence your code is not finding the field type(s) you are looking for.

Hope that helps.