sidereon_core/rtcm/
station.rs1use crate::error::{Error, Result};
15
16use super::bits::{BitReader, BitWriter};
17
18const ECEF_SCALE_M: f64 = 0.0001;
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub struct StationCoordinates {
24 pub message_number: u16,
26 pub reference_station_id: u16,
28 pub itrf_realization_year: u8,
30 pub gps_indicator: bool,
32 pub glonass_indicator: bool,
34 pub galileo_indicator: bool,
36 pub reference_station_indicator: bool,
38 pub ecef_x: i64,
40 pub single_receiver_oscillator: bool,
42 pub reserved: bool,
44 pub ecef_y: i64,
46 pub quarter_cycle_indicator: u8,
48 pub ecef_z: i64,
50 pub antenna_height: Option<u16>,
53}
54
55impl StationCoordinates {
56 pub fn x_m(&self) -> f64 {
58 self.ecef_x as f64 * ECEF_SCALE_M
59 }
60
61 pub fn y_m(&self) -> f64 {
63 self.ecef_y as f64 * ECEF_SCALE_M
64 }
65
66 pub fn z_m(&self) -> f64 {
68 self.ecef_z as f64 * ECEF_SCALE_M
69 }
70
71 pub fn antenna_height_m(&self) -> Option<f64> {
73 self.antenna_height.map(|h| f64::from(h) * ECEF_SCALE_M)
74 }
75
76 pub fn decode(body: &[u8]) -> Result<Self> {
78 let mut r = BitReader::new(body);
79 let message_number = r.u(12)? as u16;
80 if message_number != 1005 && message_number != 1006 {
81 return Err(Error::Parse(format!(
82 "message {message_number} is not station coordinates 1005/1006"
83 )));
84 }
85 let reference_station_id = r.u(12)? as u16;
86 let itrf_realization_year = r.u(6)? as u8;
87 let gps_indicator = r.flag()?;
88 let glonass_indicator = r.flag()?;
89 let galileo_indicator = r.flag()?;
90 let reference_station_indicator = r.flag()?;
91 let ecef_x = r.i(38)?;
92 let single_receiver_oscillator = r.flag()?;
93 let reserved = r.flag()?;
94 let ecef_y = r.i(38)?;
95 let quarter_cycle_indicator = r.u(2)? as u8;
96 let ecef_z = r.i(38)?;
97 let antenna_height = if message_number == 1006 {
98 Some(r.u(16)? as u16)
99 } else {
100 None
101 };
102
103 Ok(Self {
104 message_number,
105 reference_station_id,
106 itrf_realization_year,
107 gps_indicator,
108 glonass_indicator,
109 galileo_indicator,
110 reference_station_indicator,
111 ecef_x,
112 single_receiver_oscillator,
113 reserved,
114 ecef_y,
115 quarter_cycle_indicator,
116 ecef_z,
117 antenna_height,
118 })
119 }
120
121 pub fn encode(&self) -> Vec<u8> {
123 let mut w = BitWriter::new();
124 w.push_u(u64::from(self.message_number), 12);
125 w.push_u(u64::from(self.reference_station_id), 12);
126 w.push_u(u64::from(self.itrf_realization_year), 6);
127 w.push_flag(self.gps_indicator);
128 w.push_flag(self.glonass_indicator);
129 w.push_flag(self.galileo_indicator);
130 w.push_flag(self.reference_station_indicator);
131 w.push_i(self.ecef_x, 38);
132 w.push_flag(self.single_receiver_oscillator);
133 w.push_flag(self.reserved);
134 w.push_i(self.ecef_y, 38);
135 w.push_u(u64::from(self.quarter_cycle_indicator), 2);
136 w.push_i(self.ecef_z, 38);
137 if let Some(height) = self.antenna_height {
138 w.push_u(u64::from(height), 16);
139 }
140 w.into_bytes()
141 }
142}