From dfca0079495d933e6393ebe636e42fcf8dd03bdd Mon Sep 17 00:00:00 2001 From: archipelago Date: Tue, 30 Jun 2026 22:27:54 -0400 Subject: [PATCH] wip(mesh): parse MeshPacket rx_snr/rx_rssi fields (Meshtastic backlog #14, part 1/many) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Field numbers confirmed against the canonical meshtastic/protobufs mesh.proto (rx_snr=8 float, rx_rssi=12 int32), not guessed. Not yet threaded through to ParsedContact/MeshPeer/mesh.peers — that's the next step. Part of the Meshtastic 1.8.0 backlog plan (RSSI/SNR indicator, peer-location map, Device tab, provisioning robustness, onboarding modal) — see .claude/plans/floofy-riding-seahorse.md for the full plan. Co-Authored-By: Claude Sonnet 5 --- core/archipelago/src/mesh/meshtastic.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/archipelago/src/mesh/meshtastic.rs b/core/archipelago/src/mesh/meshtastic.rs index 3fcaeedf..cffd34ed 100644 --- a/core/archipelago/src/mesh/meshtastic.rs +++ b/core/archipelago/src/mesh/meshtastic.rs @@ -1446,6 +1446,12 @@ struct ParsedPacket { pki_encrypted: bool, /// MeshPacket.public_key (field 16): the sender's key, carried on PKC DMs. public_key: Option>, + /// MeshPacket.rx_snr (field 8, float) — signal-to-noise ratio in dB, as + /// measured by the receiving radio. Field numbers confirmed against the + /// canonical `meshtastic/protobufs` mesh.proto, not guessed. + rx_snr: Option, + /// MeshPacket.rx_rssi (field 12, int32) — received signal strength in dBm. + rx_rssi: Option, } fn parse_mesh_packet(data: &[u8]) -> Option { @@ -1458,6 +1464,8 @@ fn parse_mesh_packet(data: &[u8]) -> Option { let mut rx_time = None; let mut pki_encrypted = false; let mut public_key = None; + let mut rx_snr = None; + let mut rx_rssi = None; while idx < data.len() { let (field, value, next) = next_field(data, idx)?; idx = next; @@ -1468,6 +1476,10 @@ fn parse_mesh_packet(data: &[u8]) -> Option { (4, FieldValue::Bytes(b)) => decoded = Some(b), (6, FieldValue::Fixed32(v)) => id = Some(v), (7, FieldValue::Fixed32(v)) if v != 0 => rx_time = Some(v), + // float wire type (5) decodes as a 32-bit fixed value; reinterpret + // the bits as f32 rather than treating them as an integer. + (8, FieldValue::Fixed32(v)) => rx_snr = Some(f32::from_bits(v)), + (12, FieldValue::Varint(v)) => rx_rssi = Some(v as i32), (16, FieldValue::Bytes(b)) if !b.is_empty() => public_key = Some(b.to_vec()), (17, FieldValue::Varint(v)) => pki_encrypted = v != 0, _ => {} @@ -1496,6 +1508,8 @@ fn parse_mesh_packet(data: &[u8]) -> Option { rx_time, pki_encrypted, public_key, + rx_snr, + rx_rssi, }) }