From f7422c9d74c4c5df30fde3b7ce12c69a8ef5c280 Mon Sep 17 00:00:00 2001 From: Mortdecai Date: Fri, 23 Oct 2026 00:28:00 -0400 Subject: [PATCH] fix: survive command exceptions; TV DHCP-reserved so pairing key stays valid Co-Authored-By: Claude Opus 5.5 (1M context) --- DECISIONS.md | 2 ++ lgtv_mqtt.py | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/DECISIONS.md b/DECISIONS.md index e3bc2fa..b5171bb 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -49,6 +49,8 @@ Format: `YYYY-MM-DD: — ` - 2026-10-22: HA VM 706 pinned to 192.168.0.146 twice over — Omada DHCP reservation (MAC BC:24:11:3F:DC:7B) AND HAOS static IPv4 (`ha network update enp0s18 --ipv4-method static`) — HA had silently lost its IPv4 lease (~Aug 2026; IPv6-only, uptime 57d), cutting it off from MQTT/Caddy/Google: the "TV hasn't worked in months" outage. Static removes the DHCP dependency; reservation keeps the router from handing .146 to anyone else. +- 2026-10-23: TV DHCP-reserved at 192.168.0.20 (Omada) — bscpylgtv keys pairings by IP, so every DHCP drift (7 IPs so far) re-triggered the on-TV auth prompt, and a missed prompt hung `off` past the 60s timeout. New IP seeded with the newest stored key (.31) so no re-prompt. Also: on_message now catches all exceptions — one escaping killed paho's thread while the poll loop kept the process alive (silent zombie). + ## Deferred / Rejected - **DHCP reservation for the TV (static IP):** not done — Pi-hole doesn't run DHCP (router does), so it's Seth's action on the router. The cached-IP probe diff --git a/lgtv_mqtt.py b/lgtv_mqtt.py index 9a9d739..e57267c 100755 --- a/lgtv_mqtt.py +++ b/lgtv_mqtt.py @@ -110,6 +110,15 @@ def on_connect(client, userdata, flags, rc): def on_message(client, userdata, msg): + # An exception escaping a paho callback kills the network thread while the + # poll loop keeps the process alive — a silent zombie systemd never restarts. + try: + handle_command(client, msg) + except Exception: + log.exception("command handling failed") + + +def handle_command(client, msg): command = msg.payload.decode().strip().upper() log.info(f"Received command: {command}")