Skip to content

Commit ac0d6bf

Browse files
authored
Merge pull request #678 from hbldh/cb-futures
CoreBluetooth callback fixes and cleanups
2 parents dea17d7 + eb7f42c commit ac0d6bf

File tree

4 files changed

+135
-107
lines changed

4 files changed

+135
-107
lines changed

CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
1010
`Unreleased`_
1111
=============
1212

13+
Fixed
14+
-----
15+
* Fixed ``InvalidStateError`` in CoreBluetooth backend when read and notification
16+
of the same characteristic are used. Fixes #675.
17+
* Fixed reading a characteristic on CoreBluetooth backend also triggers notification
18+
callback.
19+
1320

1421
`0.13.0`_ (2021-10-20)
1522
======================

bleak/backends/corebluetooth/CentralManagerDelegate.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -152,25 +152,38 @@ async def connect(
152152
try:
153153
self._disconnect_callbacks[peripheral.identifier()] = disconnect_callback
154154
future = self.event_loop.create_future()
155+
155156
self._connect_futures[peripheral.identifier()] = future
156-
self.central_manager.connectPeripheral_options_(peripheral, None)
157-
await asyncio.wait_for(future, timeout=timeout)
157+
try:
158+
self.central_manager.connectPeripheral_options_(peripheral, None)
159+
await asyncio.wait_for(future, timeout=timeout)
160+
finally:
161+
del self._connect_futures[peripheral.identifier()]
162+
158163
except asyncio.TimeoutError:
159164
logger.debug(f"Connection timed out after {timeout} seconds.")
160165
del self._disconnect_callbacks[peripheral.identifier()]
161166
future = self.event_loop.create_future()
167+
162168
self._disconnect_futures[peripheral.identifier()] = future
163-
self.central_manager.cancelPeripheralConnection_(peripheral)
164-
await future
169+
try:
170+
self.central_manager.cancelPeripheralConnection_(peripheral)
171+
await future
172+
finally:
173+
del self._disconnect_futures[peripheral.identifier()]
174+
165175
raise
166176

167177
@objc.python_method
168178
async def disconnect(self, peripheral: CBPeripheral) -> None:
169179
future = self.event_loop.create_future()
180+
170181
self._disconnect_futures[peripheral.identifier()] = future
171-
self.central_manager.cancelPeripheralConnection_(peripheral)
172-
await future
173-
del self._disconnect_callbacks[peripheral.identifier()]
182+
try:
183+
self.central_manager.cancelPeripheralConnection_(peripheral)
184+
await future
185+
finally:
186+
del self._disconnect_callbacks[peripheral.identifier()]
174187

175188
@objc.python_method
176189
def _changed_is_scanning(self, is_scanning: bool) -> None:
@@ -280,7 +293,7 @@ def centralManager_didDiscoverPeripheral_advertisementData_RSSI_(
280293
def did_connect_peripheral(
281294
self, central: CBCentralManager, peripheral: CBPeripheral
282295
) -> None:
283-
future = self._connect_futures.pop(peripheral.identifier(), None)
296+
future = self._connect_futures.get(peripheral.identifier(), None)
284297
if future is not None:
285298
future.set_result(True)
286299

@@ -301,7 +314,7 @@ def did_fail_to_connect_peripheral(
301314
peripheral: CBPeripheral,
302315
error: Optional[NSError],
303316
) -> None:
304-
future = self._connect_futures.pop(peripheral.identifier(), None)
317+
future = self._connect_futures.get(peripheral.identifier(), None)
305318
if future is not None:
306319
if error is not None:
307320
future.set_exception(BleakError(f"failed to connect: {error}"))
@@ -331,7 +344,7 @@ def did_disconnect_peripheral(
331344
) -> None:
332345
logger.debug("Peripheral Device disconnected!")
333346

334-
future = self._disconnect_futures.pop(peripheral.identifier(), None)
347+
future = self._disconnect_futures.get(peripheral.identifier(), None)
335348
if future is not None:
336349
if error is not None:
337350
future.set_exception(BleakError(f"disconnect failed: {error}"))

0 commit comments

Comments
 (0)