Full protocol coverage: binary sensors, energy, hardware version
Sensors added: - energy_stored (kWh = V × Ah / 1000) for energy dashboard Binary sensors added (all from existing 0x03 frame, no extra BLE requests): - Charge MOSFET / Discharge MOSFET (MOS gate status) - Cell Balancing (any balance bit active) - 13× protection flags: cell/pack over/under-voltage, charge/discharge over/under-temperature, charge/discharge over-current, short circuit, frontend IC error, software lock Other: - Hardware version string fetched once via CMD 0x05, shown in device card - DeviceInfo centralised on coordinator (sensor + binary_sensor share it) - CONF_ADDRESS removed from sensor.py (coordinator holds address) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -172,6 +172,10 @@ class BmsBluetoothHandler:
|
||||
raw = struct.unpack_from(">H", p, 23 + i * 2)[0]
|
||||
temperatures.append(round((raw - 2731) / 10.0, 1))
|
||||
|
||||
balance = struct.unpack_from(">H", p, 12)[0] | struct.unpack_from(">H", p, 14)[0]
|
||||
prot = struct.unpack_from(">H", p, 16)[0]
|
||||
mos = p[20]
|
||||
|
||||
return {
|
||||
"voltage": round(struct.unpack_from(">H", p, 0)[0] / 100.0, 2),
|
||||
"current": round(struct.unpack_from(">h", p, 2)[0] / 100.0, 2),
|
||||
@@ -181,8 +185,33 @@ class BmsBluetoothHandler:
|
||||
"state_of_charge": p[19],
|
||||
"cell_count": p[21],
|
||||
"temperatures": temperatures,
|
||||
# MOS status
|
||||
"mos_charge_enabled": bool(mos & 0x01),
|
||||
"mos_discharge_enabled": bool(mos & 0x02),
|
||||
# Cell balancing (any cell currently balancing)
|
||||
"balance_active": balance != 0,
|
||||
# Protection flags (bit per event, True = protection triggered)
|
||||
"prot_cell_overvolt": bool(prot & (1 << 0)),
|
||||
"prot_cell_undervolt": bool(prot & (1 << 1)),
|
||||
"prot_pack_overvolt": bool(prot & (1 << 2)),
|
||||
"prot_pack_undervolt": bool(prot & (1 << 3)),
|
||||
"prot_charge_overtemp": bool(prot & (1 << 4)),
|
||||
"prot_charge_undertemp": bool(prot & (1 << 5)),
|
||||
"prot_discharge_overtemp": bool(prot & (1 << 6)),
|
||||
"prot_discharge_undertemp": bool(prot & (1 << 7)),
|
||||
"prot_charge_overcurrent": bool(prot & (1 << 8)),
|
||||
"prot_discharge_overcurrent": bool(prot & (1 << 9)),
|
||||
"prot_short_circuit": bool(prot & (1 << 10)),
|
||||
"prot_frontend_ic_error": bool(prot & (1 << 11)),
|
||||
"prot_software_lock": bool(prot & (1 << 12)),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def parse_version(frame: bytes) -> str:
|
||||
"""Parse a 0x05 hardware version response frame into an ASCII string."""
|
||||
p = frame[_HEADER_LEN:-_TRAILER_LEN]
|
||||
return p.decode("ascii", errors="replace").strip("\x00").strip()
|
||||
|
||||
@staticmethod
|
||||
def parse_cell_info(frame: bytes) -> dict:
|
||||
"""Parse a 0x04 cell voltage response frame.
|
||||
|
||||
Reference in New Issue
Block a user