diff --git a/custom_components/bms_ble/manifest.json b/custom_components/bms_ble/manifest.json index 009371c..a0ba42a 100644 --- a/custom_components/bms_ble/manifest.json +++ b/custom_components/bms_ble/manifest.json @@ -90,5 +90,5 @@ "issue_tracker": "https://github.com/patman15/BMS_BLE-HA/issues", "loggers": ["bleak_retry_connector"], "requirements": [], - "version": "1.11.1" + "version": "1.11.2" } diff --git a/custom_components/bms_ble/plugins/basebms.py b/custom_components/bms_ble/plugins/basebms.py index 092af43..5daf88a 100644 --- a/custom_components/bms_ble/plugins/basebms.py +++ b/custom_components/bms_ble/plugins/basebms.py @@ -191,7 +191,7 @@ def _on_disconnect(self, _client: BleakClient) -> None: self._log.debug("disconnected from BMS") - async def _init_characteristics(self) -> None: + async def _init_connection(self) -> None: await self._client.start_notify(self.uuid_rx(), self._notification_method) async def _connect(self) -> None: @@ -209,7 +209,15 @@ async def _connect(self) -> None: disconnected_callback=self._on_disconnect, services=[*self.uuid_services()], ) - await self._init_characteristics() + + try: + await self._init_connection() + except Exception as err: + self._log.info( + "failed to initialize BMS connection (%s)", type(err).__name__ + ) + await self.disconnect() + raise async def _await_reply( self, diff --git a/custom_components/bms_ble/plugins/dpwrcore_bms.py b/custom_components/bms_ble/plugins/dpwrcore_bms.py index acf713a..215a4c8 100644 --- a/custom_components/bms_ble/plugins/dpwrcore_bms.py +++ b/custom_components/bms_ble/plugins/dpwrcore_bms.py @@ -175,20 +175,22 @@ def _cmd_frame(cmd: Cmd, data: bytes) -> bytes: return frame - async def _init_characteristics(self) -> None: + async def _init_connection(self) -> None: """Connect to the BMS and setup notification if not connected.""" - await super()._init_characteristics() + await super()._init_connection() # unlock BMS if not TBA version - if not self.name.startswith("TBA-"): - pwd = int(self.name[-4:], 16) - await self._await_reply( - BMS._cmd_frame( - Cmd.UNLOCK, - bytes([(pwd >> 8) & 0xFF, pwd & 0xFF]), - ), - wait_for_notify=False, - ) + if self.name.startswith("TBA-"): + return + + pwd = int(self.name[-4:], 16) + await self._await_reply( + BMS._cmd_frame( + Cmd.UNLOCK, + bytes([(pwd >> 8) & 0xFF, pwd & 0xFF]), + ), + wait_for_notify=False, + ) @staticmethod def _cell_voltages(data: bytearray, cells: int) -> dict[str, float]: diff --git a/custom_components/bms_ble/plugins/jikong_bms.py b/custom_components/bms_ble/plugins/jikong_bms.py index 8e60cee..6dd8005 100644 --- a/custom_components/bms_ble/plugins/jikong_bms.py +++ b/custom_components/bms_ble/plugins/jikong_bms.py @@ -148,10 +148,10 @@ def _notification_handler(self, _sender, data: bytearray) -> None: self._log.debug("invalid checksum 0x%X != 0x%X", self._data[-1], crc) return - self._data_final = self._data + self._data_final = self._data.copy() self._data_event.set() - async def _init_characteristics(self) -> None: + async def _init_connection(self) -> None: """Initialize RX/TX characteristics.""" char_notify_handle: int = -1 self._char_write_handle = -1 @@ -180,7 +180,8 @@ async def _init_characteristics(self) -> None: char_notify_handle, self._char_write_handle, ) - await self._client.start_notify(char_notify_handle, self._notification_handler) + + await super()._init_connection() # query device info frame (0x03) and wait for BMS ready (0xC8) self._valid_reply = 0x03 diff --git a/custom_components/bms_ble/plugins/tdt_bms.py b/custom_components/bms_ble/plugins/tdt_bms.py index a1bcfa5..c1b1339 100644 --- a/custom_components/bms_ble/plugins/tdt_bms.py +++ b/custom_components/bms_ble/plugins/tdt_bms.py @@ -4,7 +4,6 @@ from typing import Any, Final from bleak.backends.device import BLEDevice -from bleak.exc import BleakError from bleak.uuids import normalize_uuid_str from custom_components.bms_ble.const import ( @@ -99,19 +98,16 @@ def _calc_values() -> set[str]: ATTR_TEMPERATURE, } # calculate further values from BMS provided set ones - async def _init_characteristics(self) -> None: - try: - await self._await_reply( - data=b"HiLink", char=BMS._UUID_CFG, wait_for_notify=False - ) - if ( - ret := int.from_bytes(await self._client.read_gatt_char(BMS._UUID_CFG)) - ) != 0x1: - self._log.debug("error initializing BMS: %X", ret) - except (BleakError, EOFError) as err: - self._log.debug("failed to intialize BMS: %s", err) - - await super()._init_characteristics() + async def _init_connection(self) -> None: + await self._await_reply( + data=b"HiLink", char=BMS._UUID_CFG, wait_for_notify=False + ) + if ( + ret := int.from_bytes(await self._client.read_gatt_char(BMS._UUID_CFG)) + ) != 0x1: + self._log.debug("error unlocking BMS: %X", ret) + + await super()._init_connection() def _notification_handler(self, _sender, data: bytearray) -> None: """Handle the RX characteristics notify event (new data arrives).""" diff --git a/tests/test_tdt_bms.py b/tests/test_tdt_bms.py index 0cfbbde..2f345bb 100644 --- a/tests/test_tdt_bms.py +++ b/tests/test_tdt_bms.py @@ -302,8 +302,10 @@ async def throw_response(*_args, **_kwargs) -> bytearray: bms = BMS(generate_ble_device("cc:cc:cc:cc:cc:cc", "MockBLEDevice", None, -73)) - result = await bms.async_update() - - assert result == ref_value()["16S6T"] + if bool_fixture: + with pytest.raises(BleakDeviceNotFoundError): + assert not await bms.async_update() + else: + assert await bms.async_update() == ref_value()["16S6T"] await bms.disconnect()