Background
Per meshtastic/design#15, Android hit the same cross-platform signal-quality question and settled on SNR-only rating (RSSI still displayed, just not used to determine the quality tier). From Meshtastic-Android#5446 (@GUVWAF, Android maintainer):
In the end it's SNR that matters; the "packet RSSI" we use is the real strength of only the signal here, but to judge whether that's enough we would need to know the noise floor... I would either remove the check for RSSI in both places.
Android went with removing RSSI from the rating entirely (Meshtastic-Android#5903). iOS should do better than that, not just match it — see below.
Current iOS behavior
Meshtastic/Views/Helpers/LoRaSignalStrengthIndicator.swift's getLoRaSignalStrength(snr:rssi:preset:) blends fixed, guessed RSSI thresholds (-115/-120/-126) together with the SNR-vs-preset-limit comparison to decide the 4-tier bar rating (None/Bad/Fair/Good). This is a different algorithm from getSnrColor(snr:preset:) in the same file, which is already SNR-only. So today iOS has two signal functions that can disagree on the same reading.
Fix: use the actual noise floor, not guessed RSSI thresholds
GUVWAF's blocker for using RSSI was not knowing the noise floor. We have it: DeviceMetrics.noise_floor (protobufs/meshtastic/telemetry.proto:455, field 15, int32, dBm — noiseFloor in telemetry.pb.swift) is transmitted as part of a node's Local Stats telemetry (metricsType == 4 — NodeInfoEntityExtension.swift's latestLocalStats/hasLocalStats). This is the receiving node's own radio noise floor, not a per-packet value.
Use it:
- When the connected/receiving node has a recent Local Stats reading, compute the actual link margin as
rssi - noiseFloor instead of comparing RSSI to the fixed -115/-120/-126 guesses.
- Combine that real margin with the existing SNR-vs-preset-limit comparison (
getSnrColor's bands) to produce the quality tier — this makes iOS's rating more accurate than Android's SNR-only model, not just a port of it.
- Fallback: when Local Stats /
noise_floor isn't available for the connected node (absent or stale), fall back to SNR-only, matching Android's determineSignalQuality exactly (drop the guessed fixed RSSI thresholds entirely — don't keep them as the fallback, since they're the inaccurate thing being replaced).
- Unify
getLoRaSignalStrength() and getSnrColor() so the bar indicator and the SNR text color can never disagree on the same reading (they can today).
Reference
Cross-platform alignment tracking issue: meshtastic/design#15. Related: Meshtastic-Apple#2041 (separate bug — wrong SNR floor for LongSlow), found during the same audit.
Background
Per meshtastic/design#15, Android hit the same cross-platform signal-quality question and settled on SNR-only rating (RSSI still displayed, just not used to determine the quality tier). From Meshtastic-Android#5446 (@GUVWAF, Android maintainer):
Android went with removing RSSI from the rating entirely (Meshtastic-Android#5903). iOS should do better than that, not just match it — see below.
Current iOS behavior
Meshtastic/Views/Helpers/LoRaSignalStrengthIndicator.swift'sgetLoRaSignalStrength(snr:rssi:preset:)blends fixed, guessed RSSI thresholds (-115/-120/-126) together with the SNR-vs-preset-limit comparison to decide the 4-tier bar rating (None/Bad/Fair/Good). This is a different algorithm fromgetSnrColor(snr:preset:)in the same file, which is already SNR-only. So today iOS has two signal functions that can disagree on the same reading.Fix: use the actual noise floor, not guessed RSSI thresholds
GUVWAF's blocker for using RSSI was not knowing the noise floor. We have it:
DeviceMetrics.noise_floor(protobufs/meshtastic/telemetry.proto:455, field 15,int32, dBm —noiseFloorintelemetry.pb.swift) is transmitted as part of a node's Local Stats telemetry (metricsType == 4—NodeInfoEntityExtension.swift'slatestLocalStats/hasLocalStats). This is the receiving node's own radio noise floor, not a per-packet value.Use it:
rssi - noiseFloorinstead of comparing RSSI to the fixed -115/-120/-126 guesses.getSnrColor's bands) to produce the quality tier — this makes iOS's rating more accurate than Android's SNR-only model, not just a port of it.noise_floorisn't available for the connected node (absent or stale), fall back to SNR-only, matching Android'sdetermineSignalQualityexactly (drop the guessed fixed RSSI thresholds entirely — don't keep them as the fallback, since they're the inaccurate thing being replaced).getLoRaSignalStrength()andgetSnrColor()so the bar indicator and the SNR text color can never disagree on the same reading (they can today).Reference
Cross-platform alignment tracking issue: meshtastic/design#15. Related: Meshtastic-Apple#2041 (separate bug — wrong SNR floor for LongSlow), found during the same audit.