Here is the code I have so far that uses the bleak package to connect to multiple Bluetooth devices and get data/notifications from them. The devices are scales are they automatically shut off after awhile if there are no weights on them. Upon placing weight on them, they turn on and starts notifying. The code continuously scan for devices that are on, to log data from them. Upon shutting off, the disconnect_callback() function will be called. I have a global set called connected_devices that keeps track of the devices that are on. When a device is connected, its MAC address will be added to the set. When a device disconnect, its Mac address will be removed from the set (in the disconnect_callback() function). I have locking codes that are currently commented out in order to synchronize the adding/removal of MAC addresses from the connected_device set, but I'm not sure is necessary, since everything runs in the scan_and_connect() coroutine. import asyncio import functools from bleak import BleakClient, BleakScanner #lock = asyncio.Lock() connected_devices = set() notify_uuid = "00002A37-0000-1000-8000-00805F9B34FB" def callback(client, characteristic, data): print(client.address, characteristic, data) def disconnected_callback(client): #with lock: connected_devices.remove(client.address) print("disconnect from", device.address) def match_device(device, adv_data): #with lock: return adv_data.local_name.startswith('BLE') and device.address not in connected_devices async def scan_and_connect(): while True: device = await BleakScanner.find_device_by_filter(match_device) if device is None: continue client = BleakClient(device, disconnected_callback=disconnected_callback) try: await client.connect() print("connected to", device.address) await client.start_notify(functools.partial(callback, client)) #with lock: connected_devices.add(device.address) except BleakError: # if failed to connect, this is a no-op, if failed to start notifications, it will disconnect await client.disconnect() if __name__ == "__main__": asyncio.run(scan_and_connect()) Are the locks are necessary in this case? Continue reading...