1use crate::errors::NmeaSentenceError;
2use crate::parsers;
3use crate::sentences::{GeneralSentence, SentenceType};
4
5macro_rules! status {
6 ($($name:ident, $type:ty : [$($input:tt => $status:ident),+ error: $error:ident]),+) => {
7 #[derive(Debug, Clone, Copy, PartialEq)]
8 pub enum StatusParsingError {
9 $(
10 $error,
11 )+
12 }
13 $(
14 #[derive(Debug, Clone, Copy, PartialEq)]
15 pub enum $name {
16 $(
17 $status,
18 )+
19 }
20
21 impl $name {
22 #[allow(unused)]
23 pub (crate) fn try_from<'a>(num: $type) -> Result<Self, NmeaSentenceError<'a>> {
24 match num {
25 $(
26 $input => Ok($name::$status),
27 )+
28 _ => Err(NmeaSentenceError::StatusParsingError(StatusParsingError::$error)),
29 }
30 }
31 }
32 )+
33 }
34}
35
36status! {
37 RmStatus, char: [
38 'A' => Active,
39 'V' => Warning,
40 'P' => Precise
41 error: RmStatusError
42 ],
43 LatitudeDirection, char: [
44 'N' => North,
45 'S' => South
46 error: LatitudeDirectionError
47 ],
48 LongitudeDirection, char: [
49 'E' => East,
50 'W' => West
51 error: LongitudeDirectionError
52 ],
53 GpsQuality, u8: [
54 0 => FixNotAvailable,
55 1 => Fix,
56 2 => DifferentialFix
57 error: GpsQualityError
58 ],
59 GllStatus, char: [
60 'A' => DataValid,
61 'V' => DataInvalid,
62 'P' => Precise
63 error: GllStatusError
64 ],
65 GsaMode, u8: [
66 1 => FixNotAvailable,
67 2 => Fix2D,
68 3 => Fix3D
69 error: GsaModeError
70 ],
71 GsaSelectionMode, char: [
72 'M' => Manual,
73 'A' => Automatic
74 error: GsaSelectionModeError
75 ],
76 SteerDirection, char: [
77 'L' => Left,
78 'R' => Right
79 error: SteerDirectionError
80 ],
81 ArrivalStatus, char: [
82 'A' => Arrived,
83 'V' => NotArrived
84 error: ArrivalStatusError
85 ],
86 RteMode, char: [
87 'c' => CompleteRoute,
88 'w' => WorkingRoute
89 error: RteModeError
90 ],
91 DataValidity, char: [
92 'A' => DataValid
93 error: DataValidityError
94 ],
95 GnsMode, char: [
96 'N' => NoFix,
97 'A' => AutonomousFix,
98 'D' => DifferentialFix,
99 'P' => Precise,
100 'R' => RealTime,
101 'F' => FloatRTK,
102 'E' => Estimated,
103 'M' => Manual,
104 'S' => Simulator
105 error: GnsModeError
106 ]
107}
108
109#[derive(Debug, Clone, PartialEq)]
112pub enum SentenceData<'a> {
113 AAM(AamData),
114 ABK(AbkData),
115 ACK(AckData),
116 ALM(AlmData),
117 APA(ApaData),
118 APB(ApbData),
119 BEC(BecData),
120 BOD(BodData<'a>),
121 BWC(BwcData<'a>),
122 BWR(BwrData),
123 BWW(BwwData),
124 DBK(DbkData),
125 DBS(DbsData),
126 DBT(DbtData),
127 DCN(DcnData),
128 DPT(DptData),
129 DTM(DtmData),
130 FSI(FsiData),
131 GBS(GbsData),
132 GGA(GgaData),
133 GLC(GlcData),
134 GLL(GllData),
135 GNS(GnsData),
136 GRS(GrsData),
137 GST(GstData),
138 GSA(GsaData),
139 GSV(GsvData),
140 GTD(GtdData),
141 GXA(GxaData),
142 HDG(HdgData),
143 HDM(HdmData),
144 HDT(HdtData),
145 HSC(HscData),
146 LCD(LcdData),
147 MSK(MskData),
148 MTW(MtwData),
149 MWV(MwvData),
150 OLN(OlnData),
151 OSD(OsdData),
152 ROO(RooData),
153 RMA(RmaData),
154 RMB(RmbData<'a>),
155 RMC(RmcData),
156 ROT(RotData),
157 RPM(RpmData),
158 RSA(RsaData),
159 RSD(RsdData),
160 RTE(RteData),
161 SFI(SfiData),
162 STN(StnData),
163 TLL(TllData),
164 TTM(TtmData),
165 VBW(VbwData),
166 VDR(VdrData),
167 VHW(VhwData),
168 VLW(VlwData),
169 VPW(VpwData),
170 VTG(VtgData),
171 VWR(VwrData),
172 WCV(WcvData),
173 WNC(WncData),
174 WPL(WplData<'a>),
175 XDR(XdrData),
176 XTE(XteData),
177 XTR(XtrData),
178 ZDA(ZdaData),
179 ZFO(ZfoData),
180 ZTG(ZtgData),
181}
182
183#[derive(Debug, Clone, Copy, PartialEq)]
184pub struct GpsTime {
186 pub hour: u8,
187 pub minute: u8,
188 pub second: f32,
189}
190
191#[derive(Debug, Clone, Copy, PartialEq)]
192pub struct GpsPosition {
194 pub lat: f32,
195 pub lat_dir: LatitudeDirection,
196 pub lon: f32,
197 pub lon_dir: LongitudeDirection,
198}
199
200#[derive(Debug, Clone, Copy, PartialEq)]
201pub struct GpsDate {
203 pub day: u8,
204 pub month: u8,
205 pub year: u64,
206}
207
208#[derive(Debug, Clone, Copy, PartialEq)]
209pub struct GsvSatellite {
211 pub sat_id: Option<u8>,
212 pub elevation: Option<f32>,
213 pub true_azimuth: Option<f32>,
214 pub snr: Option<u8>,
215}
216
217#[derive(Debug, Clone, Copy, PartialEq)]
218pub struct AamData {}
219#[derive(Debug, Clone, Copy, PartialEq)]
220pub struct AbkData {}
221#[derive(Debug, Clone, Copy, PartialEq)]
222pub struct AckData {}
223#[derive(Debug, Clone, Copy, PartialEq)]
224pub struct AlmData {}
225#[derive(Debug, Clone, Copy, PartialEq)]
226pub struct ApaData {}
227#[derive(Debug, Clone, Copy, PartialEq)]
228pub struct ApbData {}
229#[derive(Debug, Clone, Copy, PartialEq)]
230pub struct BecData {}
231#[derive(Debug, Clone, Copy, PartialEq)]
232pub struct BodData<'a> {
233 pub bearing_true: Option<f32>,
234 pub bearing_magnetic: Option<f32>,
235 pub to_waypoint: Option<&'a [u8]>,
236 pub from_waypoint: Option<&'a [u8]>,
237}
238#[derive(Debug, Clone, Copy, PartialEq)]
239pub struct BwcData<'a> {
240 pub time: Option<GpsTime>,
241 pub waypoint_position: GpsPosition,
242 pub bearing_true: Option<f32>,
243 pub bearing_magnetic: Option<f32>,
244 pub nautical_miles: Option<f32>,
245 pub waypoint: Option<&'a [u8]>,
246}
247#[derive(Debug, Clone, Copy, PartialEq)]
248pub struct BwrData {}
249#[derive(Debug, Clone, Copy, PartialEq)]
250pub struct BwwData {}
251#[derive(Debug, Clone, Copy, PartialEq)]
252pub struct DbkData {}
253#[derive(Debug, Clone, Copy, PartialEq)]
254pub struct DbsData {}
255#[derive(Debug, Clone, Copy, PartialEq)]
256pub struct DbtData {}
257#[derive(Debug, Clone, Copy, PartialEq)]
258pub struct DcnData {}
259#[derive(Debug, Clone, Copy, PartialEq)]
260pub struct DptData {}
261#[derive(Debug, Clone, Copy, PartialEq)]
262pub struct DtmData {}
263#[derive(Debug, Clone, Copy, PartialEq)]
264pub struct FsiData {}
265#[derive(Debug, Clone, Copy, PartialEq)]
266pub struct GbsData {
267 pub time: Option<GpsTime>,
268 pub lat_error: Option<f32>,
269 pub lon_error: Option<f32>,
270 pub alt_error: Option<f32>,
271 pub most_likely_failed_sat: Option<u8>,
272 pub missed_probability: Option<f32>,
273 pub bias_estimate: Option<f32>,
274 pub bias_standard_deviation: Option<f32>,
275}
276#[derive(Debug, Clone, Copy, PartialEq)]
277pub struct GgaData {
278 pub time: Option<GpsTime>,
279 pub position: GpsPosition,
280 pub quality: Option<GpsQuality>,
281 pub sats_in_view: Option<u8>,
282 pub hdop: Option<f32>,
283 pub altitude: Option<f32>,
284 pub geoid_altitude: Option<f32>,
285 pub age_of_differential: Option<f32>,
286 pub differential_station_id: Option<u16>,
287}
288#[derive(Debug, Clone, Copy, PartialEq)]
289pub struct GlcData {}
290#[derive(Debug, Clone, Copy, PartialEq)]
291pub struct GllData {
292 pub position: GpsPosition,
293 pub time: Option<GpsTime>,
294 pub status: Option<GllStatus>,
295}
296#[cfg(feature = "alloc")]
297#[derive(Debug, Clone, PartialEq)]
298pub struct GnsData {
299 pub time: Option<GpsTime>,
300 pub position: GpsPosition,
301 pub mode: Option<alloc::vec::Vec<GnsMode>>,
302 pub sats_in_use: Option<u8>,
303 pub hdop: Option<f32>,
304 pub orthometric_height: Option<f32>,
305 pub geoid_seperation: Option<f32>,
306 pub age_of_differential: Option<f32>,
307 pub differential_station_id: Option<u16>,
308}
309
310#[cfg(not(feature = "alloc"))]
311#[derive(Debug, Clone, Copy, PartialEq)]
312pub struct GnsData {}
313
314#[derive(Debug, Clone, Copy, PartialEq)]
315pub struct GrsData {}
316#[derive(Debug, Clone, Copy, PartialEq)]
317pub struct GstData {}
318#[derive(Debug, Clone, Copy, PartialEq)]
319pub struct GsaData {
320 pub selection_mode: Option<GsaSelectionMode>,
321 pub mode: Option<GsaMode>,
322 pub satellites: [Option<u8>; 12],
323 pub pdob: Option<f32>,
324 pub hdop: Option<f32>,
325 pub vdop: Option<f32>,
326}
327#[derive(Debug, Clone, Copy, PartialEq)]
328pub struct GtdData {}
329#[derive(Debug, Clone, Copy, PartialEq)]
330pub struct GsvData {
331 pub number_of_sentences: Option<u16>,
332 pub sentence_num: Option<u16>,
333 pub sats_in_view: Option<u8>,
334 pub sats_info: [Option<GsvSatellite>; 4],
335}
336#[derive(Debug, Clone, Copy, PartialEq)]
337pub struct GxaData {}
338#[derive(Debug, Clone, Copy, PartialEq)]
339pub struct HdgData {}
340#[derive(Debug, Clone, Copy, PartialEq)]
341pub struct HdmData {}
342#[derive(Debug, Clone, Copy, PartialEq)]
343pub struct HdtData {
344 pub heading_true: Option<f32>,
345}
346#[derive(Debug, Clone, Copy, PartialEq)]
347pub struct HscData {}
348#[derive(Debug, Clone, Copy, PartialEq)]
349pub struct LcdData {}
350#[derive(Debug, Clone, Copy, PartialEq)]
351pub struct MskData {}
352#[derive(Debug, Clone, Copy, PartialEq)]
353pub struct MtwData {}
354#[derive(Debug, Clone, Copy, PartialEq)]
355pub struct MwvData {}
356#[derive(Debug, Clone, Copy, PartialEq)]
357pub struct OlnData {}
358#[derive(Debug, Clone, Copy, PartialEq)]
359pub struct OsdData {}
360#[derive(Debug, Clone, Copy, PartialEq)]
361pub struct RooData {}
362#[derive(Debug, Clone, Copy, PartialEq)]
363pub struct RmaData {
364 pub status: Option<RmStatus>,
365 pub position: GpsPosition,
366 pub time_diff_a: Option<f32>,
367 pub time_diff_b: Option<f32>,
368 pub speed: Option<f32>,
369 pub heading: Option<f32>,
370 pub magnetic_variation: Option<f32>,
371 pub magnetic_direction: Option<LongitudeDirection>,
372}
373#[derive(Debug, Clone, Copy, PartialEq)]
374pub struct RmbData<'a> {
375 pub status: Option<RmStatus>,
376 pub cross_error: Option<f32>,
377 pub steer_direction: Option<SteerDirection>,
378 pub to_waypoint: Option<&'a [u8]>,
379 pub from_waypoint: Option<&'a [u8]>,
380 pub dest_position: GpsPosition,
381 pub range_to_dest: Option<f32>,
382 pub bearing: Option<f32>,
383 pub closing_velocity: Option<f32>,
384 pub arrival_status: Option<ArrivalStatus>,
385}
386#[derive(Debug, Clone, Copy, PartialEq)]
387pub struct RmcData {
388 pub time: Option<GpsTime>,
389 pub status: Option<RmStatus>,
390 pub position: GpsPosition,
391 pub speed: Option<f32>,
392 pub heading: Option<f32>,
393 pub date: Option<GpsDate>,
394 pub magnetic_variation: Option<f32>,
395 pub magnetic_direction: Option<LongitudeDirection>,
396}
397
398#[derive(Debug, Clone, Copy, PartialEq)]
399pub struct RotData {}
400#[derive(Debug, Clone, Copy, PartialEq)]
401pub struct RpmData {}
402#[derive(Debug, Clone, Copy, PartialEq)]
403pub struct RsaData {}
404#[derive(Debug, Clone, Copy, PartialEq)]
405pub struct RsdData {}
406#[derive(Debug, Clone, Copy, PartialEq)]
407pub struct RteData {}
408#[derive(Debug, Clone, Copy, PartialEq)]
409pub struct SfiData {}
410#[derive(Debug, Clone, Copy, PartialEq)]
411pub struct StnData {
412 pub talker_id: u8,
413}
414#[derive(Debug, Clone, Copy, PartialEq)]
415pub struct TllData {}
416#[derive(Debug, Clone, Copy, PartialEq)]
417pub struct TtmData {}
418#[derive(Debug, Clone, Copy, PartialEq)]
419pub struct VbwData {
420 pub lon_water_speed: Option<f32>,
421 pub transverse_water_speed: Option<f32>,
422 pub water_validity: Option<DataValidity>,
423 pub lon_ground_speed: Option<f32>,
424 pub transverse_ground_speed: Option<f32>,
425 pub ground_validity: Option<DataValidity>,
426}
427#[derive(Debug, Clone, Copy, PartialEq)]
428pub struct VdrData {}
429#[derive(Debug, Clone, Copy, PartialEq)]
430pub struct VhwData {}
431#[derive(Debug, Clone, Copy, PartialEq)]
432pub struct VlwData {}
433#[derive(Debug, Clone, Copy, PartialEq)]
434pub struct VpwData {}
435#[derive(Debug, Clone, Copy, PartialEq)]
436pub struct VtgData {
437 pub bearing_true: Option<f32>,
438 pub bearing_magnetic: Option<f32>,
439 pub speed_knots: Option<f32>,
440 pub speed_kmh: Option<f32>,
441}
442#[derive(Debug, Clone, Copy, PartialEq)]
443pub struct VwrData {}
444#[derive(Debug, Clone, Copy, PartialEq)]
445pub struct WcvData {}
446#[derive(Debug, Clone, Copy, PartialEq)]
447pub struct WncData {}
448#[derive(Debug, Clone, Copy, PartialEq)]
449pub struct WplData<'a> {
450 pub position: Option<GpsPosition>,
451 pub waypoint_name: Option<&'a [u8]>,
452}
453#[derive(Debug, Clone, Copy, PartialEq)]
454pub struct XdrData {}
455#[derive(Debug, Clone, Copy, PartialEq)]
456pub struct XteData {}
457#[derive(Debug, Clone, Copy, PartialEq)]
458pub struct XtrData {}
459#[derive(Debug, Clone, Copy, PartialEq)]
460pub struct ZdaData {}
461#[derive(Debug, Clone, Copy, PartialEq)]
462pub struct ZfoData {}
463#[derive(Debug, Clone, Copy, PartialEq)]
464pub struct ZtgData {}
465
466macro_rules! sentence_parse_generator {
467 ($sentence:ident : [$($TYPE:ident => $function:path,)+]) => {
468 match $sentence.sentence_type {
469 $(
470 SentenceType::$TYPE => Ok(SentenceData::$TYPE(parse_result_to_data($function($sentence.data))?)),
471 )+
472 _ => Err(NmeaSentenceError::TypeNotImplementedError($sentence.sentence_type)),
473 }
474 }
475}
476
477fn parse_result_to_data<'a, Data>(
478 parse_result: Result<(&'a [u8], Data), nom::Err<(&'a [u8], nom::error::ErrorKind)>>,
479) -> Result<Data, NmeaSentenceError<'a>> {
480 match parse_result {
481 Ok(value) => Ok(value.1),
482 Err(val) => Err(NmeaSentenceError::DataParsingError(val)),
483 }
484}
485
486pub(crate) fn parse_sentence_data<'a>(
487 general_sentence: GeneralSentence<'a>,
488) -> Result<SentenceData, NmeaSentenceError<'a>> {
489 sentence_parse_generator!(
490 general_sentence: [
491 BOD => parsers::bod::parse_bod,
499 BWC => parsers::bwc::parse_bwc,
500 GBS => parsers::gbs::parse_gbs,
510 GGA => parsers::gga::parse_gga,
511 GLL => parsers::gll::parse_gll,
513 GNS => parsers::gns::parse_gns,
514 GSA => parsers::gsa::parse_gsa,
517 GSV => parsers::gsv::parse_gsv,
518 HDT => parsers::hdt::parse_hdt,
523 RMA => parsers::rma::parse_rma,
532 RMB => parsers::rmb::parse_rmb,
533 RMC => parsers::rmc::parse_rmc,
534 STN => parsers::stn::parse_stn,
541 VBW => parsers::vbw::parse_vbw,
544 VTG => parsers::vtg::parse_vtg,
549 WPL => parsers::wpl::parse_wpl,
553 ]
560 )
561}