Two correctness fixes for remote-admin TX optimization:
1. Reverse/round-trip measurement path. The optimizer traced a one-way path
ending at the (possibly far) target and waited for the target itself to
originate the trace reply, which never returns when the target is only
reachable via other repeaters, so every trace timed out. Now we trace out
to the target and back (the MeshCore A,B,A convention) so a reachable
near node answers; the target only forwards. Its received SNR is read from
its hop by hash (the round trip turn-around) rather than by position.
2. Restore original TX on no result. If not one trace gets through at any
level there is no meaningful winner, so leave the node at its original
power (applied=False) and warn, instead of writing a bogus value.
Mock updated to model each hop SNR from the node that transmitted into it and
to drop traces on the bottleneck hop. Added round-trip / target-hash tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tune the TX power of a remote node we have admin rights on (the hop before
a chosen target) to maximize the SNR the target receives from it, instead of
tuning the local device against a path bottleneck.
- Device gains admin_login / get_remote_tx_power / set_remote_tx_power
(MeshCoreDevice via send_login_sync + `set tx <dbm>` send_cmd; MockDevice
models target SNR as an inverted-U in the admin node's TX with a reliability
dropoff at the band edges).
- tx_optimizer: forced-path sweep with a lexicographic objective (reliability
first, then SNR), median-based levels, coarse+refine search, and a verify
pass; near-SNR ties break toward lower power. Outlier-robust by construction.
- AdminStore remembers per-node admin passwords in <config_dir>/admin.json
(owner-only perms), cleared automatically when a login is rejected.
- Configurable 12-28 dBi default range (tx_opt_min/tx_opt_max).
- tx-optimize tool: path/password prompts, live progress, persistence, applies
the winner on finish, and renders an interactive HTML chart.
- Rewrote TX result models, widgets, plot, repository.record_tx_sample, and the
TX tests for the new flow.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MeshTools is a Rich+Questionary interactive / Typer-scriptable toolkit for
tuning a MeshCore mesh over a serial companion device, with SQLite-logged runs
and Plotly visualizations. Includes the skeleton (trace, info, history),
TX-power optimization, and a MockDevice simulator (--mock).
Device discovery & selection:
- core/discovery.py: enumerate serial ports (pyserial), flag/sort likely LoRa
hardware by USB vendor id, stable_id for replug-safe identity.
- core/device_store.py: remember the last successfully connected device in
<config_dir>/devices.json (independent of --db).
- core/selection.py: non-interactive resolver (--port > profile > remembered >
sole device > guidance error) for the CLI.
- ui/device_picker.py + menu startup: interactive picker preselecting the
remembered default; banner reflects the choice.
- tools/devices.py: `meshtools devices` lists/marks attached devices.
- AppContext resolves the port and records last-known-good on connect success.
Fixes:
- theme.py: force UTF-8 on stdout/stderr so glyphs don't crash legacy consoles.
- connection.py: friendly message when meshcore is missing; pin meshcore>=2.3.
- trace/tx-optimize: fall back to free-text target entry when the device
reports no contacts (autocomplete requires non-empty choices).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>