feat(mesh): device-detected setup modal with board images + full radio settings

Plugging in a LoRa radio now pops a global two-step setup modal on any
page: step 1 shows the ACTUAL detected board (25 board SVGs vendored
from the Meshtastic web-flasher, GPL-3.0; matched by USB product string
on native-USB boards, vid:pid heuristics for bridge chips, animated
fallback otherwise); step 2 configures with Archipelago presets — the
LoRa region pre-selected from the node's location (new lat/lon→region
mapping), channel 'archipelago', node name, and an advanced firmware
pin. Options adapt per protocol: region+channel program Meshtastic;
MeshCore shows its community frequency plan (firmware owns RF); RNode
defers to the Reticulum daemon config.

Backend: mesh.configure now accepts lora_region (validated against the
driver's region table) and device_kind (probe pin); mesh.status returns
the persisted values plus per-port USB identity (sysfs vid/pid/product)
for board identification. The Mesh Device tab gains a full settings
form (region with duty-cycle/legality hints, firmware pin, channel,
name, identity broadcast) replacing the read-only panel; the old
Mesh-page-only onboarding modal is superseded by the global flow.

Mock backend: stateful mesh config so the dev UI demos the full
detect→configure round-trip (disable mesh → modal fires with Heltec V3).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-14 08:40:18 -04:00
co-authored by Claude Fable 5
parent c014c4b3ee
commit 7b36b5cc34
38 changed files with 5210 additions and 71 deletions
+12
View File
@@ -401,6 +401,12 @@ pub struct MeshConfig {
pub reticulum_tcp: Option<types::ReticulumTcpConfig>,
}
/// True when `name` is a LoRa region the Meshtastic driver can program
/// (the canonical region list for the mesh settings UI).
pub fn meshtastic_region_is_valid(name: &str) -> bool {
meshtastic::region_name_to_code(name).is_some()
}
fn default_assistant_backend() -> String {
"claude".to_string()
}
@@ -545,6 +551,12 @@ pub async fn detect_devices() -> Vec<String> {
serial::detect_serial_devices().await
}
/// Detected serial ports with USB identity metadata (for the device-detected
/// setup modal's hardware graphic).
pub async fn detect_devices_info() -> Vec<serial::DetectedDeviceInfo> {
serial::detect_serial_devices_info().await
}
// ─── MeshService ────────────────────────────────────────────────────────
/// Top-level mesh networking service.