Skip to content

Commit

Permalink
winrt/client: fix TimeoutError for certain devices
Browse files Browse the repository at this point in the history
Some devices will get a TimeoutError when trying to connect because
setting `self._session.maintain_connection = True` is not enough to
trigger a connection to the device. We also have to start an interaction
with the device. This can be done by calling `self.get_services()` which
we need to do here anyway. This also make `get_services()` be included
in the timeout, which is probably a good thing.

Fixes: #604
  • Loading branch information
dlech committed Nov 7, 2022
1 parent f3a66f8 commit 986c718
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -10,6 +10,10 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
`Unreleased`_
=============

Fixed
-----
* Fixed ``TimeoutError`` when connecting to certain devices with WinRT backend. Fixes #604.

`0.19.2`_ (2022-11-06)
======================

Expand Down
26 changes: 18 additions & 8 deletions bleak/backends/winrt/client.py
Expand Up @@ -366,18 +366,30 @@ def max_pdu_size_changed_handler(sender: GattSession, args):
self._session.maintain_connection = True
# This keeps the device connected until we set maintain_connection = False.

# wait for the session to become active
async with async_timeout.timeout(timeout):
await event.wait()
wait_connect_task = asyncio.create_task(event.wait())

try:
# a connection may not be made until we request info from the
# device, so we have to get services before the GATT session
# is set to active
wait_get_services_task = asyncio.create_task(self.get_services())

try:
# wait for the session to become active
async with async_timeout(timeout):
await asyncio.gather(wait_connect_task, wait_get_services_task)

finally:
wait_get_services_task.cancel()
finally:
wait_connect_task.cancel()

except BaseException:
handle_disconnect()
raise
finally:
self._session_active_events.remove(event)

# Obtain services, which also leads to connection being established.
await self.get_services()

return True

async def disconnect(self) -> bool:
Expand Down Expand Up @@ -540,8 +552,6 @@ async def get_services(self, **kwargs) -> BleakGATTServiceCollection:
A :py:class:`bleak.backends.service.BleakGATTServiceCollection` with this device's services tree.
"""
if not self.is_connected:
raise BleakError("Not connected")

# Return the Service Collection.
if self._services_resolved:
Expand Down

0 comments on commit 986c718

Please sign in to comment.