$ show allangood/rtlamr2mqtt
rtlamr2mqtt is a Home Assistant add-on and standalone Docker container that reads utility meters (electric, gas, water) using an RTL-SDR USB receiver and publishes readings to MQTT. The application runs rtl_tcp to interface with the SDR hardware and rtlamr to decode meter transmissions, parsing the JSON output and publishing formatted readings, HA auto-discovery payloads, and status to an MQTT broker. It supports sleep/wake cycles to conserve resources on Raspberry Pi, automatic process restart with backoff, USB device reset on timeout, and listen mode for discovering unknown meter IDs. The architecture is fully async (asyncio TaskGroup) with three independent tasks: MeterReader (rtlamr output parsing), MQTTPublisher (aiomqtt-based MQTT communication), and ManagedProcess (generic async subprocess lifecycle manager). It can run as a Home Assistant add-on (auto-discovers MQTT via Supervisor API) or standalone with a YAML config file.
The LLM identified 4 files worth highlighting for reuse:
Generic async subprocess manager that wraps asyncio.create_subprocess_exec with ready-pattern detection, configurable timeout, retry with exponential backoff, and clean shutdown (SIGTERM -> SIGKILL with process group signaling). Supports an optional on_retry callback (sync or async) for USB reset or other recovery actions. Maintains a rolling 20-line output buffer for diagnostics. Fully isolated with no internal dependencies beyond asyncio and shutil, making it reusable in any Python project that needs reliable subprocess lifecycle management.
Pure functions for constructing rtl_tcp and rtlamr command-line arguments from a config dict. Implements a clean override pattern: custom parameters from the config are parsed first, then default values (like -s 2048000 for rtl_tcp or -unique=true for rtlamr) are only added if not overridden by the user. Handles removal of conflicting flags (e.g., -server from rtlamr custom params) and produces separate tokens safe for create_subprocess_exec (no embedded spaces). The listen mode variant correctly uses -msgtype=all when no meters are configured. Reusable in any project needing modular, overridable command-line construction.
Pure functions for parsing rtlamr JSON output lines. Uses ordered key lists (METER_ID_KEYS, CONSUMPTION_KEYS) instead of set intersection, eliminating non-deterministic behavior. The get_message_for_ids function supports an empty meter_ids_list (listen mode) to accept any meter ID, with deterministic extraction of meter_id, consumption, msg_type, and remaining message fields. Includes a format_number helper for zero-padded digit formatting. No external dependencies, fully self-contained for reuse in any JSON-stream parsing context.
Config loader that handles both Home Assistant add-on mode (auto-discovers MQTT via Supervisor API with SUPERVISOR_TOKEN) and standalone Docker mode (reads YAML/JSON from known paths). Merges defaults for all sections (general, mqtt, custom_parameters) and converts the meters list to a dict keyed by string ID for O(1) lookup. Validates that meters are present unless listen_mode is enabled, and forces sleep_for to 0 in listen mode. Reusable in any project needing a robust, dual-path config loader with environment-aware fallback.