Skip to content

Commit bdb8d58

Browse files
committed
feat: config fields, module pages, key verification, telemetry capture
Incorporates the firmware-current feature work onto the protobuf foundation: new config fields (Display message bubbles; LoRa fem_lna_mode + serial_hal_only; Telemetry air_quality_screen_enabled); 4 new ModuleConfig pages (TrafficManagement, StatusMessage, TAK, RemoteHardware); the manual Key Verification flow (sendKeyVerification + ClientNotificationDialog stages + Verify Key button); live telemetry capture (nodeDB addDeviceMetrics) and admin hardening (toggleMutedNode, graceful PortNum default); plus the sdk-preview ConfigEditor demo and store/config tests. Build + lint + format + 131 tests green.
1 parent ec59c8a commit bdb8d58

49 files changed

Lines changed: 1884 additions & 28 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

PR-NOTES.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Protobuf catch-up to firmware-current
2+
3+
> Draft PR description + the one decision for maintainers. This file is **untracked**
4+
> use it as the PR body, then delete it (or leave it, it won't be committed).
5+
6+
## What this does
7+
8+
- Syncs the vendored `.proto` sources in `packages/protobufs/meshtastic/` from ~v2.7.20 to
9+
**firmware-current (v2.7.25 + 48 commits)** — +2 new files (`deviceonly_legacy`, `serial_hal`)
10+
and additions across `config` / `module_config` / `mesh` / `admin` / `portnums` / `telemetry`.
11+
- Regenerates the v2 TS bindings (`buf generate`).
12+
- Makes the app consume the **workspace** protobufs (`workspace:*`) instead of the stale JSR
13+
`@meshtastic/protobufs@2.7.20`, finishing the monorepo migration that was half-done
14+
(`@meshtastic/core` was already `workspace:*`; protobufs was still on JSR).
15+
- One breaking-change fix: `admin.proto` `nodedb_reset` changed `int32 → bool`, so
16+
`MeshDevice.resetNodes()` now sends `value: true` (the oneof-case presence triggers the
17+
reset; `true` preserves favorites through it).
18+
19+
## Free wins (dynamic enum dropdowns — no UI code)
20+
21+
New LoRa regions (ITU/EU amateur bands), modem presets (LONG_TURBO, LITE/NARROW/TINY_*),
22+
~25 hardware names, `OLED_SH1107_ROTATED`, serial `LOG`/`LOGTEXT` — they flow into the
23+
existing enum-bound `<select>`s automatically once the bindings regenerate.
24+
25+
## Breaking proto changes that DON'T break us (verified)
26+
27+
- `deviceonly.proto` `NodeInfoLite` restructure — core never imports `NodeInfoLite`.
28+
- `channel.proto` `is_client_muted → is_muted` + `mute` removed — neither web nor core
29+
references those fields yet.
30+
31+
## The one decision for maintainers — how to consume the protobufs
32+
33+
This changeset takes **Option A (workspace consumption):** rename the workspace package
34+
`@meshtastic/protobufs-ws → @meshtastic/protobufs` (still `private`), point its `exports` at the
35+
TS source, and depend on it via `workspace:*` from root + core.
36+
37+
- ✅ Monorepo is self-consuming and always firmware-current; no publish round-trip; matches
38+
the already-migrated `@meshtastic/core`.
39+
- ⚠️ Diverges from the JSR publish flow; the published JSR `@meshtastic/protobufs`
40+
(latest 2.7.23) is no longer what the app builds against.
41+
42+
**Option B (canonical publish flow):** keep the package JSR-published — sync the `.proto`
43+
sources here, publish a new `@meshtastic/protobufs` to JSR, then bump the root range.
44+
45+
- ✅ Stays on the established pipeline; one source of truth on JSR.
46+
- ⚠️ Needs a JSR publish, and can't reach firmware-current until that release lands
47+
(JSR tops out at 2.7.23, still behind firmware).
48+
49+
If you prefer **B**, everything except the 3 dependency-wiring edits still applies — the
50+
`.proto` sync, the regen, and the `nodedbReset` fix are identical; only the root dep, the core
51+
dep, and the protobufs `package.json` name/exports get swapped for a JSR publish + range bump.
52+
53+
## Regenerating bindings
54+
55+
```
56+
pnpm --filter @meshtastic/protobufs gen
57+
```
58+
59+
Output lands in `packages/protobufs/packages/ts/dist/` (gitignored).
60+
61+
## Verified in isolation (this branch only — no feature/demo code)
62+
63+
- `packages/core` typecheck: clean except 2 **pre-existing** `queue.ts` strict-catch errors.
64+
- `packages/web` `vite build`: green.
65+
- 36 config/module validation tests: pass.

apps/web/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"@meshtastic/transport-web-bluetooth": "workspace:*",
3939
"@meshtastic/transport-web-serial": "workspace:*",
4040
"@noble/curves": "^1.9.2",
41+
"@preact/signals-core": "^1.8.0",
42+
"better-result": "^1.0.0",
4143
"@radix-ui/react-accordion": "^1.2.12",
4244
"@radix-ui/react-alert-dialog": "^1.1.15",
4345
"@radix-ui/react-checkbox": "^1.3.3",

apps/web/public/i18n/locales/en/config.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@
118118
"wakeOnTapOrMotion": {
119119
"description": "Wake the device on tap or motion",
120120
"label": "Wake on Tap or Motion"
121+
},
122+
"enableMessageBubbles": {
123+
"label": "Message Bubbles",
124+
"description": "Display incoming messages as bubbles on the device screen"
121125
}
122126
},
123127
"lora": {
@@ -198,6 +202,14 @@
198202
"radioSettings": {
199203
"label": "Radio Settings",
200204
"description": "Settings for the LoRa radio"
205+
},
206+
"femLnaMode": {
207+
"label": "FEM/LNA Mode",
208+
"description": "Control an external RF front-end module / low-noise amplifier (only on boards that have one)"
209+
},
210+
"serialHalOnly": {
211+
"label": "Serial HAL Only",
212+
"description": "Communicate with the radio exclusively over the serial hardware abstraction layer"
201213
}
202214
},
203215
"network": {

apps/web/public/i18n/locales/en/dialog.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@
128128
"publicKey": "Public Key: ",
129129
"messageable": "Messageable: ",
130130
"KeyManuallyVerifiedTrue": "Public Key has been manually verified",
131-
"KeyManuallyVerifiedFalse": "Public Key is not manually verified"
131+
"KeyManuallyVerifiedFalse": "Public Key is not manually verified",
132+
"verifyKey": "Verify Key"
132133
},
133134
"pkiBackup": {
134135
"loseKeysWarning": "If you lose your keys, you will need to reset your device.",
@@ -234,5 +235,25 @@
234235
"description": "This will factory reset the configuration on the connected device, erasing all configurations on the device. This cannot be undone. Are you sure you want to continue?",
235236
"confirm": "Factory Reset Config",
236237
"failedTitle": "There was an error performing the factory reset. Please try again."
238+
},
239+
"keyVerification": {
240+
"continue": "Continue",
241+
"cancel": "Cancel",
242+
"inform": {
243+
"title": "Key Verification",
244+
"description": "Share this security number with {{name}} so they can enter it on their device:"
245+
},
246+
"request": {
247+
"title": "Key Verification",
248+
"description": "Enter the security number shown on {{name}}'s device:",
249+
"placeholder": "Security number",
250+
"submit": "Submit"
251+
},
252+
"final": {
253+
"title": "Verify Key",
254+
"description": "Confirm these characters match the ones shown on {{name}}'s device:",
255+
"verify": "Verify",
256+
"reject": "Don't Verify"
257+
}
237258
}
238259
}

apps/web/public/i18n/locales/en/moduleConfig.json

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
"tabRangeTest": "Range Test",
1212
"tabSerial": "Serial",
1313
"tabStoreAndForward": "S&F",
14-
"tabTelemetry": "Telemetry"
14+
"tabTelemetry": "Telemetry",
15+
"tabRemoteHardware": "Remote Hardware",
16+
"tabTrafficManagement": "Traffic Management",
17+
"tabStatusMessage": "Status Message",
18+
"tabTak": "TAK"
1519
},
1620
"ambientLighting": {
1721
"title": "Ambient Lighting Settings",
@@ -443,6 +447,102 @@
443447
"powerScreenEnabled": {
444448
"label": "Power Screen Enabled",
445449
"description": "Enable the Power Telemetry Screen"
450+
},
451+
"airQualityScreenEnabled": {
452+
"label": "Air Quality Screen Enabled",
453+
"description": "Show the Air Quality telemetry on the device screen"
454+
}
455+
},
456+
"remoteHardware": {
457+
"title": "Remote Hardware Settings",
458+
"description": "Settings for the Remote Hardware module",
459+
"enabled": {
460+
"label": "Module Enabled",
461+
"description": "Enable the Remote Hardware module"
462+
},
463+
"allowUndefinedPinAccess": {
464+
"label": "Allow Undefined Pin Access",
465+
"description": "Allow reading/writing GPIO pins not defined in the available pins list"
466+
}
467+
},
468+
"statusMessage": {
469+
"title": "Status Message Settings",
470+
"description": "Periodically rebroadcast a short status message for this node",
471+
"nodeStatus": {
472+
"label": "Status Message",
473+
"description": "The status string this node broadcasts on change and on a timer"
474+
}
475+
},
476+
"tak": {
477+
"title": "TAK Settings",
478+
"description": "Settings for the ATAK (Team Awareness Kit) plugin module",
479+
"team": {
480+
"label": "Team",
481+
"description": "Team color / designation reported to ATAK"
482+
},
483+
"role": {
484+
"label": "Role",
485+
"description": "Member role reported to ATAK"
486+
}
487+
},
488+
"trafficManagement": {
489+
"title": "Traffic Management Settings",
490+
"description": "Packet inspection and traffic shaping to reduce channel utilization",
491+
"enabled": {
492+
"label": "Module Enabled",
493+
"description": "Enable traffic management packet inspection and shaping"
494+
},
495+
"positionDedupEnabled": {
496+
"label": "Position Deduplication",
497+
"description": "Drop redundant position broadcasts"
498+
},
499+
"positionPrecisionBits": {
500+
"label": "Position Precision Bits",
501+
"description": "Bits of precision used for position deduplication (0-32)"
502+
},
503+
"positionMinIntervalSecs": {
504+
"label": "Position Min Interval",
505+
"description": "Minimum seconds between position updates from the same node"
506+
},
507+
"nodeinfoDirectResponse": {
508+
"label": "NodeInfo Direct Response",
509+
"description": "Answer NodeInfo requests directly from the local cache"
510+
},
511+
"nodeinfoDirectResponseMaxHops": {
512+
"label": "NodeInfo Response Max Hops",
513+
"description": "Minimum hop distance from the requester before responding to NodeInfo requests"
514+
},
515+
"rateLimitEnabled": {
516+
"label": "Rate Limiting",
517+
"description": "Throttle chatty nodes with per-node rate limiting"
518+
},
519+
"rateLimitWindowSecs": {
520+
"label": "Rate Limit Window",
521+
"description": "Time window in seconds for rate-limit calculations"
522+
},
523+
"rateLimitMaxPackets": {
524+
"label": "Rate Limit Max Packets",
525+
"description": "Maximum packets allowed per node within the rate-limit window"
526+
},
527+
"dropUnknownEnabled": {
528+
"label": "Drop Unknown Packets",
529+
"description": "Drop undecryptable packets per rate-limit window"
530+
},
531+
"unknownPacketThreshold": {
532+
"label": "Unknown Packet Threshold",
533+
"description": "Number of unknown packets before dropping from a node"
534+
},
535+
"exhaustHopTelemetry": {
536+
"label": "Exhaust Hop (Telemetry)",
537+
"description": "Set hop limit to 0 for relayed telemetry broadcasts"
538+
},
539+
"exhaustHopPosition": {
540+
"label": "Exhaust Hop (Position)",
541+
"description": "Set hop limit to 0 for relayed position broadcasts"
542+
},
543+
"routerPreserveHops": {
544+
"label": "Preserve Router Hops",
545+
"description": "Preserve hop limit for router-to-router traffic"
446546
}
447547
}
448548
}

0 commit comments

Comments
 (0)