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};
19
20/// A decoded antenna / receiver descriptor message (1007, 1008, or 1033).
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct AntennaDescriptor {
23    /// 1007, 1008, or 1033.
24    pub message_number: u16,
25    /// Reference station identifier (DF003).
26    pub reference_station_id: u16,
27    /// Antenna descriptor string (DF030).
28    pub antenna_descriptor: String,
29    /// Antenna setup id (DF031).
30    pub antenna_setup_id: u8,
31    /// Antenna serial number (DF033). Present for 1008 and 1033.
32    pub antenna_serial_number: Option<String>,
33    /// Receiver type descriptor (DF228). Present for 1033.
34    pub receiver_type: Option<String>,
35    /// Receiver firmware version (DF230). Present for 1033.
36    pub receiver_firmware_version: Option<String>,
37    /// Receiver serial number (DF232). Present for 1033.
38    pub receiver_serial_number: Option<String>,
39}
40
41impl AntennaDescriptor {
42    /// Decode a 1007 / 1008 / 1033 body (without the transport frame).
43    pub fn decode(body: &[u8]) -> Result<Self> {
44        let mut r = BitReader::new(body);
45        let message_number = r.u(12)? as u16;
46        if !matches!(message_number, 1007 | 1008 | 1033) {
47            return Err(Error::Parse(format!(
48                "message {message_number} is not an antenna descriptor 1007/1008/1033"
49            )));
50        }
51        let reference_station_id = r.u(12)? as u16;
52        let antenna_descriptor = read_string(&mut r)?;
53        let antenna_setup_id = r.u(8)? as u8;
54
55        let mut descriptor = Self {
56            message_number,
57            reference_station_id,
58            antenna_descriptor,
59            antenna_setup_id,
60            antenna_serial_number: None,
61            receiver_type: None,
62            receiver_firmware_version: None,
63            receiver_serial_number: None,
64        };
65
66        if matches!(message_number, 1008 | 1033) {
67            descriptor.antenna_serial_number = Some(read_string(&mut r)?);
68        }
69        if message_number == 1033 {
70            descriptor.receiver_type = Some(read_string(&mut r)?);
71            descriptor.receiver_firmware_version = Some(read_string(&mut r)?);
72            descriptor.receiver_serial_number = Some(read_string(&mut r)?);
73        }
74
75        Ok(descriptor)
76    }
77
78    /// Encode this descriptor body (without the transport frame).
79    pub fn encode(&self) -> Vec<u8> {
80        let mut w = BitWriter::new();
81        w.push_u(u64::from(self.message_number), 12);
82        w.push_u(u64::from(self.reference_station_id), 12);
83        write_string(&mut w, &self.antenna_descriptor);
84        w.push_u(u64::from(self.antenna_setup_id), 8);
85        if matches!(self.message_number, 1008 | 1033) {
86            write_string(&mut w, self.antenna_serial_number.as_deref().unwrap_or(""));
87        }
88        if self.message_number == 1033 {
89            write_string(&mut w, self.receiver_type.as_deref().unwrap_or(""));
90            write_string(
91                &mut w,
92                self.receiver_firmware_version.as_deref().unwrap_or(""),
93            );
94            write_string(&mut w, self.receiver_serial_number.as_deref().unwrap_or(""));
95        }
96        w.into_bytes()
97    }
98}
99
100/// Read an 8-bit-counted run of 8-bit characters as a string.
101fn read_string(r: &mut BitReader<'_>) -> Result<String> {
102    let count = r.u(8)? as usize;
103    let mut s = String::with_capacity(count);
104    for _ in 0..count {
105        s.push(r.u(8)? as u8 as char);
106    }
107    Ok(s)
108}
109
110/// Write a string as an 8-bit count followed by its 8-bit characters.
111fn write_string(w: &mut BitWriter, s: &str) {
112    let bytes = s.as_bytes();
113    w.push_u(bytes.len() as u64, 8);
114    for &b in bytes {
115        w.push_u(u64::from(b), 8);
116    }
117}