updates to evse
This commit is contained in:
@@ -292,19 +292,18 @@ def decode_modbus_response(frame: ModbusFrame) -> dict[str, Any]:
|
||||
# live probing of a single pack. See ../NOTES.md "Register map" section.
|
||||
# High-confidence fields promoted to named entities; unknowns (reg 32, 35,
|
||||
# 38-40, 43-45) still emitted as register_NN for correlation.
|
||||
|
||||
_WARNING_BITS = [
|
||||
"pack_ov", "cell_ov", "pack_uv", "cell_uv",
|
||||
"charge_oc", "discharge_oc", "temp_anomaly", "mos_ot",
|
||||
"charge_ot", "discharge_ot", "charge_ut", "discharge_ut",
|
||||
"low_capacity", "other_error",
|
||||
]
|
||||
_PROTECTION_BITS = [
|
||||
"pack_ov", "cell_ov", "pack_uv", "cell_uv",
|
||||
"charge_oc", "discharge_oc", "temp_anomaly", "mos_ot",
|
||||
"charge_ot", "discharge_ot", "charge_ut", "discharge_ut",
|
||||
"float_stopped", "discharge_sc",
|
||||
]
|
||||
#
|
||||
# regs 33 and 34 USED to decode as warning_* / protection_* bitfields here,
|
||||
# per the lv_host.app UI display order. That mapping was wrong: live probe
|
||||
# (2026-05-09, all 3 packs) showed reg33 == reg34 always, with both halves
|
||||
# of each register equal to the byte value of reg20 (temperature_03):
|
||||
# pack 1/2 temp_03 = 19 (0x13) → reg33 = reg34 = 0x1313
|
||||
# pack 3 temp_03 = 18 (0x12) → reg33 = reg34 = 0x1212
|
||||
# i.e. the "alarms that flipped between packs" were just a 1 °C ambient
|
||||
# difference, decoded as if the temperature byte were a 14-bit alarm mask.
|
||||
# The real alarm word is reg35 (error_code), already exposed and = 0 on
|
||||
# healthy packs. Don't re-add reg33/34 as alarms without first confirming
|
||||
# they break out of the temp-mirror pattern under a real fault condition.
|
||||
|
||||
|
||||
def _signed16(v: int) -> int:
|
||||
@@ -357,13 +356,10 @@ def decode_eg4_modbus_regs(regs: list[int], expose_raw: bool = False) -> dict[st
|
||||
# --- max charge/discharge current limit (reg 31), A ---
|
||||
out["max_current_limit"] = round(regs[31] / 100.0, 2)
|
||||
|
||||
# --- bitfields: warnings (reg 33), protections (reg 34), error code (reg 35) ---
|
||||
warn = regs[33]
|
||||
for i, name in enumerate(_WARNING_BITS):
|
||||
out[f"warning_{name}"] = "on" if (warn >> i) & 1 else "off"
|
||||
prot = regs[34]
|
||||
for i, name in enumerate(_PROTECTION_BITS):
|
||||
out[f"protection_{name}"] = "on" if (prot >> i) & 1 else "off"
|
||||
# --- error / alarm word (reg 35) ---
|
||||
# reg 33/34 used to decode as warning_/protection_ bitfields but were
|
||||
# actually mirroring a temperature byte — see the file-header comment.
|
||||
# reg 35 is the canonical alarm word; 0 on healthy packs.
|
||||
out["error_code"] = regs[35]
|
||||
|
||||
# --- static-ish (regs 36, 37) ---
|
||||
@@ -706,12 +702,6 @@ _FIELD_META.update({
|
||||
"firmware_version": (None, None, None, "mdi:chip"),
|
||||
"firmware_date": (None, None, None, "mdi:calendar"),
|
||||
})
|
||||
for _name in _WARNING_BITS:
|
||||
_FIELD_META[f"warning_{_name}"] = (None, None, None, "mdi:alert")
|
||||
for _name in _PROTECTION_BITS:
|
||||
_FIELD_META[f"protection_{_name}"] = (None, None, None, "mdi:shield-alert")
|
||||
|
||||
|
||||
def field_meta(key: str) -> tuple[str | None, str | None, str | None, str | None]:
|
||||
if key.startswith("register_"):
|
||||
return (None, None, "measurement", "mdi:numeric")
|
||||
|
||||
Reference in New Issue
Block a user