Files
shaggy-solar/eg4battery/tmp/eg4-purge-orphans
2026-04-26 08:18:57 -04:00

84 lines
2.8 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/home/noise/.local/share/uv/tools/powermon/bin/python
"""eg4-purge-orphans — remove deprecated HA-discovery entities from MQTT.
After we drop fields from the daemon's published set (raw register_NN, the
superseded bms_version_hi/lo u16s, the noisy uptime_ds counter, etc.), the
old discovery configs remain RETAINED in the broker — so HA keeps the
orphaned entities forever.
This tool publishes an empty payload (with retain=true) to each orphaned
config topic, which tells HA "forget this entity" and clears the broker's
retained slot.
Idempotent + safe to re-run. Doesn't touch live entities (those get
re-published by the daemon every cycle).
Usage:
eg4-purge-orphans <broker> <user> <password> [--dry-run]
"""
from __future__ import annotations
import sys
import argparse
import paho.mqtt.client as mqtt
PACK_NAMES = ["lifepower4_1", "lifepower4_2", "lifepower4_3"]
# Build the topic list to purge.
DEPRECATED_KEYS: list[str] = []
for n in range(0, 136):
DEPRECATED_KEYS.append(f"register_{n:02d}") # 136 raw register entities
DEPRECATED_KEYS.append("bms_version_hi") # superseded by firmware_version
DEPRECATED_KEYS.append("bms_version_lo") # superseded by firmware_version
DEPRECATED_KEYS.append("uptime_ds") # noisy counter
PREFIX = "homeassistant/sensor"
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("host")
ap.add_argument("user")
ap.add_argument("password")
ap.add_argument("--dry-run", action="store_true",
help="print topics that would be purged, don't publish")
ap.add_argument("--port", type=int, default=1883)
args = ap.parse_args()
topics: list[str] = []
for pack in PACK_NAMES:
for key in DEPRECATED_KEYS:
topics.append(f"{PREFIX}/{pack}_{key}/config")
print(f"will purge {len(topics)} topic(s) "
f"({len(DEPRECATED_KEYS)} keys × {len(PACK_NAMES)} packs)")
if args.dry_run:
for t in topics[:5]:
print(f" (dry-run) {t}")
print(f" ... and {len(topics) - 5} more")
return 0
# Use legacy constructor — works on both paho-mqtt 1.x and 2.x
try:
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="eg4-purge")
except AttributeError:
c = mqtt.Client(client_id="eg4-purge")
c.username_pw_set(args.user, args.password)
c.connect(args.host, args.port, keepalive=30)
c.loop_start()
try:
for i, t in enumerate(topics):
info = c.publish(t, payload="", qos=0, retain=True)
info.wait_for_publish(2)
if (i + 1) % 50 == 0:
print(f" ...{i + 1}/{len(topics)}")
print(f"done — {len(topics)} retained configs cleared")
finally:
c.loop_stop()
c.disconnect()
return 0
if __name__ == "__main__":
sys.exit(main())