Skip to content

Commit 105c1df

Browse files
committed
Merge branch 'main' into 509-eg4-ll-server-rack-battery
2 parents a6c96c9 + f096eb6 commit 105c1df

File tree

17 files changed

+308
-169
lines changed

17 files changed

+308
-169
lines changed

.github/workflows/stale.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ jobs:
1212
steps:
1313
- uses: actions/stale@v9
1414
with:
15-
stale-issue-message: 'This issue is stale because it has been open 32 days with no activity. Remove stale label or comment or this will be closed in 8 days.'
16-
stale-pr-message: 'This PR is stale because it has been open 32 days with no activity.'
15+
stale-issue-message: 'This issue is stale because it has been open 24 days with no activity. Remove stale label or comment or this will be closed in 8 days.'
16+
stale-pr-message: 'This PR is stale because it has been open 24 days with no activity.'
1717
close-issue-message: 'This issue was closed because it has been stalled for 8 days with no activity.'
1818
exempt-issue-labels: 'bug'
1919
exempt-all-assignees: true
20-
days-before-stale: 32
20+
days-before-stale: 24
2121
days-before-close: 8
2222
days-before-pr-close: -1

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ This integration allows to monitor Bluetooth Low Energy (BLE) battery management
2626
## Features
2727
- Zero configuration
2828
- Auto detects compatible batteries
29-
- Supports [ESPHome Bluetooth proxy][btproxy-url] (limit: 3 devices/proxy)
29+
- Supports [ESPHome Bluetooth proxy][btproxy-url]
3030
- Any number of batteries in parallel
3131
- Native Home Assistant integration (works with all [HA installation methods](https://www.home-assistant.io/installation/#advanced-installation-methods))
3232
- Readout of individual cell voltages to be able to judge battery health
@@ -50,6 +50,7 @@ This integration allows to monitor Bluetooth Low Energy (BLE) battery management
5050
- Ective, Startcraft, Topband batteries (show up as `$PFLAC`…, `NWJ20`…, `ZM20`…)
5151
- EG4 BMS
5252
- Felicity ESS (show up as `F10`…) and FLB batteries (show up as `F07`…)
53+
- Gobel Power BMS (show up as `BMS-`…)
5354
- HumsiENK Smart BMS (show up as `HS`…)
5455
- JBD BMS, Jiabaida, Xiaoxiang (show up as `JBD-`…)
5556
- accurat batteries, Aolithium batteries
@@ -59,6 +60,7 @@ This integration allows to monitor Bluetooth Low Energy (BLE) battery management
5960
- JK BMS, Jikong, (HW version ≥ 6 required)
6061
- LiTime, Power Queen, and Redodo batteries
6162
- LiPower BMS
63+
- Ective batteries
6264
- NEEY balancer (4th gen) (show up as `GW-24S`…)
6365
- Offgridtec LiFePo4 Smart Pro: type A & B (show up as `SmartBat-A`… or `SmartBat-B`…)
6466
- PaceEX BMS (show up as `PC-`…)
@@ -73,6 +75,8 @@ This integration allows to monitor Bluetooth Low Energy (BLE) battery management
7375
- Super-B Epsilon BMS (show up as `Epsilon-`…)
7476
- TDT BMS
7577
- Wattcycle batteries
78+
- Topband BMS
79+
- Ective, Startcraft, KiloVault batteries
7680
- TianPower BMS (show up as `TP_`…)
7781
- Vatrer BMS (show up as `YYMMDDVVVAAAAxx` (date, V, Ah))
7882
- Wattstunde Nova Core
@@ -162,15 +166,16 @@ These batteries need a shorter interval between queries. Be a bit patient to get
162166
The internal Bluetooth adapter issues <code>AT</code> commands in regular intervals which can interfere with BMS messages causing them to be corrupted. This impacts data availability (<code>link quality</code>).
163167
</details>
164168

165-
### If your device is not recognized
169+
### If your device is not recognized / initialized
166170

167171
1. Check that your BMS type is listed as [supported device](#supported-devices)
168172
1. If a name detection pattern is listed ("show up as"), make sure your device matches it.
169173
1. Check the [known issues](#known-issues) for an entry for your BMS.
170174
1. Make sure that no other device is connected to the BMS, e.g. app on your phone
171175
1. Check that your are running the [latest release](https://github.com//patman15/BMS_BLE-HA/releases) of the integration
172176
1. Go to the [advertisement monitor](https://my.home-assistant.io/redirect/bluetooth_advertisement_monitor/) and verify that your device shows up there. Also, please ensure that your `RSSI` value is `>= -75 dBm`. If your device is missing or the `RSSI` value is `-80 dBm`or worse, please check your BT setup (is the device in range?).
173-
1. If you use a BT proxy, make sure you have set `active: true` and that you do not exceed the [BT proxy limit][btproxy-url] of 3 devices/proxy; check the logs of the proxy if the device is recognized. Note: The [Bluetooth proxy of Shelly devices](https://www.home-assistant.io/integrations/shelly/#bluetooth-support) does not support active connections and thus cannot be used.
177+
1. If you use a BT proxy, make sure you have set `active: true`; check the logs of the proxy if the device is recognized. Note: The [Bluetooth proxy of Shelly devices](https://www.home-assistant.io/integrations/shelly/#bluetooth-support) does not support active connections and thus cannot be used.
178+
1. Check that you do not exceed the number of connections of your adapter, see **[Settings](https://my.home-assistant.io/redirect/config/) > Bluetooth**
174179
1. If above points did not help, please go to the [Bluetooth integration](https://my.home-assistant.io/redirect/integration/?domain=bluetooth). On your BT adapter select `configure`.
175180
1. Verify that you have connection slots available.
176181
1. Go to the [advertisement monitor](https://my.home-assistant.io/redirect/bluetooth_advertisement_monitor/) and click the device in question. Please provide the information via **`copy to clipboard`** to [a new issue](https://github.com/patman15/BMS_BLE-HA/issues/new?assignees=&labels=question&projects=&template=feature_request.yml) giving your BMS/battery type in the title.
@@ -306,7 +311,7 @@ all [contributors of aiobmsble](https://github.com/patman15/aiobmsble?tab=readme
306311
[license-shield]: https://img.shields.io/github/license/patman15/BMS_BLE-HA?style=for-the-badge&color=orange&cacheSeconds=86400
307312
[releases-shield]: https://img.shields.io/github/release/patman15/BMS_BLE-HA.svg?style=for-the-badge&cacheSeconds=14400
308313
[releases]: https://github.com//patman15/BMS_BLE-HA/releases
309-
[effort-shield]: https://img.shields.io/badge/Effort%20spent-840_hours-gold?style=for-the-badge&cacheSeconds=86400
314+
[effort-shield]: https://img.shields.io/badge/Effort%20spent-876_hours-gold?style=for-the-badge&cacheSeconds=86400
310315
[install-shield]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=green&label=HACS&suffix=%20Installs&cacheSeconds=15600&url=https://analytics.home-assistant.io/custom_integrations.json&query=$.bms_ble.total&cacheSeconds=14400
311316
[btproxy-url]: https://esphome.io/components/bluetooth_proxy
312317
[custint-url]: https://www.home-assistant.io/common-tasks/general/#defining-a-custom-polling-interval

custom_components/bms_ble/__init__.py

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""The BLE Battery Management System integration."""
22

3+
from dataclasses import dataclass
34
from types import ModuleType
45
from typing import Final
56

@@ -14,6 +15,7 @@
1415
from homeassistant.helpers.device_registry import format_mac
1516
from homeassistant.helpers.importlib import async_import_module
1617

18+
from .config_flow import ConfigFlow
1719
from .const import DOMAIN, LOGGER
1820
from .coordinator import BTBmsCoordinator
1921

@@ -78,22 +80,33 @@ async def async_migrate_entry(
7880
hass: HomeAssistant, config_entry: BTBmsConfigEntry
7981
) -> bool:
8082
"""Migrate old entry."""
81-
_latest_version: Final[int] = 2
8283

83-
if config_entry.version > _latest_version:
84-
# This means the user has downgraded from a future version
84+
@dataclass(repr=False, eq=False, slots=True)
85+
class EntryVersion:
86+
major: int
87+
minor: int
88+
89+
if config_entry.version > ConfigFlow.VERSION:
90+
# This means the user has downgraded from a future major version (incompatible)
8591
LOGGER.debug("Cannot downgrade from version %s", config_entry.version)
8692
return False
8793

88-
LOGGER.debug("Migrating from version %s.%s", config_entry.version, config_entry.minor_version)
94+
LOGGER.debug(
95+
"Migrating from version %s.%s", config_entry.version, config_entry.minor_version
96+
)
97+
98+
bms_type: Final[str] = str(config_entry.data["type"])
99+
new_data: dict[str, str] = config_entry.data.copy()
100+
entry_version: EntryVersion = EntryVersion(
101+
config_entry.version,
102+
config_entry.minor_version,
103+
)
89104

90-
if config_entry.version == 0:
91-
bms_type: str = str(config_entry.data["type"])
92-
new: dict[str, str] = {}
105+
if entry_version.major == 0:
93106
if bms_type == "OGTBms":
94-
new = {"type": "custom_components.bms_ble.plugins.ogt_bms"}
107+
new_data["type"] = "custom_components.bms_ble.plugins.ogt_bms"
95108
elif bms_type == "DalyBms":
96-
new = {"type": "custom_components.bms_ble.plugins.daly_bms"}
109+
new_data["type"] = "custom_components.bms_ble.plugins.daly_bms"
97110
else:
98111
LOGGER.debug("Entry: %s", config_entry.data)
99112
LOGGER.error(
@@ -102,17 +115,24 @@ async def async_migrate_entry(
102115
config_entry.minor_version,
103116
)
104117
return False
105-
106-
hass.config_entries.async_update_entry(
107-
config_entry, data=new, minor_version=0, version=1
108-
)
109-
110-
if config_entry.version == 1:
111-
bms_type = str(config_entry.data["type"])
112-
new = {"type": f"aiobmsble.bms.{bms_type.rsplit('.', 1)[-1]}"}
113-
hass.config_entries.async_update_entry(
114-
config_entry, data=new, minor_version=0, version=2
115-
)
118+
entry_version = EntryVersion(1, 0)
119+
120+
if entry_version.major < 2:
121+
new_data["type"] = f"aiobmsble.bms.{new_data["type"].rsplit('.', 1)[-1]}"
122+
entry_version = EntryVersion(2, 0)
123+
124+
if config_entry.version < 3:
125+
# rename Ective BMS to Topband BMS
126+
if bms_type.endswith("ective_bms"):
127+
new_data["type"] = "aiobmsble.bms.topband_bms"
128+
entry_version = EntryVersion(3, 0)
129+
130+
hass.config_entries.async_update_entry(
131+
config_entry,
132+
data=new_data,
133+
minor_version=entry_version.minor,
134+
version=entry_version.major,
135+
)
116136

117137
LOGGER.debug(
118138
"Migration to version %s.%s successful",

custom_components/bms_ble/config_flow.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
2727
"""Handle a config flow for BT Battery Management System."""
2828

29-
VERSION = 2
29+
VERSION = 3
3030
MINOR_VERSION = 0
3131

3232
@dataclass
@@ -39,7 +39,7 @@ class DiscoveredDevice:
3939

4040
def model(self) -> str:
4141
"""Return BMS type in capital letters, e.g. 'DUMMY BMS'."""
42-
return self.type.rsplit(".", 1)[-1].replace("_", " ").upper()
42+
return self.type.rsplit(".", 1)[1].replace("_", " ").upper()
4343

4444
def __init__(self) -> None:
4545
"""Initialize the config flow."""

custom_components/bms_ble/coordinator.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
class BTBmsCoordinator(DataUpdateCoordinator[BMSSample]):
2525
"""Update coordinator for a battery management system."""
2626

27+
_LOW_RSSI: Final = -75 # dBm considered low signal strength
28+
2729
def __init__(
2830
self,
2931
hass: HomeAssistant,
@@ -74,10 +76,10 @@ def rssi(self) -> int | None:
7476
return service_info.rssi if service_info else None
7577

7678
def _rssi_msg(self) -> str:
77-
"""Return check RSSI message if below -75dBm."""
79+
"""Return check RSSI message if below _LOW_RSSI dBm."""
7880
return (
7981
f", check signal strength ({self.rssi} dBm)"
80-
if self.rssi and self.rssi < -75
82+
if self.rssi and self.rssi < self._LOW_RSSI
8183
else ""
8284
)
8385

@@ -142,7 +144,9 @@ async def _async_update_data(self) -> BMSSample:
142144
LOGGER.debug(
143145
"%s: BMS communication timed out%s", self.name, self._rssi_msg()
144146
)
145-
raise TimeoutError("BMS communication timed out") from err
147+
raise UpdateFailed(
148+
translation_domain=DOMAIN, translation_key=("bms_timeout")
149+
) from err
146150
except (BleakError, EOFError) as err:
147151
LOGGER.debug(
148152
"%s: BMS communication failed%s: %s (%s)",
@@ -152,7 +156,11 @@ async def _async_update_data(self) -> BMSSample:
152156
type(err).__name__,
153157
)
154158
raise UpdateFailed(
155-
f"BMS communication failed{self._rssi_msg()}: {err!s} ({type(err).__name__})"
159+
translation_domain=DOMAIN,
160+
translation_key=("bms_com_fail"),
161+
translation_placeholders={
162+
"err_msg": f"{err!s} ({type(err).__name__})",
163+
},
156164
) from err
157165
finally:
158166
self._link_q.extend(

custom_components/bms_ble/manifest.json

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,98 +3,98 @@
33
"name": "BLE Battery Management System",
44
"bluetooth": [
55
{
6-
"service_uuid": "00001000-0000-1000-8000-00805f9b34fb"
6+
"local_name": "BMS-*"
77
},
88
{
9-
"service_uuid": "0000af30-0000-1000-8000-00805f9b34fb"
9+
"local_name": "DXB-*"
1010
},
1111
{
12-
"service_uuid": "0000fee7-0000-1000-8000-00805f9b34fb"
12+
"local_name": "ECO-WORTHY 02_*"
1313
},
1414
{
15-
"service_uuid": "0000ff00-0000-1000-8000-00805f9b34fb"
15+
"local_name": "Epsilon-*"
1616
},
1717
{
18-
"service_uuid": "0000ffd0-0000-1000-8000-00805f9b34fb"
18+
"local_name": "F07*"
1919
},
2020
{
21-
"service_uuid": "0000ffe0-0000-1000-8000-00805f9b34fb"
21+
"local_name": "F10*"
2222
},
2323
{
24-
"service_uuid": "0000ffe5-0000-1000-8000-00805f9b34fb"
24+
"local_name": "L-12V???AH-*"
2525
},
2626
{
27-
"service_uuid": "0000fff0-0000-1000-8000-00805f9b34fb"
27+
"local_name": "LT-*"
2828
},
2929
{
30-
"service_uuid": "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
30+
"local_name": "PC-????"
3131
},
3232
{
33-
"manufacturer_id": 770
33+
"local_name": "TBA-*"
3434
},
3535
{
36-
"manufacturer_id": 771
36+
"local_name": "TP_*"
3737
},
3838
{
39-
"manufacturer_id": 258
39+
"local_name": "V-12V???Ah-*"
4040
},
4141
{
42-
"manufacturer_id": 260
42+
"local_name": "libatt*",
43+
"manufacturer_id": 21320
4344
},
4445
{
45-
"manufacturer_id": 1026
46+
"local_name": "RNG*",
47+
"manufacturer_id": 57676
4648
},
4749
{
48-
"local_name": "ECO-WORTHY 02_*"
50+
"local_name": "SV12V*",
51+
"manufacturer_id": 33384
4952
},
5053
{
51-
"local_name": "TBA-*"
54+
"manufacturer_id": 258
5255
},
5356
{
54-
"local_name": "DXB-*"
57+
"manufacturer_id": 260
5558
},
5659
{
57-
"local_name": "libatt*",
58-
"manufacturer_id": 21320
60+
"manufacturer_id": 770
5961
},
6062
{
61-
"local_name": "LT-*"
63+
"manufacturer_id": 771
6264
},
6365
{
64-
"local_name": "SV12V*",
65-
"manufacturer_id": 33384
66+
"manufacturer_id": 1026
6667
},
6768
{
68-
"local_name": "L-12V???AH-*"
69+
"manufacturer_id": 54976
6970
},
7071
{
71-
"local_name": "V-12V???Ah-*"
72+
"manufacturer_id": 21330,
73+
"service_uuid": "000003c1-0000-1000-8000-00805f9b34fb"
7274
},
7375
{
74-
"manufacturer_id": 54976
76+
"service_uuid": "0000af30-0000-1000-8000-00805f9b34fb"
7577
},
7678
{
77-
"local_name": "F10*"
79+
"service_uuid": "0000fee7-0000-1000-8000-00805f9b34fb"
7880
},
7981
{
80-
"local_name": "F07*"
82+
"service_uuid": "0000ff00-0000-1000-8000-00805f9b34fb"
8183
},
8284
{
83-
"manufacturer_id": 21330,
84-
"service_uuid": "000003c1-0000-1000-8000-00805f9b34fb"
85+
"service_uuid": "0000ffd0-0000-1000-8000-00805f9b34fb"
8586
},
8687
{
87-
"local_name": "RNG*",
88-
"manufacturer_id": 57676
88+
"service_uuid": "0000ffe0-0000-1000-8000-00805f9b34fb"
8989
},
9090
{
91-
"local_name": "TP_*"
91+
"service_uuid": "0000ffe5-0000-1000-8000-00805f9b34fb"
9292
},
9393
{
94-
"local_name": "Epsilon-*"
94+
"service_uuid": "0000fff0-0000-1000-8000-00805f9b34fb"
9595
},
9696
{
97-
"local_name": "PC-????"
97+
"service_uuid": "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
9898
}
9999
],
100100
"codeowners": ["@patman15"],
@@ -107,5 +107,5 @@
107107
"loggers": ["bleak_retry_connector", "aiobmsble"],
108108
"quality_scale": "silver",
109109
"requirements": ["aiobmsble@git+https://github.com/patman15/aiobmsble.git@48-eg4-bms-support"],
110-
"version": "2.6.0-beta.1"
110+
"version": "2.7.0"
111111
}

custom_components/bms_ble/strings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@
6161
}
6262
},
6363
"exceptions": {
64+
"bms_com_fail": {
65+
"message": "BMS communication failed: {err_msg}"
66+
},
67+
"bms_timeout": {
68+
"message": "BMS communication timed out."
69+
},
6470
"device_not_found": {
6571
"message": "Could not find BMS ({MAC}) via Bluetooth."
6672
},

0 commit comments

Comments
 (0)