-
Notifications
You must be signed in to change notification settings - Fork 334
Description
I tried this simple code to connect to a Polar H10. Using a BleakClient without passing a timeout parameter, the connection almost never succeeds it ends with a TimeoutError. However, when setting timeout=15–20, the connection becomes stable and ServicesResolved is reached successfully. The documentation mentions that setting a timeout is not recommended, but without it, the device never completes service discovery.
def on_disconnect(client: BleakClient):
"""Triggered automatically when the device disconnects."""
print("Device has been disconnected.")
async def connect_device(client: BleakClient) -> BleakClient | None:
"""Establish a BLE connection using a BleakClient instance."""
try:
# Connection only succeeds reliably on BlueZ when timeout is explicitly set
await client.connect(timeout=20)
except BluetoothConnectionError as e:
print(f"Connection error ({type(e).__name__}): {e}")
return None
if client.is_connected:
print("Device connected successfully.")
return client
print("Connection failed after connect().")
return None
async def disconnect_device(client: BleakClient):
"""Controlled disconnection."""
if client.is_connected:
try:
await client.disconnect()
print("Device disconnected successfully.")
except Exception as e:
print(f"Error while disconnecting ({type(e).__name__}): {e}")
else:
print("No active connection to disconnect.")
async def hr_monitor():
devices = await scan_devices(filter_name="polar", show=True)
if not devices:
return
polar = devices[0]
client = BleakClient(polar, disconnected_callback=on_disconnect)
print(f"Attempting to connect to {polar.name}...")
client = await connect_device(client)
if not client:
print("Could not connect to the device.")
return
try:
while True:
await aio.sleep(1)
finally:
await disconnect_device(client)
print("Disconnected by user.")
if __name__ == "__main__":
try:
aio.run(hr_monitor())
except KeyboardInterrupt:
print("\nStopped by user.")Environment:
- OS: Debian 12
- BlueZ: 5.66
- Python: 3.10
- Bleak: 1.1
- Peripheral: Polar H10 (firmware up to date)
1- Scrip Error:
Traceback (most recent call last):
File ".../bleak/backends/bluezdbus/client.py", line 355, in connect
await self._get_services(
File ".../bleak/backends/bluezdbus/client.py", line 713, in _get_services
self.services = await manager.get_services(
File ".../bleak/backends/bluezdbus/manager.py", line 687, in get_services
await self._wait_for_services_discovery(device_path)
File ".../bleak/backends/bluezdbus/manager.py", line 841, in _wait_for_services_discovery
done, _ = await asyncio.wait(...)
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ".../bleak/init.py", line 580, in connect
await self._backend.connect(self._pair_before_connect, **kwargs)
File ".../bleak/backends/bluezdbus/client.py", line 156, in connect
async with async_timeout(timeout):
File ".../async_timeout/init.py", line 265, in aexit
raise asyncio.TimeoutError
asyncio.exceptions.TimeoutError
What I checked:
- D-Bus: Connected=True arrives, but ServicesResolved=True does not arrive in the failing case.
- HCI/ATT (Wireshark): link up + MTU exchange are visible; when it fails, I don’t see the expected Read By Group Type Response (0x11) following Read By Group Type (0x10), so BlueZ appears to wait indefinitely for service discovery to finish. With timeout=20, the 0x11 responses show up and discovery completes.
Questions / ask
1- Is this a known BlueZ-backend quirk that requires an explicit timeout for some peripherals?
2- Possibly related to: #1806 (service discovery/ServicesResolved behavior)?