mirror of
https://github.com/pe1hvh/meshcore-gui.git
synced 2026-10-31 01:42:04 +01:00
feat(repeater): poll repeater statistics on a configurable interval Configured repeaters are logged into, queried for their status and logged out again on a configurable interval. Raw values are archived with the moment of each poll, so battery voltage can be tracked over multiple days. New modules - services/repeater_config_store.py — per-device configuration in ~/.meshcore-gui/repeaters/<device>_repeaters.json (directory 0700, file 0600). Holds the full 32-byte public key, display name, login password, poll interval and enabled flag. A key that is not 64 hex characters is rejected: the meshcore library refuses a prefix for login, status and logout requests. An absent password means "not configured", an empty string is a valid credential. - services/repeater_stats_archive.py — append-only JSONL at ~/.meshcore-gui/archive/<device>_repeater_stats.jsonl, one record per poll, retention through the existing daily cleanup task. - services/repeater_poller.py — send_login_sync, req_status_sync, send_logout. The sync variants are used because plain send_login and send_statusreq return as soon as the frame is on the wire and say nothing about the outcome. - gui/panels/repeater_stats_panel.py — read-only REPEATERS panel showing the latest values, the age of the last successful poll and the last error per repeater. Changed - config.py: VERSION 1.23.0, REPEATERS_DIR, REPEATER_POLL_ENABLED, REPEATER_POLL_INTERVAL (900 s), REPEATER_POLL_CHECK_INTERVAL, REPEATER_LOGIN_TIMEOUT, REPEATER_STATUS_TIMEOUT, REPEATER_STATS_RETENTION_DAYS. - ble/worker.py: _main_loop runs the repeater poll alongside the existing periodic tasks, following the same interval-guarded pattern; _cleanup_old_data applies retention to the new archive. - __main__.py, gui/dashboard.py, gui/panels/__init__.py: wiring. Behaviour - At most one repeater is polled per check, each with its own start offset within the interval, so two repeaters are never queried back to back. Two repeaters on the default interval land ~7.5 minutes apart. - A failed login, an absent status response or an exception is recorded as a poll attempt with ok=false and a reason, and blocks neither the other repeater nor the application. Logout is always sent once a login has been attempted, including after a timeout — a login that returned no confirmation may still have succeeded on the far side. - Values are stored exactly as reported: no scaling, rounding or averaging. Battery voltage keeps the unit the firmware returns. - The password is reachable through a single method that only the poller calls. Objects handed to the GUI have no password field, and no password reaches the archive, the log or any error message. - Polling stays idle until a repeater is configured, so an installation without a configuration file behaves exactly as before. No change to the archive JSON schema, the public REST API or any existing public method signature. Worker and dashboard constructors gained optional keyword arguments only.