Skip to content

feat(ui): use modem-preset-relative SNR thresholds for signal quality#5903

Merged
jamesarich merged 1 commit into
mainfrom
claude/eloquent-noyce-d4d073
Jun 22, 2026
Merged

feat(ui): use modem-preset-relative SNR thresholds for signal quality#5903
jamesarich merged 1 commit into
mainfrom
claude/eloquent-noyce-d4d073

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

Why

Signal quality was rated against fixed SNR/RSSI thresholds, so a node's rating ignored the active modem preset. A node at −10 dB SNR showed BAD even though that's 7.5 dB above LongFast's −17.5 dB demodulation floor — an excellent link. This rates SNR relative to the preset's demodulation floor instead, matching the intent of Meshtastic-Apple's getSnrColor(snr:preset:).

Resolves #5446.

🌟 New Features

  • Preset-relative signal quality. determineSignalQuality(snr, modemPreset) now rates SNR against the preset's demodulation floor: GOOD > limit, FAIR > limit − 5.5, BAD ≥ limit − 7.5, NONE below. The per-value Snr() text color uses the same bands.
  • ModemPreset?.snrLimit (core:model, on ChannelOption alongside bandwidth) maps each preset to its spreading-factor demodulation floor (SF7 −7.5 … SF12 −20); unknown/unset → LongFast default.

🐛 Bug Fixes

  • Good links on the longer-range presets no longer mis-rate as BAD/NONE.
  • RSSI is dropped from the rating (still displayed): per @GUVWAF, without the noise floor RSSI can't indicate whether a signal is demodulable, so SNR-vs-preset-floor is the meaningful measure.
  • LongSlow uses the physically-correct SF12 floor (−20 dB), not −7.5. Meshtastic-Apple's snrLimit() returns −7.5 for LongSlow (the SF7 value — an apparent bug); every other preset matches the SF physics. This intentionally diverges from Apple on that one value; worth fixing on Apple's side too.

🛠️ Refactoring & Architecture

  • Delivery via a LocalModemPreset CompositionLocal, provided once in MeshtasticAppShell from RadioConfigRepository.localConfigFlow. Leaf composables (Snr, NodeSignalQuality, LoraSignalIndicator, …) default modemPreset = LocalModemPreset.current, so the node list, node-detail Signal Metrics, and message/reaction rows all rate preset-relative with no per-screen plumbing — matching the app's existing narrow Local* ambients.
  • Android Auto (feature:car) is non-Compose, so it sources the preset from its own localConfigFlow combine in CarStateCoordinator and precomputes NodeUi.signalQuality (its 5-level enum kept, now preset-relative).

Testing Performed

  • New core/ui/.../LoraSignalIndicatorTest.kt: SF→floor mapping per preset, the LongSlow −20 correction, null/unset → LongFast fallback, the issue's −10 dB-on-LongFast = GOOD example, band boundaries, and RSSI-independence.
  • Updated CarScreenDataBuilderTest: rewrote the signal-quality cases for the new (snr, modemPreset) signature (preset-relative bands, LongSlow floor).
  • Full baseline green: spotlessApply spotlessCheck detekt assembleDebug test allTests kmpSmokeCompile.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the enhancement New feature or request label Jun 22, 2026
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

📄 Docs staleness check — advisory

This PR modifies user-facing UI source files but does not update any page under docs/en/user/ or docs/en/developer/.

⚠️ Doc changes propagate to 3 consumers: in-app docs browser, Jekyll site (GitHub Pages), and meshtastic.org (Docusaurus sync). Updating a page in docs/en/ automatically flows to all three.

Changed source files:

core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/BuildNodeDescription.kt
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/LoraSignalIndicator.kt
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/MeshtasticAppShell.kt
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/NodeItem.kt
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/NodeItemCompact.kt
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/SignalInfo.kt
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/util/LocalModemPreset.kt

What to check:

Changed area Likely doc page
feature/messaging/ docs/en/user/messages-and-channels.md
feature/node/ docs/en/user/nodes.md or docs/en/user/node-metrics.md
feature/map/ docs/en/user/map-and-waypoints.md
feature/connections/ docs/en/user/connections.md
feature/settings/ docs/en/user/settings-radio-user.md or docs/en/user/settings-module-admin.md
feature/firmware/ docs/en/user/firmware.md
feature/intro/ docs/en/user/onboarding.md
feature/discovery/ docs/en/user/discovery.md
feature/docs/ Internal docs infrastructure
core/ui/ docs/en/developer/codebase.md or component-specific user pages

New page checklist (if adding a new doc page):

  1. Create the .md file in docs/en/user/ or docs/en/developer/ with last_updated frontmatter
  2. Register in DocBundleLoader.kt with string resources (in-app browser)
  3. Jekyll and Docusaurus sync pick up new pages automatically — no config change needed

If this PR does not require a doc update (e.g., internal refactor, bug fix, test change), add the skip-docs-check label to dismiss this check.

Cross-platform note: This check is advisory while doc coverage matures. Both Android and Apple repos use the same skip-docs-check label and advisory severity. See meshtastic/design standards for shared conventions.

@jamesarich jamesarich marked this pull request as ready for review June 22, 2026 16:54
Signal quality was rated against fixed SNR/RSSI thresholds, ignoring the active modem preset — a node at -10 dB SNR showed BAD even though it is well above LongFast's -17.5 dB demodulation floor. Rate SNR relative to the preset's demodulation floor instead (RSSI dropped from the rating per GUVWAF, still displayed); deliver the preset via a LocalModemPreset CompositionLocal provided once at the app root.

Resolves #5446.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jamesarich jamesarich force-pushed the claude/eloquent-noyce-d4d073 branch from 7d6a799 to 32d07e2 Compare June 22, 2026 16:54
@jamesarich jamesarich enabled auto-merge June 22, 2026 16:54
@jamesarich jamesarich added this pull request to the merge queue Jun 22, 2026
Merged via the queue into main with commit 27e936f Jun 22, 2026
22 checks passed
@jamesarich jamesarich deleted the claude/eloquent-noyce-d4d073 branch June 22, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use modem-preset-relative SNR thresholds for signal quality

1 participant