Skip to main content

sidereon_core/rtcm/
antenna.rs

1//! RTCM 3 antenna and receiver descriptor messages 1007, 1008, and 1033.
2//!
3//! These messages carry the human-readable equipment strings a receiver needs
4//! to apply the correct antenna calibration (RTCM 10403.3 Tables 3.5-11,
5//! 3.5-12, 3.5-31):
6//!
7//!   * **1007** - antenna descriptor and setup id.
8//!   * **1008** - 1007 plus the antenna serial number.
9//!   * **1033** - 1008 plus the receiver type, firmware version, and serial
10//!     number.
11//!
12//! Each string is length-prefixed by an 8-bit character count followed by that
13//! many 8-bit characters (DF030, DF033, DF228, DF230, DF232). The counts are
14//! reconstructed from the string lengths on encode, so the body round-trips.
15
16use crate::error::{Error, Result};
17
18use super::bits::{BitReader, BitWriter};
19use super::DecodeResult;
20
21/// A decoded antenna / receiver descriptor message (1007, 1008, or 1033).
22#[derive(Clone, Debug, PartialEq, Eq)]
23pub struct AntennaDescriptor {
24    /// 1007, 1008, or 1033.
25    pub message_number: u16,
26    /// Reference station identifier (DF003).
27    pub reference_station_id: u16,
28    /// Antenna descriptor string (DF030).
29    pub antenna_descriptor: String,
30    /// Antenna setup id (DF031).
31    pub antenna_setup_id: u8,
32    /// Antenna serial number (DF033). Present for 1008 and 1033.
33    pub antenna_serial_number: Option<String>,
34    /// Receiver type descriptor (DF228). Present for 1033.
35    pub receiver_type: Option<String>,
36    /// Receiver firmware version (DF230). Present for 1033.
37    pub receiver_firmware_version: Option<String>,
38    /// Receiver serial number (DF232). Present for 1033.
39    pub receiver_serial_number: Option<String>,
40}
41
42impl AntennaDescriptor {
43    /// Decode a 1007 / 1008 / 1033 body (without the transport frame).
44    pub fn decode(body: &[u8]) -> Result<Self> {
45        Self::decode_inner(body).map_err(Into::into)
46    }
47
48    pub(crate) fn decode_inner(body: &[u8]) -> DecodeResult<Self> {
49        let mut r = BitReader::new(body);
50        let message_number = r.u(12)? as u16;
51        if !matches!(message_number, 1007 | 1008 | 1033) {
52            return Err(Error::Parse(format!(
53                "message {message_number} is not an antenna descriptor 1007/1008/1033"
54            ))
55            .into());
56        }
57        let reference_station_id = r.u(12)? as u16;
58        let antenna_descriptor = read_string(&mut r)?;
59        let antenna_setup_id = r.u(8)? as u8;
60
61        let mut descriptor = Self {
62            message_number,
63            reference_station_id,
64            antenna_descriptor,
65            antenna_setup_id,
66            antenna_serial_number: None,
67            receiver_type: None,
68            receiver_firmware_version: None,
69            receiver_serial_number: None,
70        };
71
72        if matches!(message_number, 1008 | 1033) {
73            descriptor.antenna_serial_number = Some(read_string(&mut r)?);
74        }
75        if message_number == 1033 {
76            descriptor.receiver_type = Some(read_string(&mut r)?);
77            descriptor.receiver_firmware_version = Some(read_string(&mut r)?);
78            descriptor.receiver_serial_number = Some(read_string(&mut r)?);
79        }
80
81        Ok(descriptor)
82    }
83
84    /// Encode this descriptor body (without the transport frame).
85    pub fn encode(&self) -> Vec<u8> {
86        let mut w = BitWriter::new();
87        w.push_u(u64::from(self.message_number), 12);
88        w.push_u(u64::from(self.reference_station_id), 12);
89        write_string(&mut w, &self.antenna_descriptor);
90        w.push_u(u64::from(self.antenna_setup_id), 8);
91        if matches!(self.message_number, 1008 | 1033) {
92            write_string(&mut w, self.antenna_serial_number.as_deref().unwrap_or(""));
93        }
94        if self.message_number == 1033 {
95            write_string(&mut w, self.receiver_type.as_deref().unwrap_or(""));
96            write_string(
97                &mut w,
98                self.receiver_firmware_version.as_deref().unwrap_or(""),
99            );
100            write_string(&mut w, self.receiver_serial_number.as_deref().unwrap_or(""));
101        }
102        w.into_bytes()
103    }
104}
105
106/// Read an 8-bit-counted run of 8-bit characters as a string.
107fn read_string(r: &mut BitReader<'_>) -> DecodeResult<String> {
108    let count = r.u(8)? as usize;
109    let mut s = String::with_capacity(count);
110    for _ in 0..count {
111        s.push(r.u(8)? as u8 as char);
112    }
113    Ok(s)
114}
115
116/// Write a string as an 8-bit count followed by its 8-bit characters.
117fn write_string(w: &mut BitWriter, s: &str) {
118    let bytes = s.as_bytes();
119    w.push_u(bytes.len() as u64, 8);
120    for &b in bytes {
121        w.push_u(u64::from(b), 8);
122    }
123}