BLE scan() not returning complete advertisement payload

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
Blip!
Posts: 3
Joined: Sun Jan 24, 2021 5:52 pm

BLE scan() not returning complete advertisement payload

Post by Blip! » Sun Feb 21, 2021 5:25 pm

020106111695fe30585b05015646d238c1a4280100
020106111695FE30585B05015646D238C1A42801000B094C5957534430334D4D43

BLE Scan() not returning complete advertisement payload

Summary: Micropython Bluetooth BLE scan() does not return the complete advertisement payload, specifically missing "Complete Local Name".

Setup: I'm trying to scan and discover a Xiaomi temperature device using Micropython. Using the APP "nRF Connect" on my phone displays the following advertised raw data:

Code: Select all

020106111695FE30585B05015646D238C1A42801000B094C5957534430334D4D43
Broken up, this decodes to the following details

Code: Select all

len==2,  0x01==FLAGS:           0201 06 
len==17, 0x16==SERVICE_DATA:    1116 95FE30585B05015646D238C1A4280100
len==11, 0x09==NAME:            0B09 4C5957534430334D4D43
The last element is the 0x09 (Complete Local Name), but the problem is that Micropython ble.scan() does not return the complete advert. payload. When scanning in Micropythin, the last element (name) is missing. The raw data returned in `adv_data` is:

Code: Select all

020106111695fe30585b05015646d238c1a4280100
I just made a small modification to `_irq(...)` ble_simple_central.py to simply display all discovered devices and to illustrate the problem:

Code: Select all

    def _irq(self, event, data):
        if event == _IRQ_SCAN_RESULT:
            addr_type, addr, adv_type, rssi, adv_data = data
            addr_h = binascii.hexlify(bytes(addr)).decode('utf-8')
            adv_data_h = binascii.hexlify(bytes(adv_data)).decode('utf-8')
            print('addr_type: {}, addr: {}, adv_type: {}, rssi: {}, adv_data: {}'.format(addr_type, addr_h, adv_type, rssi, adv_data_h))
The output (for the Xiaomi device) is:

Code: Select all

addr_type: 0, addr: a4c138d24656, adv_type: 0, rssi: -68, adv_data: 020106111695fe30585b05015646d238c1a4280100
Am I forgetting something?
Does the Xiaomi misbehave?
(edited: typos and details)

Blip!
Posts: 3
Joined: Sun Jan 24, 2021 5:52 pm

Re: BLE scan() not returning complete advertisement payload

Post by Blip! » Sun Feb 21, 2021 10:07 pm

Based on comment and great tip from Emil at stackoverflow, the solution is to set parameter 'active' in BLE.gap_scan(..., active=True) to receive scan responses in the results.

This makes the irq callback receive 2 separate messages with different adv_types:

0x00 - ADV_IND - containing the advertising data
0x04 - SCAN_RSP - containing the name

Doc ref: Observer Role (Scanner)

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: BLE scan() not returning complete advertisement payload

Post by jimmo » Mon Feb 22, 2021 2:59 am

Blip! wrote:
Sun Feb 21, 2021 10:07 pm
Based on comment and great tip from Emil at stackoverflow, the solution is to set parameter 'active' in BLE.gap_scan(..., active=True) to receive scan responses in the results.
Yes, that's exactly right.

I have implemented logic to automatically merge and parse the scan response with the advertising data during scan in the "aioble" library that I'm working on. You can see the logic here: https://github.com/jimmo/micropython-li ... al.py#L136

Anyway, I plan to send this as a PR shortly to micropython-lib, just finishing up a few more examples and tests. https://github.com/jimmo/micropython-li ... ble/aioble

Post Reply