wip(mesh): parse MeshPacket rx_snr/rx_rssi fields (Meshtastic backlog #14, part 1/many)

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 <noreply@anthropic.com>
This commit is contained in:
archipelago 2026-06-30 22:27:54 -04:00
parent 0eb5c258f5
commit dfca007949

View File

@ -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<Vec<u8>>,
/// 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<f32>,
/// MeshPacket.rx_rssi (field 12, int32) — received signal strength in dBm.
rx_rssi: Option<i32>,
}
fn parse_mesh_packet(data: &[u8]) -> Option<ParsedPacket> {
@ -1458,6 +1464,8 @@ fn parse_mesh_packet(data: &[u8]) -> Option<ParsedPacket> {
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<ParsedPacket> {
(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<ParsedPacket> {
rx_time,
pki_encrypted,
public_key,
rx_snr,
rx_rssi,
})
}