Wrap bluetooth.connect in a per-device locked section.

This commit is contained in:
Fabio Manganiello 2023-02-19 23:11:19 +01:00
parent 9112239ac3
commit 73bf2446bd
Signed by: blacklight
GPG key ID: D90FBA7F76362774

View file

@ -1,5 +1,5 @@
import base64 import base64
from asyncio import Event, ensure_future from asyncio import Event, Lock, ensure_future
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from threading import RLock, Timer from threading import RLock, Timer
from time import time from time import time
@ -127,6 +127,7 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager):
self._scan_enabled = Event() self._scan_enabled = Event()
self._scan_controller_timer: Optional[Timer] = None self._scan_controller_timer: Optional[Timer] = None
self._connections: Dict[str, BleakClient] = {} self._connections: Dict[str, BleakClient] = {}
self._connection_locks: Dict[str, Lock] = {}
self._devices: Dict[str, BLEDevice] = {} self._devices: Dict[str, BLEDevice] = {}
self._device_last_updated_at: Dict[str, float] = {} self._device_last_updated_at: Dict[str, float] = {}
self._device_name_by_addr = device_names or {} self._device_name_by_addr = device_names or {}
@ -255,7 +256,6 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager):
or old_props.get('TxPower') != new_props.get('TxPower') or old_props.get('TxPower') != new_props.get('TxPower')
): ):
event_types.append(BluetoothDeviceSignalUpdateEvent) event_types.append(BluetoothDeviceSignalUpdateEvent)
else: else:
event_types.append(BluetoothDeviceFoundEvent) event_types.append(BluetoothDeviceFoundEvent)
@ -278,6 +278,10 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager):
timeout: Optional[float] = None, timeout: Optional[float] = None,
) -> AsyncGenerator[BleakClient, None]: ) -> AsyncGenerator[BleakClient, None]:
dev = await self._get_device(device) dev = await self._get_device(device)
async with self._connection_locks.get(dev.address, Lock()) as lock:
self._connection_locks[dev.address] = lock or Lock()
async with BleakClient( async with BleakClient(
dev.address, dev.address,
adapter=interface or self._interface, adapter=interface or self._interface,
@ -285,7 +289,7 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager):
) as client: ) as client:
self._connections[dev.address] = client self._connections[dev.address] = client
yield client yield client
self._connections.pop(dev.address) self._connections.pop(dev.address, None)
async def _read( async def _read(
self, self,