mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-07-26 19:42:43 +02:00
docs: cover the My Repeaters (repeater administration) feature
user-guide.md gains a full My Repeaters section (adding repeaters, saved passwords + the wrong-password/unreachable ambiguity, path editing, and the six management tools) and fixes the stale Quick Access placement list (now 12 items, real labels). architecture.md documents the /api/repeaters/* endpoint family with its shared error mapping, the repeaters DB table, and a DeviceManager subsection on serialization, login sessions, CLI reply correlation, settings batches and the actions whitelist. whatsnew.md adds three New features bullets, a Reliability note (console login reports role), and Deploy notes (meshcore>=2.3.7 rebuild, plaintext password trade-off). rpt-mgmt.md now points to the built-in panel first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -94,6 +94,17 @@ The `DeviceManager` handles the connection to the MeshCore device via a direct s
|
||||
- **Advert scheduler** — an observer-owned daemon thread checks every 10 minutes and sends a flood advert once `advert_interval_hours` has elapsed since the `observer_last_advert_at` timestamp persisted in `app_settings` (restart-safe)
|
||||
- **Live status** — `observer_status` events on the `/chat` namespace (throttled to one per 2 s on the packet path) drive the Settings-tab badges and counters; `GET /api/observer/status` returns the full merged view
|
||||
|
||||
### Repeater administration (My Repeaters)
|
||||
|
||||
The `/repeaters` (list) and `/repeaters/manage` (per-repeater tools) panels are standalone iframe pages built on the companion protocol's remote-request commands plus the repeater text CLI:
|
||||
|
||||
- **Serialization** — the companion firmware tracks a single pending remote request (each new send silently clears the previous one), so every repeater operation runs under `DeviceManager._repeater_lock` (180 s acquire timeout; a held lock returns `{'busy': True}` → HTTP 429). This also guards against two browser tabs operating at once
|
||||
- **Login sessions** — `repeater_login()` waits for `LOGIN_SUCCESS` filtered by the contact's `pubkey_prefix` and stores `{is_admin, permissions, logged_in_at}` in the in-memory `_repeater_sessions` dict (cleared on logout/app restart; the UI auto-relogs with the saved password). All remote endpoints fail fast with 401 `need_login` when no session exists — a repeater only answers pubkeys in its ACL, so requesting without a login would just burn a multi-minute timeout. A wrong password is indistinguishable from an unreachable repeater (the firmware never replies to failed logins), so timeout messages always name both causes
|
||||
- **CLI reply correlation** — `repeater_cmd_wait()` sends one text command and blocks for its reply. Replies arrive as `CONTACT_MSG_RECV` with `txt_type=1` (CLI_DATA) and carry no protocol-level correlation, so correlation = the repeater lock (single command in flight) + a single-slot waiter matched against the sender's 12-hex pubkey prefix at the top of `_on_dm_received`. Matched replies are consumed there and never stored as chat DMs; unmatched CLI replies keep the legacy behavior (stored as a DM) so the Console's fire-and-forget `cmd` flow is unchanged. Wait time derives from the device-suggested timeout (clamped 10–45 s)
|
||||
- **Settings batches** — reads run sequential `get <field>` commands per section and parse the firmware's `> value` replies, reporting per-field errors without failing the batch; writes send only dirty fields and classify each reply as `ok` (starts with `ok`/`password now`), `reboot_required` (reply mentions reboot — e.g. `set radio`), or `failed` (anything else, surfaced verbatim). Connection-level failures abort the rest of the batch
|
||||
- **Role gating** — the firmware silently drops text CLI from non-admin logins (which would surface as a timeout), so the CLI/Settings/Actions endpoints reject guest sessions with 403 up front instead
|
||||
- **Actions whitelist** — `advert.zerohop`, `advert` (flood), `clock sync`, `reboot`. `reboot` never replies (the firmware restarts immediately without building one), so a clean send followed by silence is reported as success. Text `erase` is firmware-gated to the USB serial console (`sender_timestamp == 0`), hence no erase in the UI
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
@@ -156,6 +167,7 @@ Key tables:
|
||||
- `read_status` - Per-channel read counters and favorites (`is_favorite` column; used to pin channels in the sidebar/dropdown sort order)
|
||||
- `analyzers` - User-configured MeshCore Analyzer services (`name`, `url_template` with `{packetHash}` placeholder, `is_default`, `is_disabled`; partial unique index enforces a single default)
|
||||
- `observer_brokers` - MQTT brokers for the Observer packet-capture feature (`name`, `host`, `port`, `username`, `password` — stored plaintext, `use_tls`, `tls_verify`, `is_disabled`)
|
||||
- `repeaters` - Repeaters saved in the My Repeaters panel (`public_key` PK, `password` — stored plaintext per the observer_brokers precedent, `added_at`, `last_login_at`, `last_login_role`). Everything else about a repeater (name, path, position) comes from the device contact at read time
|
||||
|
||||
`direct_messages` gained a `delivery_path_hash_size` column (auto-migrated, defaults to 1) so reloaded DM bubbles render multi-byte routes correctly. The `path_len` column on `channel_messages`, `direct_messages`, and `paths` now stores the raw firmware byte (masked hop count plus path_hash_mode in the upper bits), recombined at write time via `pack_path_len()`; the API endpoints decode it back into `path_hash_size` on read. `channel_messages` also gained a `raw_packet` column (the full hex wire snapshot captured at send time, indexed by `idx_cm_pkt` on `pkt_payload` for fast self-echo lookups) that powers raw resend; it is `NULL` for received and pre-migration rows, so the resend button stays disabled there.
|
||||
|
||||
@@ -280,6 +292,29 @@ The backend no longer ships a pre-built `analyzer_url` per message — channel-m
|
||||
|
||||
Every mutating endpoint hot-reloads the `ObserverManager`, so broker and setting changes take effect without an app restart.
|
||||
|
||||
### My Repeaters (repeater administration)
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| GET | `/api/repeaters` | Saved repeaters merged with device contact truth (`?refresh=true` bypasses the contacts cache) |
|
||||
| POST | `/api/repeaters` | Add a repeater (`{public_key}`; 409 when already saved) |
|
||||
| GET | `/api/repeaters/<pk>` | Single merged entry + login session state |
|
||||
| PUT | `/api/repeaters/<pk>` | Set or clear the saved password (`{password}`; empty string clears) |
|
||||
| DELETE | `/api/repeaters/<pk>` | Remove from the list (device contact untouched) |
|
||||
| POST | `/api/repeaters/<pk>/login` | Log in with `{password?, save?}` — omitted password uses the saved one |
|
||||
| GET | `/api/repeaters/<pk>/session` | In-memory session state (`logged_in`, `is_admin`, `permissions`) |
|
||||
| POST | `/api/repeaters/<pk>/logout` | Log out and drop the session |
|
||||
| GET | `/api/repeaters/<pk>/status` | Binary status request (battery, radio, packet stats) |
|
||||
| GET | `/api/repeaters/<pk>/clock` | Repeater clock (LE epoch from `req_basic_sync`) |
|
||||
| GET | `/api/repeaters/<pk>/telemetry` | All Cayenne LPP channels |
|
||||
| GET | `/api/repeaters/<pk>/neighbours` | Zero-hop neighbours enriched with contact names/positions |
|
||||
| POST | `/api/repeaters/<pk>/cli` | Text CLI command (`{command}` → `{output, elapsed_ms}`); admin only |
|
||||
| GET | `/api/repeaters/<pk>/settings` | Read one settings section (`?section=basic\|radio\|location\|features\|network\|advert\|operator\|advanced`) as a `get` batch; admin only |
|
||||
| POST | `/api/repeaters/<pk>/settings` | Apply dirty fields (`{values}`) as a `set` batch with per-field `ok\|failed\|reboot_required` results; admin only |
|
||||
| POST | `/api/repeaters/<pk>/action` | One-shot action (`{action: zerohop_advert\|flood_advert\|clock_sync\|reboot}`); admin only |
|
||||
|
||||
Error mapping is shared across the family: 401 `need_login` (no session), 403 (guest on an admin endpoint), 429 (another repeater operation in progress — single firmware request slot), 503 (device not connected), 504 (timeout: repeater unreachable *or* wrong password — indistinguishable by protocol). Passwords are never returned by any GET (`password_set` boolean only). The panels are served by `GET /repeaters` and `GET /repeaters/manage?pubkey=<64-hex>`.
|
||||
|
||||
### Direct Messages
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# How to Manage Your Repeater
|
||||
|
||||
> **Note:** mc-webui now ships a built-in repeater administration panel — **My Repeaters** in the main menu — with status, telemetry, neighbours, a remote CLI, settings, and actions. See [My Repeaters in the user guide](user-guide.md#my-repeaters-repeater-administration). The DM-based method below still works and remains useful as a fallback.
|
||||
|
||||
This guide explains how to manage a MeshCore repeater device directly from the mc-webui interface using Direct Messages.
|
||||
|
||||
---
|
||||
|
||||
+81
-2
@@ -16,6 +16,7 @@ This guide covers all features and functionality of mc-webui. For installation i
|
||||
- [Adding Contacts](#adding-contacts)
|
||||
- [DM Path Management](#dm-path-management)
|
||||
- [Interactive Console](#interactive-console)
|
||||
- [My Repeaters (Repeater Administration)](#my-repeaters-repeater-administration)
|
||||
- [Device Dashboard](#device-dashboard)
|
||||
- [Quick-Access FAB Buttons](#quick-access-fab-buttons)
|
||||
- [Settings](#settings)
|
||||
@@ -504,6 +505,8 @@ The console supports a comprehensive set of MeshCore commands organized into cat
|
||||
- `set_regions <name> <value>` - Set repeater regions
|
||||
- `set_clock <name>` - Sync repeater clock
|
||||
|
||||
For a graphical alternative to these commands, see [My Repeaters](#my-repeaters-repeater-administration).
|
||||
|
||||
**Contact Management:**
|
||||
- `contacts` - List all device contacts (paths shown with commas, e.g. `D1,90,05,54`)
|
||||
- `.contacts` - List contacts (JSON format)
|
||||
@@ -534,6 +537,82 @@ The console supports a comprehensive set of MeshCore commands organized into cat
|
||||
|
||||
---
|
||||
|
||||
## My Repeaters (Repeater Administration)
|
||||
|
||||
Administer MeshCore repeaters you hold the password to — check status and telemetry, browse neighbours, run CLI commands, change settings, and trigger actions like adverts or a reboot, all over the mesh:
|
||||
|
||||
1. Click the menu icon (☰) in the navbar
|
||||
2. Select **My Repeaters** from the menu
|
||||
|
||||
The panel opens full-screen, like Contact Management, and lists the repeaters you have added with their current routing path. (The menu item can be moved to the Quick Access FAB cluster in Settings → Appearance.)
|
||||
|
||||
### Adding a Repeater
|
||||
|
||||
Click **Add repeater**. The picker lists repeater contacts stored **on your device** — if the one you need is missing, it has to be heard and approved first (see [Contact Management](#contact-management)). Use the search box to filter, then click a repeater to add it. Adding is purely local: nothing is sent over the mesh yet.
|
||||
|
||||
### Passwords and Logging In
|
||||
|
||||
Click a repeater row to log in. The first time, you are asked for the repeater password; leave **Save password** checked and the app remembers it per repeater, so future logins are one click.
|
||||
|
||||
- The repeater decides your role from the password: **ADMIN** (full access) or **GUEST** (read-only: Status, Telemetry, Neighbors).
|
||||
- **Important:** a wrong password and an unreachable repeater look identical — MeshCore repeaters simply never answer a bad login. When a login times out, check reachability first (is the repeater several flood hops away?) before assuming the password is wrong.
|
||||
- Logins can take up to a minute on flood paths. Pinning a direct path (below) makes them much faster.
|
||||
|
||||
### Row Actions
|
||||
|
||||
- **Set path** - Configure the routing path used to reach the repeater, with the same editor as DM Contact Info: saved paths, apply to device, reset to flood, and a map-based repeater picker
|
||||
- **Set password** (key icon; filled when a password is saved) - Save, change, or clear the stored password
|
||||
- **Remove** - Remove the repeater from your list and delete its saved password. The device contact is untouched
|
||||
|
||||
### Repeater Management Panel
|
||||
|
||||
After a successful login the management panel opens. The header shows the repeater's name, shortened public key (with a copy button), current path, location, and your role badge (ADMIN / GUEST). Six tools are available; with a guest login, CLI, Settings, and Actions are locked.
|
||||
|
||||
#### Status
|
||||
|
||||
Fetched automatically when opened. A compact table in three groups:
|
||||
|
||||
- **System** - Battery (estimated % and volts), uptime, on-board clock, TX queue length, error events
|
||||
- **Radio** - Last RSSI / SNR, noise floor, TX and RX airtime
|
||||
- **Packets** - Sent and received counts (flood/direct split), duplicates, RX errors, and channel utilization (TX+RX airtime as a percentage of uptime)
|
||||
|
||||
#### Telemetry
|
||||
|
||||
Shows **all** Cayenne LPP channels at once — no channel picker. Each channel renders as a card with typed, unit-formatted rows (voltage, temperature, humidity, GPS position, and so on). Channel 1 is the repeater's own vitals.
|
||||
|
||||
#### Neighbors
|
||||
|
||||
Lists every zero-hop neighbour the repeater hears: resolved contact name (or the raw pubkey prefix for unknown nodes), how long ago it was heard, and SNR. When at least one neighbour has a known position, a **Map** toggle appears: the managed repeater is shown as a red marker, positioned neighbours in green, and the dashed connection lines carry SNR labels. A footnote counts neighbours that could not be placed on the map.
|
||||
|
||||
#### CLI (admin only)
|
||||
|
||||
A remote text console for the repeater, styled like the Interactive Console. Type a command (e.g. `get name`, `ver`, `clock`) and the reply comes back into the terminal together with the round-trip time. Quick-command chips, Enter to send, and per-repeater command history (arrow keys) are built in.
|
||||
|
||||
Replies travel over LoRa, so an occasional lost reply (timeout) is normal — just send the command again.
|
||||
|
||||
#### Settings (admin only)
|
||||
|
||||
Repeater configuration organized into collapsible sections: **Basic** (name, admin and guest passwords), **Radio** (frequency / bandwidth / SF / CR, TX power, RX gain), **Location**, **Features** (repeat, read-only access, multiple ACKs), **Network health** (loop detection, duty cycle), **Advertisement** (advert intervals, max flood hops), **Operator info**, and **Advanced**.
|
||||
|
||||
- Each section loads its values live from the repeater when you first expand it (every field is one mesh round-trip, so a section takes a few seconds) and has its own **Refresh** and **Apply** buttons
|
||||
- Changed fields are highlighted and counted on the Apply button; only those fields are sent
|
||||
- Every field reports back individually: a green check (applied), a **reboot required** badge (stored, takes effect after a reboot — radio parameters work this way), or a red error showing the repeater's own reply (e.g. an out-of-range value). Failed fields stay marked so you can correct and re-apply
|
||||
- Changing radio parameters asks for confirmation first — wrong values can make the repeater unreachable over the mesh
|
||||
- The admin password is write-only (the current one is never displayed). After a successful change, the password saved in mc-webui is updated automatically so one-click login keeps working. Changing it does **not** log out sessions that are already active
|
||||
|
||||
#### Actions (admin only)
|
||||
|
||||
One-click operations:
|
||||
|
||||
- **Send zero-hop advert** - Announce the repeater to its direct neighbours. The recommended way to make it visible
|
||||
- **Send flood advert** - Advert flooded across the whole mesh. Not recommended — high network load; use sparingly
|
||||
- **Sync clock** - Set the repeater clock from your device's current time. The firmware refuses to move a clock backwards and says so
|
||||
- **Danger zone: Reboot** - Restarts the repeater after a confirmation prompt. The firmware does not reply to this command; the repeater simply drops off the mesh for a few seconds and comes back
|
||||
|
||||
Erasing the repeater's file system is **not** available over the mesh — the firmware only accepts it on the USB serial console (use the MeshCore flasher for that).
|
||||
|
||||
---
|
||||
|
||||
## Device Dashboard
|
||||
|
||||
Access device information and statistics:
|
||||
@@ -586,7 +665,7 @@ Tap the toggle button (short click, no drag) to hide or show the rest of the FAB
|
||||
|
||||
Open Settings → **Appearance** tab to adjust:
|
||||
- **Hide Quick Access** - Master switch: hides the FAB cluster entirely and moves all actions to the Main Menu
|
||||
- **Per-item placement** - Choose whether each of the 11 actions appears in the FAB or in the Main Menu. Changes take effect immediately
|
||||
- **Per-item placement** - Choose whether each of the 12 actions appears in the FAB or in the Main Menu. Changes take effect immediately
|
||||
- **Button size** - 28 to 72 pixels (default: 56)
|
||||
- **Spacing** - 2 to 24 pixels between buttons (default: 12)
|
||||
- **Reset position** - Reset both main chat and DM FAB positions to their defaults
|
||||
@@ -672,7 +751,7 @@ Controls small notification toasts shown after actions (e.g. "Advert Sent", erro
|
||||
|
||||
**Quick Access Buttons:**
|
||||
- **Hide Quick Access** - Master switch that hides the entire floating FAB cluster and moves all items to the Main Menu (slide-out)
|
||||
- **Per-item placement** - A table of all 11 configurable actions (Filter, Search, Direct Messages, Contacts, Settings, Send Advert, Flood Advert, Backup, Cleanup Contacts, System Log, Repeater Mgmt). Each row has two radio buttons: **Quick Access** (shows in FAB) and **Main Menu** (shows in the slide-out). Changes take effect immediately
|
||||
- **Per-item placement** - A table of all 12 configurable actions (Filter messages, Search messages, Direct Messages, Contact Management, Settings, Send Advert, Flood Advert, Map, Console, My Repeaters, Device Info, System Log). Each row has two radio buttons: **Quick Access** (shows in FAB) and **Main Menu** (shows in the slide-out). Changes take effect immediately
|
||||
- **Button size (px)** - Adjust the size of FAB buttons (default: 56)
|
||||
- **Spacing (px)** - Space between FAB buttons (default: 12)
|
||||
- **Position** - Reset FAB position to default (top-right)
|
||||
|
||||
+9
-1
@@ -10,12 +10,20 @@ For deep technical notes, see [architecture.md](architecture.md). For the full g
|
||||
|
||||
### New features
|
||||
|
||||
- **My Repeaters — administer your repeaters from the browser.** A new full-screen panel (main menu → **My Repeaters**) for the MeshCore repeaters you hold the password to. Add repeaters from your device's contacts, save the admin password once, and from then on logging in is one click — the app shows whether the repeater granted you **ADMIN** or **GUEST** rights. Each entry also gets the same path editor as DMs, so you can pin a direct route to make logins and commands fast. Heads-up: repeaters never answer a bad login, so a wrong password looks exactly like an unreachable repeater — the app's error messages say so instead of guessing.
|
||||
- **Monitoring tools per repeater: Status, Telemetry, Neighbors.** After login you land in a management panel. **Status** shows battery, uptime, clock, RSSI/SNR/noise floor, packet counters, and channel utilization in one compact table. **Telemetry** lists every Cayenne LPP channel at once, with proper units. **Neighbors** shows every zero-hop node the repeater hears (name, last heard, SNR) — plus a map view that draws SNR-labeled links to the neighbours it can place. Works with guest logins too.
|
||||
- **Remote CLI, Settings, and Actions (admin logins).** **CLI** is a real terminal to the repeater — quick-command chips, per-repeater history, round-trip times. **Settings** edits the repeater configuration in collapsible sections (Basic, Radio, Location, Features, Network health, Advertisement, Operator info, Advanced): values load live from the repeater, only the fields you change are sent, and every field reports back individually — including a "reboot required" badge for radio parameters and the firmware's own error text for rejected values. **Actions** covers zero-hop advert, flood advert (marked "not recommended" — high network load), clock sync, and a confirmation-guarded reboot in a Danger zone. Erasing the file system stays USB-serial-only by firmware design, and the panel says so.
|
||||
- **Observer mode — feed packet analyzers straight from mc-webui.** The new **Settings → Observer** tab turns your node into a MeshCore observer: every packet the device overhears is published to one or more MQTT brokers in the standard `meshcore-packet-capture` format, so analyzer services (a self-hosted Corescope, letsmesh-style maps) see your local mesh traffic without a separate capture script or a dedicated second node. Configure brokers with host/port, optional username/password and TLS; each row shows a live connected/error badge, and the tab counts packets captured vs published in real time. Capture is completely passive — chat and direct messages are unaffected — and all changes apply immediately, no restart needed. (LetsMesh token-authenticated brokers are not supported yet.)
|
||||
- **Scheduled flood adverts.** The Observer tab includes an optional advert interval in hours: the app sends a flood advert on that schedule so your observer stays visible on analyzer maps. The timer survives restarts, so a redeploy won't send an extra advert early. Set it to 0 to keep adverts fully manual.
|
||||
|
||||
### Reliability & polish
|
||||
|
||||
- **Console `login` reports your role.** A successful repeater login in the Interactive Console now answers "Logged into X as admin" (or guest) instead of a bare success line.
|
||||
|
||||
### Deploy notes
|
||||
|
||||
- This update adds a new Python dependency (`paho-mqtt`), so the Docker image must be rebuilt — the standard `mcupdate` flow does this automatically. Broker passwords entered in the Observer tab are stored in plain text in the app database; use dedicated MQTT credentials.
|
||||
- This update adds a new Python dependency (`paho-mqtt`) and raises the `meshcore` library requirement to 2.3.7, so the Docker image must be rebuilt — the standard `mcupdate` flow does this automatically.
|
||||
- Passwords you save in the app — MQTT broker credentials in the Observer tab and repeater admin passwords in My Repeaters — are stored in plain text in the app database. That's a deliberate trade-off for a private single-user LAN app; use dedicated credentials where you can.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user