_ensure_connected() doesn't seem to work.
Opened this issue · 3 comments
If I run:
ble_device = await BleakScanner.find_device_by_address(MAC, timeout=20)
device = Switchbot(ble_device)
device.turn_on()
Then after 60 seconds if I try to run
device.turn_off()
It says:
bleak_retry_connector.BleakNotFoundError: D0-A7-8B-16-46-4E (D0:A7:8B:16:46:4E) - /org/bluez/hci1/dev_D0_A7_8B_16_46_4E: Failed to connect: Device with address D0:A7:8B:16:46:4E was not found. It may have been removed from BlueZ when scanning stopped.
You need to keep the scanner running and pass in new BLE Device objects to the lib via bleak's advertisement callbacks otherwise bluez will remove the object from the bus
Thank you for explaining this! Do you have an example of how this would be / has been implemented? Thanks!
@d-walsh I have this working in a (not yet open-source) application of myself.
You need to initialize the bot & scanner like this (taken from my codebase):
class MyBot:
def __init__(mac, password)
self.mac = mac
self.password = password
async def press(self):
return await self._try_command(lambda: self.bot.press())
async def _init(self):
if self.bot: return True
self.scanner = BleakScanner(self._detection_callback)
device = await self.scanner.find_device_by_address(self.mac)
if not device:
logger.error("Could not find device")
return False
self.bot = Switchbot(device=device, password=self.password)
await self.scanner.start()
def _detection_callback(device, adv_data):
if device.address == self.mac:
result = parse_advertisement_data(device, adv_data, SwitchbotModel.BOT)
self.bot.update_from_advertisement(result)
async def _try_command(self, block):
if not await self._init(): return
try:
return await block()
except (BleakNotFoundError, BleakDeviceNotFoundError):
await self.scanner.start()
await asyncio.sleep(5)
return await block()
This makes sure the advertisement data is continously updated. If you have multiple devices, you need to refactor this so you are only using a single BleakScanner
instance in your app.