Fix dirty client state after failed BLE connection

Previously a failed connect() / start_notify() left self._client pointing
at a broken BleakClient. On the next poll is_connected returned False but
the stale object caused confusing errors. Now the client is only assigned
after both steps succeed; on any exception we try a clean disconnect and
reset to None so the next attempt starts completely fresh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-11 20:02:31 +02:00
parent 03b63c476a
commit af608792da
@@ -52,14 +52,25 @@ class BmsBluetoothHandler:
if self.is_connected: if self.is_connected:
return return
_LOGGER.debug("Connecting to BMS at %s (via %s)", self._address, ble_device.name) _LOGGER.debug("Connecting to BMS at %s (via %s)", self._address, ble_device.name)
self._client = BleakClient( client = BleakClient(
ble_device, ble_device,
disconnected_callback=self._on_disconnect, disconnected_callback=self._on_disconnect,
) )
await self._client.connect() try:
await self._client.start_notify(RX_CHAR_UUID, self._on_notify) await client.connect()
await client.start_notify(RX_CHAR_UUID, self._on_notify)
except Exception:
# Ensure a failed connect never leaves a broken client behind —
# next poll will start fresh
try:
await client.disconnect()
except Exception:
pass
self._client = None
raise
# Give the BMS a moment to register the notification subscription # Give the BMS a moment to register the notification subscription
# before we start sending commands — avoids dropped first response # before we start sending commands — avoids dropped first response
self._client = client
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
_LOGGER.debug("Connected to BMS at %s", self._address) _LOGGER.debug("Connected to BMS at %s", self._address)