BLE Broadcasts vs Scans

The official PYBD running MicroPython, and its accessories.
Target audience: Users with a PYBD
Post Reply
User avatar
devnull
Posts: 452
Joined: Sat Jan 07, 2017 1:52 am
Location: Singapore / Cornwall
Contact:

BLE Broadcasts vs Scans

Post by devnull » Wed Nov 06, 2019 3:26 am

Sorrie for all of the BLE questions, I have googled but are not able to find a direct answer.

It appears that beacons broadcast and that it is not necessary to connect to the device, but just to listen for a specific device broadcast and read it's data.

But how would you do this ? - I know that with a scan you get a list of nearby devices, but how do you actively listen for broadcasts from devices ??

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

Re: BLE Broadcasts vs Scans

Post by jimmo » Wed Nov 06, 2019 3:52 am

A beacon is an advertiser that includes some application-specific data in its advertising payload. (Normally, devices would use this payload to indicate which services they support, appearance, name, etc).

A scanner sees the advertising payload and extracts the beacon data.

This process is entirely passive -- the advertiser just sends out its advertising messages at some interval, the scanner listens on the three channels and opportunistically receives these messages. (This is why the window and interval parameters to gap_scan are important)

Unfortunately the advertising payload is tiny. So there is an extension to this called "active scanning" where the scanner can then attempt to query an advertiser for more data (this is the scan_resp kwarg to gap_advertise). (This is different to connecting, it's just a message that the scanner can send to an advertising device, to which the advertising device will respond with this additional data).

The MicroPython API supports a beacon setting the scan_resp data, but does not currently support a scanner receiving it (we always do "passive scans"). I plan to add this later.

User avatar
devnull
Posts: 452
Joined: Sat Jan 07, 2017 1:52 am
Location: Singapore / Cornwall
Contact:

Re: BLE Broadcasts vs Scans

Post by devnull » Wed Nov 06, 2019 4:11 am

Jimmo, thanks, that's very helpful.

I have already checked the scan manufacturer's data and it does not contain active data, only static data such as the mac address and a couple of other byte variables.

Code: Select all

b"\x02\x01\x06\x03\x02 \xaa\x0e\xff\x00\x1f\x00\x00B\x01d\xcb\xd0\xc5\x0c'\xbd"

User avatar
devnull
Posts: 452
Joined: Sat Jan 07, 2017 1:52 am
Location: Singapore / Cornwall
Contact:

Re: BLE Broadcasts vs Scans

Post by devnull » Wed Nov 06, 2019 5:32 am

Also, not sure if this is related to the gap-scan timing you mentioned, but very often devices which the mac is known and can be connected to do not appear in the scan results, whether or not they are already connected.

Only if I scan several times for a minute at a time will these devices be eventually discovered.

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

Re: BLE Broadcasts vs Scans

Post by jimmo » Wed Nov 06, 2019 5:35 am

Yes it's most likely exactly that. Try:

Code: Select all

ble.gap_scan(duration_ms, 30000, 30000)
which is the fastest allowable scan. The default is that it spends a lot of time sleeping in order to save power. See https://github.com/micropython/micropython/pull/5190 for more info.

User avatar
devnull
Posts: 452
Joined: Sat Jan 07, 2017 1:52 am
Location: Singapore / Cornwall
Contact:

Re: BLE Broadcasts vs Scans

Post by devnull » Wed Nov 06, 2019 7:40 am

Yes, using those options it finds the devices immediately

Eckaard
Posts: 2
Joined: Fri May 15, 2020 6:45 am

Re: BLE Broadcasts vs Scans

Post by Eckaard » Fri May 15, 2020 10:11 am

Hi,

I was hoping you could perhaps help me out. I am trying to implement a continuous scan which only ends once a specific ble beacon is found (I did read somewhere that the scanning timeouts after 7 hours, If this is the max, I'll just restart the process). Once found a different process will start. My current code, which doesn't work as I wish it to, only scans for a short amount of time before stopping even if the beacon wasn't detected. The code also only works when I include a time.sleep() for more than 2 seconds and then it only detects some beacons.

Code: Select all

import ubluetooth
import ubinascii
from micropython import const

_IRQ_SCAN_RESULT                     = const(1 << 4)
_IRQ_SCAN_COMPLETE                   = const(1 << 5)

def bt_irq(event, data):
	if event == _IRQ_SCAN_COMPLETE:
		print("complete")
	elif event == _IRQ_SCAN_RESULT:
		addr_type, addr, adv_type, rssi, adv_data = data
		print('type:{} addr:{} rssi:{} data:{}'.format(addr_type, ubinascii.hexlify(addr), rssi, ubinascii.hexlify(adv_data)))
		if addr==b'\xa0\xa0C \x13\xcd':
			ble.gap_scan(None)

ble = ubluetooth.BLE()
ble.active(True)
ble.irq(handler=bt_irq)
ble.gap_scan(0,30000,30000)
time.sleep(2)

# type:
# 0 addr:b'a0a0432013cd' rssi:-58 data:b'0201061aff Ibeacon:4c00021 Noidea:5 UUID:12345678 abcd 1234 5678 abcd12345678 Major:0014 Minor:2711 RSSI:32'
So in short, my question is: How do I implement a continuous scan which only ends once a certain criteria is met.

Thank you.

Eckaard
Posts: 2
Joined: Fri May 15, 2020 6:45 am

Re: BLE Broadcasts vs Scans

Post by Eckaard » Fri May 15, 2020 12:23 pm

Replying to my own question.

This seems to work:

Code: Select all

import time
import ubluetooth
import ubinascii
from micropython import const

_IRQ_SCAN_RESULT                     = const(1 << 4)
_IRQ_SCAN_COMPLETE                   = const(1 << 5)
mac=None
def bt_irq(event, data):
	global mac
	if event == _IRQ_SCAN_RESULT:
		addr_type, addr, adv_type, rssi, adv_data = data
		if addr==b'\xa0\xa0C \x13\xcd':
			mac=addr
			print('type:{} addr:{} rssi:{} data:{}'.format(addr_type, ubinascii.hexlify(addr), rssi,
			                                               ubinascii.hexlify(adv_data)))
	elif event == _IRQ_SCAN_COMPLETE:
		print("complete")

ble = ubluetooth.BLE()
ble.active(True)
ble.irq(handler=bt_irq)
ble.gap_scan(0,30000,30000)
while mac is None:
	time.sleep_ms(1000)
I would, however, like to know what the gap_scan and sleep_ms parameters should be to best detect a beacon transmitting every 100ms for about 3 seconds. Because the current settings don't always detect the beacons even though it has been switched on.

Thanks in advance.

Post Reply