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:
co-authored by
Claude Fable 5
parent
c014c4b3ee
commit
7b36b5cc34
@@ -2632,20 +2632,32 @@ app.post('/rpc/v1', (req, res) => {
|
||||
// =====================================================================
|
||||
case 'mesh.status': {
|
||||
globalThis.__meshHeaders ||= { announce_block_headers: false, receive_block_headers: true }
|
||||
// Stateful enable/disable so the dev UI can demo the global
|
||||
// "mesh device detected" setup modal: disable mesh on the Mesh page
|
||||
// and the modal fires (device present but not connected).
|
||||
globalThis.__meshCfg ||= { enabled: true, lora_region: 'EU_868', device_kind: null, channel_name: 'archipelago', advert_name: 'archy-228' }
|
||||
const mc = globalThis.__meshCfg
|
||||
return res.json({
|
||||
result: {
|
||||
enabled: true,
|
||||
device_type: 'Meshcore',
|
||||
enabled: mc.enabled,
|
||||
device_type: mc.enabled ? 'Meshcore' : 'unknown',
|
||||
device_path: '/dev/ttyUSB0',
|
||||
device_connected: true,
|
||||
firmware_version: '2.3.1',
|
||||
self_node_id: 42,
|
||||
self_advert_name: 'archy-228',
|
||||
peer_count: 4,
|
||||
channel_name: 'archipelago',
|
||||
device_connected: mc.enabled,
|
||||
firmware_version: mc.enabled ? '2.3.1' : null,
|
||||
self_node_id: mc.enabled ? 42 : null,
|
||||
self_advert_name: mc.advert_name,
|
||||
peer_count: mc.enabled ? 4 : 0,
|
||||
channel_name: mc.channel_name,
|
||||
messages_sent: 23,
|
||||
messages_received: 47,
|
||||
detected_devices: ['/dev/ttyUSB0'],
|
||||
device_present: true,
|
||||
detected_device_info: [
|
||||
{ path: '/dev/ttyUSB0', vid: '10c4', pid: 'ea60', product: 'HELTEC LoRa 32 V3', manufacturer: 'Heltec' },
|
||||
],
|
||||
lora_region: mc.lora_region,
|
||||
device_kind: mc.device_kind,
|
||||
region: mc.enabled ? mc.lora_region : null,
|
||||
announce_block_headers: globalThis.__meshHeaders.announce_block_headers,
|
||||
receive_block_headers: globalThis.__meshHeaders.receive_block_headers,
|
||||
},
|
||||
@@ -2756,7 +2768,16 @@ app.post('/rpc/v1', (req, res) => {
|
||||
globalThis.__meshHeaders ||= { announce_block_headers: false, receive_block_headers: true }
|
||||
if (params && typeof params.announce_block_headers === 'boolean') globalThis.__meshHeaders.announce_block_headers = params.announce_block_headers
|
||||
if (params && typeof params.receive_block_headers === 'boolean') globalThis.__meshHeaders.receive_block_headers = params.receive_block_headers
|
||||
return res.json({ result: { configured: true, ...globalThis.__meshHeaders } })
|
||||
// Stateful radio settings (see mesh.status) — lets the dev UI demo
|
||||
// the detected-device modal + the Device panel settings round-trip.
|
||||
globalThis.__meshCfg ||= { enabled: true, lora_region: 'EU_868', device_kind: null, channel_name: 'archipelago', advert_name: 'archy-228' }
|
||||
const cfg = globalThis.__meshCfg
|
||||
if (params && typeof params.enabled === 'boolean') cfg.enabled = params.enabled
|
||||
if (params && typeof params.lora_region === 'string') cfg.lora_region = params.lora_region || null
|
||||
if (params && typeof params.device_kind === 'string') cfg.device_kind = params.device_kind === 'auto' ? null : params.device_kind
|
||||
if (params && typeof params.channel_name === 'string') cfg.channel_name = params.channel_name
|
||||
if (params && typeof params.advert_name === 'string') cfg.advert_name = params.advert_name
|
||||
return res.json({ result: { configured: true, enabled: cfg.enabled, lora_region: cfg.lora_region, device_kind: cfg.device_kind, ...globalThis.__meshHeaders } })
|
||||
}
|
||||
|
||||
case 'mesh.send-invoice': {
|
||||
|
||||
Reference in New Issue
Block a user