Skip to content

Commit

Permalink
Fixed reconnect on BMS initialization failure (#127)
Browse files Browse the repository at this point in the history
* fix reconnect on init failure
  • Loading branch information
patman15 authored Dec 26, 2024
1 parent ef445de commit 32775db
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 34 deletions.
2 changes: 1 addition & 1 deletion custom_components/bms_ble/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
12 changes: 10 additions & 2 deletions custom_components/bms_ble/plugins/basebms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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,
Expand Down
24 changes: 13 additions & 11 deletions custom_components/bms_ble/plugins/dpwrcore_bms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand Down
7 changes: 4 additions & 3 deletions custom_components/bms_ble/plugins/jikong_bms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
24 changes: 10 additions & 14 deletions custom_components/bms_ble/plugins/tdt_bms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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)."""
Expand Down
8 changes: 5 additions & 3 deletions tests/test_tdt_bms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 32775db

Please sign in to comment.