From d896fc908b36c65fddb44da1fcab0ec63d4f0241 Mon Sep 17 00:00:00 2001 From: Andreas Wrede Date: Sun, 27 Sep 2026 11:57:06 -0400 Subject: [PATCH] li3-ha: apply the same status-gate + current-scale fixes to the HA integration parser.py is a verbatim port of li3/van-li3-battery and still had the old "000000" string gate and raw int(parts[7]) current. Apply the identical fixes (72487cf) so the native integration and the MQTT bridge agree: - status gate and decode_status share one parsed-int helper (0 == OK in any representation; unparseable = unreliable) - main-pack current parsed at its real 0.1 A scale The 72487c MQTT/systemd/discovery/expire_after hardening intentionally does not appear here: parser.py is protocol-only, and coordinator.py already uses bleak_retry_connector + HA bluetooth discovery + native sensor availability in place of those standalone concerns. --- ha/custom_components/li3_battery/parser.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/ha/custom_components/li3_battery/parser.py b/ha/custom_components/li3_battery/parser.py index 3510928..2ae8005 100644 --- a/ha/custom_components/li3_battery/parser.py +++ b/ha/custom_components/li3_battery/parser.py @@ -31,10 +31,19 @@ STATUS_FLAGS = [ ] -def decode_status(hex_code): +def status_value(status): + """Parse the raw hex status field to an int; None if unparseable. + Single source of truth for both the "is this OK" gate and the flag + decode, so the two can't disagree on e.g. "0" vs "000000".""" try: - value = int(hex_code, 16) + return int(status, 16) except (ValueError, TypeError): + return None + + +def decode_status(hex_code): + value = status_value(hex_code) + if value is None: return hex_code active = [ label for i, label in enumerate(STATUS_FLAGS) @@ -61,7 +70,7 @@ def parse_line(line): "cell4": round(int(parts[4]) * 0.01, 2), "bms_temp_f": int(parts[5]), "batt_temp_f": int(parts[6]), - "current_a": int(parts[7]), + "current_a": round(int(parts[7]) * 0.1, 1), # reported in 0.1A units "soc_pct": int(parts[8]), "status": parts[9] if len(parts) > 9 else "?", } @@ -113,7 +122,11 @@ def build_state_payload(cs_reading, trace_fields): # ("&" line) fields come from a separate message and are published # regardless. status = cs_reading["status"] - if status != "000000": + # "OK" == integer zero in ANY representation. Gate on the parsed int (not + # the raw string) so "0"/"0000"/"000000" all agree with decode_status, and + # an unparseable status (e.g. "?") is treated as unreliable and suppressed. + value = status_value(status) + if value is None or value != 0: payload = {"status": status} else: payload = {