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, }) }