Have really been struggling with multiple connections to multiple devices and being able to asynchronously read the data from each beacon and return that data to other code for further processing.
Dealing with a single connection and a single read is pretty simple, but when you have multiple devices to read (with multiple open connections) and need to read multiple values from each device asynchronously it becomes very messy when using a global interrupt.
I guess that everyone will say that uasyncio is probably the way, but having to deal with a single interrupt for all connections is still going to need some workarounds !
And I don't really need for my code to do anything else while waiting for this data, as the data is crucial to the next step !
What is the recommended approach for this ??
Reading Multiple Bluetooth Beacons
Re: Reading Multiple Bluetooth Beacons
So your beacons need you to connect to them? They're not just using advertising data?
I think the answer to this is fairly application specific, but the basic idea is that you'd make a Beacon class to track each beacon and route the irq method to the right instance based on address / conn_handle.
Here's a rough sketch of what that might look like?
I think the answer to this is fairly application specific, but the basic idea is that you'd make a Beacon class to track each beacon and route the irq method to the right instance based on address / conn_handle.
Here's a rough sketch of what that might look like?
Code: Select all
class Peripheral:
def __init__(self, central, addr_type, addr):
self._central = central
self._addr_type = addr_type
self._addr = addr
self._conn_handle = None
self._central._connecting_peripherals[(addr_type, addr)] = self
self._central._ble.connect(addr_type, addr)
def connected(self):
pass
def irq(self, event, data):
pass
class Central:
def __init__(self, ble):
self._connecting_peripherals = {}
self._connected_peripherals = {}
self._ble = ble
self._ble.irq(handler=self.irq, trigger=0xffff)
def irq(self, event, data):
if event == _IRQ_SCAN_RESULT:
addr_type, addr, connectable, rssi, adv_data = data
# e.g. create a Peripheral(self, addr_type, addr)
elif event == _IRQ_SCAN_COMPLETE:
pass
elif event == _IRQ_PERIPHERAL_CONNECT:
conn_handle, addr_type, addr = data
key = (addr_type, addr,)
if key in self._connecting_peripherals:
p = self._connecting_peripherals[key]
p._conn_handle = conn_handle
p.connected()
del self._connecting_peripherals[key]
self._connected_peripherals[conn_handle] = p
else if data[0] in self._connected_peripherals:
# All other events, data[0] is conn_handle.
self._connected_peripherals[data[0]].irq(event, data)
Re: Reading Multiple Bluetooth Beacons
Thanks Jimmo;
That works really well, I have expanded on it and fixed a couple of typos but it pretty much works out of the box.
But how can I disconnect a peripheral and destroy it's class instance, or allow disconnect & reconnect of an instance ?
I have added these into the peripheral class, disconnect works but I can never reconnect again.
That works really well, I have expanded on it and fixed a couple of typos but it pretty much works out of the box.
But how can I disconnect a peripheral and destroy it's class instance, or allow disconnect & reconnect of an instance ?
Code: Select all
def connect(self):
self._central._connecting_peripherals[(self._addr_type, self._addr)] = self
self._central._ble.gap_connect(self._addr_type, self._addr)
def disconnect(self):
self._central._ble.gap_disconnect(self._conn_handle)
Last edited by devnull on Mon Nov 04, 2019 11:19 pm, edited 1 time in total.
Re: Reading Multiple Bluetooth Beacons
After calling p.irq(), check if the event is "disconnected" and del from the connected dict.