"""Devices that announced they went offline. The firmware's LWT (unclean disconnect) and its graceful-disconnect message both publish {"state": "offline", "ok": false} to status/heartbeat, retained. Online status is otherwise "a heartbeat newer than 90s", which would keep showing a device that just dropped as online for up to 90s. This remembers the marker so /mqtt/status and the ping loop treat the device as offline right away. In-memory only, which is enough: on backend start the broker replays each device's retained heartbeat, so a device whose last word was "offline" gets re-marked, and any live heartbeat clears the mark. """ _offline: set[str] = set() def mark_offline(serial: str) -> None: _offline.add(serial) def mark_alive(serial: str) -> None: _offline.discard(serial) def is_marked_offline(serial: str) -> bool: return serial in _offline