Skip to main content

sbp/messages/
navigation.rs

1// Copyright (C) 2015-2021 Swift Navigation Inc.
2// Contact: https://support.swiftnav.com
3//
4// This source is subject to the license found in the file 'LICENSE' which must
5// be distributed together with this source. All other rights reserved.
6//
7// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
8// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
9// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
10
11//****************************************************************************
12// Automatically generated from yaml/swiftnav/sbp/navigation.yaml
13// with generate.py. Please do not hand edit!
14//****************************************************************************/
15//! Geodetic navigation messages reporting GPS time, position, velocity, and
16//! baseline position solutions. For position solutions, these messages define
17//! several different position solutions: single-point (SPP), RTK, and pseudo-
18//! absolute position solutions.
19//!
20//! The SPP is the standalone, absolute GPS position solution using only a
21//! single receiver. The RTK solution is the differential GPS solution, which
22//! can use either a fixed/integer or floating carrier phase ambiguity. The
23//! pseudo-absolute position solution uses a user-provided, well-surveyed base
24//! station position (if available) and the RTK solution in tandem.
25//!
26//! When the inertial navigation mode indicates that the IMU is used, all
27//! messages are reported in the vehicle body frame as defined by device
28//! settings.  By default, the vehicle body frame is configured to be
29//! coincident with the antenna phase center.  When there is no inertial
30//! navigation, the solution will be reported at the phase center of the
31//! antenna. There is no inertial navigation capability on Piksi Multi or
32//! Duro.
33//!
34//! The tow field, when valid, is most often the Time of Measurement. When
35//! this is the case, the 5th bit of flags is set to the default value of 0.
36//! When this is not the case, the tow may be a time of arrival or a local
37//! system timestamp, irrespective of the time reference (GPS Week or else),
38//! but not a Time of Measurement.
39pub use estimated_horizontal_error_ellipse::EstimatedHorizontalErrorEllipse;
40pub use msg_age_corrections::MsgAgeCorrections;
41pub use msg_baseline_ecef::MsgBaselineEcef;
42pub use msg_baseline_ecef_dep_a::MsgBaselineEcefDepA;
43pub use msg_baseline_heading_dep_a::MsgBaselineHeadingDepA;
44pub use msg_baseline_ned::MsgBaselineNed;
45pub use msg_baseline_ned_dep_a::MsgBaselineNedDepA;
46pub use msg_dops::MsgDops;
47pub use msg_dops_dep_a::MsgDopsDepA;
48pub use msg_gps_time::MsgGpsTime;
49pub use msg_gps_time_dep_a::MsgGpsTimeDepA;
50pub use msg_gps_time_gnss::MsgGpsTimeGnss;
51pub use msg_pos_ecef::MsgPosEcef;
52pub use msg_pos_ecef_cov::MsgPosEcefCov;
53pub use msg_pos_ecef_cov_gnss::MsgPosEcefCovGnss;
54pub use msg_pos_ecef_dep_a::MsgPosEcefDepA;
55pub use msg_pos_ecef_gnss::MsgPosEcefGnss;
56pub use msg_pos_llh::MsgPosLlh;
57pub use msg_pos_llh_acc::MsgPosLlhAcc;
58pub use msg_pos_llh_cov::MsgPosLlhCov;
59pub use msg_pos_llh_cov_gnss::MsgPosLlhCovGnss;
60pub use msg_pos_llh_dep_a::MsgPosLlhDepA;
61pub use msg_pos_llh_gnss::MsgPosLlhGnss;
62pub use msg_pose_relative::MsgPoseRelative;
63pub use msg_protection_level::MsgProtectionLevel;
64pub use msg_protection_level_dep_a::MsgProtectionLevelDepA;
65pub use msg_reference_frame_param::MsgReferenceFrameParam;
66pub use msg_utc_leap_second::MsgUtcLeapSecond;
67pub use msg_utc_time::MsgUtcTime;
68pub use msg_utc_time_gnss::MsgUtcTimeGnss;
69pub use msg_vel_body::MsgVelBody;
70pub use msg_vel_cog::MsgVelCog;
71pub use msg_vel_ecef::MsgVelEcef;
72pub use msg_vel_ecef_cov::MsgVelEcefCov;
73pub use msg_vel_ecef_cov_gnss::MsgVelEcefCovGnss;
74pub use msg_vel_ecef_dep_a::MsgVelEcefDepA;
75pub use msg_vel_ecef_gnss::MsgVelEcefGnss;
76pub use msg_vel_ned::MsgVelNed;
77pub use msg_vel_ned_cov::MsgVelNedCov;
78pub use msg_vel_ned_cov_gnss::MsgVelNedCovGnss;
79pub use msg_vel_ned_dep_a::MsgVelNedDepA;
80pub use msg_vel_ned_gnss::MsgVelNedGnss;
81
82pub mod estimated_horizontal_error_ellipse {
83    #![allow(unused_imports)]
84
85    use super::*;
86    use crate::messages::lib::*;
87    /// Horizontal estimated error ellipse
88    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89    #[allow(clippy::derive_partial_eq_without_eq)]
90    #[derive(Debug, PartialEq, Clone)]
91    pub struct EstimatedHorizontalErrorEllipse {
92        /// The semi major axis of the estimated horizontal error ellipse at the
93        /// user-configured confidence level; zero implies invalid.
94        #[cfg_attr(feature = "serde", serde(rename = "semi_major"))]
95        pub semi_major: f32,
96        /// The semi minor axis of the estimated horizontal error ellipse at the
97        /// user-configured confidence level; zero implies invalid.
98        #[cfg_attr(feature = "serde", serde(rename = "semi_minor"))]
99        pub semi_minor: f32,
100        /// The orientation of the semi major axis of the estimated horizontal error
101        /// ellipse with respect to North.
102        #[cfg_attr(feature = "serde", serde(rename = "orientation"))]
103        pub orientation: f32,
104    }
105
106    impl WireFormat for EstimatedHorizontalErrorEllipse {
107        const MIN_LEN: usize = <f32 as WireFormat>::MIN_LEN
108            + <f32 as WireFormat>::MIN_LEN
109            + <f32 as WireFormat>::MIN_LEN;
110        fn len(&self) -> usize {
111            WireFormat::len(&self.semi_major)
112                + WireFormat::len(&self.semi_minor)
113                + WireFormat::len(&self.orientation)
114        }
115        fn write<B: BufMut>(&self, buf: &mut B) {
116            WireFormat::write(&self.semi_major, buf);
117            WireFormat::write(&self.semi_minor, buf);
118            WireFormat::write(&self.orientation, buf);
119        }
120        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
121            EstimatedHorizontalErrorEllipse {
122                semi_major: WireFormat::parse_unchecked(buf),
123                semi_minor: WireFormat::parse_unchecked(buf),
124                orientation: WireFormat::parse_unchecked(buf),
125            }
126        }
127    }
128}
129
130pub mod msg_age_corrections {
131    #![allow(unused_imports)]
132
133    use super::*;
134    use crate::messages::lib::*;
135
136    /// Age of corrections
137    ///
138    /// This message reports the Age of the corrections used for the current
139    /// Differential solution.
140    ///
141    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
142    #[allow(clippy::derive_partial_eq_without_eq)]
143    #[derive(Debug, PartialEq, Clone)]
144    pub struct MsgAgeCorrections {
145        /// The message sender_id
146        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
147        pub sender_id: Option<u16>,
148        /// GPS Time of Week
149        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
150        pub tow: u32,
151        /// Age of the corrections (0xFFFF indicates invalid)
152        #[cfg_attr(feature = "serde", serde(rename = "age"))]
153        pub age: u16,
154    }
155
156    impl ConcreteMessage for MsgAgeCorrections {
157        const MESSAGE_TYPE: u16 = 528;
158        const MESSAGE_NAME: &'static str = "MSG_AGE_CORRECTIONS";
159    }
160
161    impl SbpMessage for MsgAgeCorrections {
162        fn message_name(&self) -> &'static str {
163            <Self as ConcreteMessage>::MESSAGE_NAME
164        }
165        fn message_type(&self) -> Option<u16> {
166            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
167        }
168        fn sender_id(&self) -> Option<u16> {
169            self.sender_id
170        }
171        fn set_sender_id(&mut self, new_id: u16) {
172            self.sender_id = Some(new_id);
173        }
174        fn encoded_len(&self) -> usize {
175            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
176        }
177        fn is_valid(&self) -> bool {
178            true
179        }
180        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
181            Ok(self)
182        }
183
184        #[cfg(feature = "swiftnav")]
185        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
186            let tow_s = (self.tow as f64) / 1000.0;
187            let gps_time = match time::GpsTime::new(0, tow_s) {
188                Ok(gps_time) => gps_time.tow(),
189                Err(e) => return Some(Err(e.into())),
190            };
191            Some(Ok(time::MessageTime::Rover(gps_time.into())))
192        }
193    }
194
195    impl FriendlyName for MsgAgeCorrections {
196        fn friendly_name() -> &'static str {
197            "AGE CORRECTIONS"
198        }
199    }
200
201    impl TryFrom<Sbp> for MsgAgeCorrections {
202        type Error = TryFromSbpError;
203        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
204            match msg {
205                Sbp::MsgAgeCorrections(m) => Ok(m),
206                _ => Err(TryFromSbpError(msg)),
207            }
208        }
209    }
210
211    impl WireFormat for MsgAgeCorrections {
212        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN + <u16 as WireFormat>::MIN_LEN;
213        fn len(&self) -> usize {
214            WireFormat::len(&self.tow) + WireFormat::len(&self.age)
215        }
216        fn write<B: BufMut>(&self, buf: &mut B) {
217            WireFormat::write(&self.tow, buf);
218            WireFormat::write(&self.age, buf);
219        }
220        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
221            MsgAgeCorrections {
222                sender_id: None,
223                tow: WireFormat::parse_unchecked(buf),
224                age: WireFormat::parse_unchecked(buf),
225            }
226        }
227    }
228}
229
230pub mod msg_baseline_ecef {
231    #![allow(unused_imports)]
232
233    use super::*;
234    use crate::messages::lib::*;
235
236    /// GNSS-only Baseline Position in ECEF
237    ///
238    /// This message reports the baseline solution in Earth Centered Earth Fixed
239    /// (ECEF) coordinates. This baseline is the relative vector distance from the
240    /// base station to the rover receiver. The full GPS time is given by the
241    /// preceding MSG_GPS_TIME with the matching time-of-week (tow).
242    ///
243    /// The values in this message are from GNSS measurements only.
244    ///
245    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
246    #[allow(clippy::derive_partial_eq_without_eq)]
247    #[derive(Debug, PartialEq, Clone)]
248    pub struct MsgBaselineEcef {
249        /// The message sender_id
250        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
251        pub sender_id: Option<u16>,
252        /// GPS Time of Week
253        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
254        pub tow: u32,
255        /// Baseline ECEF X coordinate
256        #[cfg_attr(feature = "serde", serde(rename = "x"))]
257        pub x: i32,
258        /// Baseline ECEF Y coordinate
259        #[cfg_attr(feature = "serde", serde(rename = "y"))]
260        pub y: i32,
261        /// Baseline ECEF Z coordinate
262        #[cfg_attr(feature = "serde", serde(rename = "z"))]
263        pub z: i32,
264        /// Position estimated standard deviation
265        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
266        pub accuracy: u16,
267        /// Number of satellites used in solution
268        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
269        pub n_sats: u8,
270        /// Status flags
271        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
272        pub flags: u8,
273    }
274
275    impl MsgBaselineEcef {
276        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
277        ///
278        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
279        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
280        /// or because new variants of `FixMode` were added.
281        pub fn fix_mode(&self) -> Result<FixMode, u8> {
282            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
283        }
284
285        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
286        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
287            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
288        }
289    }
290
291    impl ConcreteMessage for MsgBaselineEcef {
292        const MESSAGE_TYPE: u16 = 523;
293        const MESSAGE_NAME: &'static str = "MSG_BASELINE_ECEF";
294    }
295
296    impl SbpMessage for MsgBaselineEcef {
297        fn message_name(&self) -> &'static str {
298            <Self as ConcreteMessage>::MESSAGE_NAME
299        }
300        fn message_type(&self) -> Option<u16> {
301            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
302        }
303        fn sender_id(&self) -> Option<u16> {
304            self.sender_id
305        }
306        fn set_sender_id(&mut self, new_id: u16) {
307            self.sender_id = Some(new_id);
308        }
309        fn encoded_len(&self) -> usize {
310            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
311        }
312        fn is_valid(&self) -> bool {
313            true
314        }
315        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
316            Ok(self)
317        }
318
319        #[cfg(feature = "swiftnav")]
320        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
321            let tow_s = (self.tow as f64) / 1000.0;
322            let gps_time = match time::GpsTime::new(0, tow_s) {
323                Ok(gps_time) => gps_time.tow(),
324                Err(e) => return Some(Err(e.into())),
325            };
326            Some(Ok(time::MessageTime::Rover(gps_time.into())))
327        }
328    }
329
330    impl FriendlyName for MsgBaselineEcef {
331        fn friendly_name() -> &'static str {
332            "BASELINE ECEF"
333        }
334    }
335
336    impl TryFrom<Sbp> for MsgBaselineEcef {
337        type Error = TryFromSbpError;
338        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
339            match msg {
340                Sbp::MsgBaselineEcef(m) => Ok(m),
341                _ => Err(TryFromSbpError(msg)),
342            }
343        }
344    }
345
346    impl WireFormat for MsgBaselineEcef {
347        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
348            + <i32 as WireFormat>::MIN_LEN
349            + <i32 as WireFormat>::MIN_LEN
350            + <i32 as WireFormat>::MIN_LEN
351            + <u16 as WireFormat>::MIN_LEN
352            + <u8 as WireFormat>::MIN_LEN
353            + <u8 as WireFormat>::MIN_LEN;
354        fn len(&self) -> usize {
355            WireFormat::len(&self.tow)
356                + WireFormat::len(&self.x)
357                + WireFormat::len(&self.y)
358                + WireFormat::len(&self.z)
359                + WireFormat::len(&self.accuracy)
360                + WireFormat::len(&self.n_sats)
361                + WireFormat::len(&self.flags)
362        }
363        fn write<B: BufMut>(&self, buf: &mut B) {
364            WireFormat::write(&self.tow, buf);
365            WireFormat::write(&self.x, buf);
366            WireFormat::write(&self.y, buf);
367            WireFormat::write(&self.z, buf);
368            WireFormat::write(&self.accuracy, buf);
369            WireFormat::write(&self.n_sats, buf);
370            WireFormat::write(&self.flags, buf);
371        }
372        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
373            MsgBaselineEcef {
374                sender_id: None,
375                tow: WireFormat::parse_unchecked(buf),
376                x: WireFormat::parse_unchecked(buf),
377                y: WireFormat::parse_unchecked(buf),
378                z: WireFormat::parse_unchecked(buf),
379                accuracy: WireFormat::parse_unchecked(buf),
380                n_sats: WireFormat::parse_unchecked(buf),
381                flags: WireFormat::parse_unchecked(buf),
382            }
383        }
384    }
385
386    /// Fix mode
387    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
388    pub enum FixMode {
389        /// Invalid
390        Invalid = 0,
391
392        /// Differential GNSS (DGNSS)
393        DifferentialGnss = 2,
394
395        /// Float RTK
396        FloatRtk = 3,
397
398        /// Fixed RTK
399        FixedRtk = 4,
400    }
401
402    impl std::fmt::Display for FixMode {
403        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
404            match self {
405                FixMode::Invalid => f.write_str("Invalid"),
406                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
407                FixMode::FloatRtk => f.write_str("Float RTK"),
408                FixMode::FixedRtk => f.write_str("Fixed RTK"),
409            }
410        }
411    }
412
413    impl TryFrom<u8> for FixMode {
414        type Error = u8;
415        fn try_from(i: u8) -> Result<Self, u8> {
416            match i {
417                0 => Ok(FixMode::Invalid),
418                2 => Ok(FixMode::DifferentialGnss),
419                3 => Ok(FixMode::FloatRtk),
420                4 => Ok(FixMode::FixedRtk),
421                i => Err(i),
422            }
423        }
424    }
425}
426
427pub mod msg_baseline_ecef_dep_a {
428    #![allow(unused_imports)]
429
430    use super::*;
431    use crate::messages::lib::*;
432
433    /// Deprecated
434    ///
435    /// Deprecated.
436    ///
437    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
438    #[allow(clippy::derive_partial_eq_without_eq)]
439    #[derive(Debug, PartialEq, Clone)]
440    pub struct MsgBaselineEcefDepA {
441        /// The message sender_id
442        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
443        pub sender_id: Option<u16>,
444        /// GPS Time of Week
445        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
446        pub tow: u32,
447        /// Baseline ECEF X coordinate
448        #[cfg_attr(feature = "serde", serde(rename = "x"))]
449        pub x: i32,
450        /// Baseline ECEF Y coordinate
451        #[cfg_attr(feature = "serde", serde(rename = "y"))]
452        pub y: i32,
453        /// Baseline ECEF Z coordinate
454        #[cfg_attr(feature = "serde", serde(rename = "z"))]
455        pub z: i32,
456        /// Position accuracy estimate
457        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
458        pub accuracy: u16,
459        /// Number of satellites used in solution
460        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
461        pub n_sats: u8,
462        /// Status flags
463        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
464        pub flags: u8,
465    }
466
467    impl MsgBaselineEcefDepA {
468        /// Gets the [RaimRepairFlag][self::RaimRepairFlag] stored in the `flags` bitfield.
469        ///
470        /// Returns `Ok` if the bitrange contains a known `RaimRepairFlag` variant.
471        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
472        /// or because new variants of `RaimRepairFlag` were added.
473        pub fn raim_repair_flag(&self) -> Result<RaimRepairFlag, u8> {
474            get_bit_range!(self.flags, u8, u8, 4, 4).try_into()
475        }
476
477        /// Set the bitrange corresponding to the [RaimRepairFlag][RaimRepairFlag] of the `flags` bitfield.
478        pub fn set_raim_repair_flag(&mut self, raim_repair_flag: RaimRepairFlag) {
479            set_bit_range!(&mut self.flags, raim_repair_flag, u8, u8, 4, 4);
480        }
481
482        /// Gets the [RaimAvailabilityFlag][self::RaimAvailabilityFlag] stored in the `flags` bitfield.
483        ///
484        /// Returns `Ok` if the bitrange contains a known `RaimAvailabilityFlag` variant.
485        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
486        /// or because new variants of `RaimAvailabilityFlag` were added.
487        pub fn raim_availability_flag(&self) -> Result<RaimAvailabilityFlag, u8> {
488            get_bit_range!(self.flags, u8, u8, 3, 3).try_into()
489        }
490
491        /// Set the bitrange corresponding to the [RaimAvailabilityFlag][RaimAvailabilityFlag] of the `flags` bitfield.
492        pub fn set_raim_availability_flag(&mut self, raim_availability_flag: RaimAvailabilityFlag) {
493            set_bit_range!(&mut self.flags, raim_availability_flag, u8, u8, 3, 3);
494        }
495
496        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
497        ///
498        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
499        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
500        /// or because new variants of `FixMode` were added.
501        pub fn fix_mode(&self) -> Result<FixMode, u8> {
502            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
503        }
504
505        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
506        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
507            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
508        }
509    }
510
511    impl ConcreteMessage for MsgBaselineEcefDepA {
512        const MESSAGE_TYPE: u16 = 514;
513        const MESSAGE_NAME: &'static str = "MSG_BASELINE_ECEF_DEP_A";
514    }
515
516    impl SbpMessage for MsgBaselineEcefDepA {
517        fn message_name(&self) -> &'static str {
518            <Self as ConcreteMessage>::MESSAGE_NAME
519        }
520        fn message_type(&self) -> Option<u16> {
521            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
522        }
523        fn sender_id(&self) -> Option<u16> {
524            self.sender_id
525        }
526        fn set_sender_id(&mut self, new_id: u16) {
527            self.sender_id = Some(new_id);
528        }
529        fn encoded_len(&self) -> usize {
530            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
531        }
532        fn is_valid(&self) -> bool {
533            true
534        }
535        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
536            Ok(self)
537        }
538
539        #[cfg(feature = "swiftnav")]
540        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
541            let tow_s = (self.tow as f64) / 1000.0;
542            let gps_time = match time::GpsTime::new(0, tow_s) {
543                Ok(gps_time) => gps_time.tow(),
544                Err(e) => return Some(Err(e.into())),
545            };
546            Some(Ok(time::MessageTime::Rover(gps_time.into())))
547        }
548    }
549
550    impl FriendlyName for MsgBaselineEcefDepA {
551        fn friendly_name() -> &'static str {
552            "BASELINE ECEF DEP A"
553        }
554    }
555
556    impl TryFrom<Sbp> for MsgBaselineEcefDepA {
557        type Error = TryFromSbpError;
558        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
559            match msg {
560                Sbp::MsgBaselineEcefDepA(m) => Ok(m),
561                _ => Err(TryFromSbpError(msg)),
562            }
563        }
564    }
565
566    impl WireFormat for MsgBaselineEcefDepA {
567        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
568            + <i32 as WireFormat>::MIN_LEN
569            + <i32 as WireFormat>::MIN_LEN
570            + <i32 as WireFormat>::MIN_LEN
571            + <u16 as WireFormat>::MIN_LEN
572            + <u8 as WireFormat>::MIN_LEN
573            + <u8 as WireFormat>::MIN_LEN;
574        fn len(&self) -> usize {
575            WireFormat::len(&self.tow)
576                + WireFormat::len(&self.x)
577                + WireFormat::len(&self.y)
578                + WireFormat::len(&self.z)
579                + WireFormat::len(&self.accuracy)
580                + WireFormat::len(&self.n_sats)
581                + WireFormat::len(&self.flags)
582        }
583        fn write<B: BufMut>(&self, buf: &mut B) {
584            WireFormat::write(&self.tow, buf);
585            WireFormat::write(&self.x, buf);
586            WireFormat::write(&self.y, buf);
587            WireFormat::write(&self.z, buf);
588            WireFormat::write(&self.accuracy, buf);
589            WireFormat::write(&self.n_sats, buf);
590            WireFormat::write(&self.flags, buf);
591        }
592        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
593            MsgBaselineEcefDepA {
594                sender_id: None,
595                tow: WireFormat::parse_unchecked(buf),
596                x: WireFormat::parse_unchecked(buf),
597                y: WireFormat::parse_unchecked(buf),
598                z: WireFormat::parse_unchecked(buf),
599                accuracy: WireFormat::parse_unchecked(buf),
600                n_sats: WireFormat::parse_unchecked(buf),
601                flags: WireFormat::parse_unchecked(buf),
602            }
603        }
604    }
605
606    /// RAIM repair flag
607    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
608    pub enum RaimRepairFlag {
609        /// No repair
610        NoRepair = 0,
611
612        /// Solution came from RAIM repair
613        SolutionCameFromRaimRepair = 1,
614    }
615
616    impl std::fmt::Display for RaimRepairFlag {
617        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
618            match self {
619                RaimRepairFlag::NoRepair => f.write_str("No repair"),
620                RaimRepairFlag::SolutionCameFromRaimRepair => {
621                    f.write_str("Solution came from RAIM repair")
622                }
623            }
624        }
625    }
626
627    impl TryFrom<u8> for RaimRepairFlag {
628        type Error = u8;
629        fn try_from(i: u8) -> Result<Self, u8> {
630            match i {
631                0 => Ok(RaimRepairFlag::NoRepair),
632                1 => Ok(RaimRepairFlag::SolutionCameFromRaimRepair),
633                i => Err(i),
634            }
635        }
636    }
637
638    /// RAIM availability flag
639    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
640    pub enum RaimAvailabilityFlag {
641        /// RAIM check was explicitly disabled or unavailable
642        RaimCheckWasExplicitlyDisabledOrUnavailable = 0,
643
644        /// RAIM check was available
645        RaimCheckWasAvailable = 1,
646    }
647
648    impl std::fmt::Display for RaimAvailabilityFlag {
649        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
650            match self {
651                RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable => {
652                    f.write_str("RAIM check was explicitly disabled or unavailable")
653                }
654                RaimAvailabilityFlag::RaimCheckWasAvailable => {
655                    f.write_str("RAIM check was available")
656                }
657            }
658        }
659    }
660
661    impl TryFrom<u8> for RaimAvailabilityFlag {
662        type Error = u8;
663        fn try_from(i: u8) -> Result<Self, u8> {
664            match i {
665                0 => Ok(RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable),
666                1 => Ok(RaimAvailabilityFlag::RaimCheckWasAvailable),
667                i => Err(i),
668            }
669        }
670    }
671
672    /// Fix mode
673    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
674    pub enum FixMode {
675        /// Float RTK
676        FloatRtk = 0,
677
678        /// Fixed RTK
679        FixedRtk = 1,
680    }
681
682    impl std::fmt::Display for FixMode {
683        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
684            match self {
685                FixMode::FloatRtk => f.write_str("Float RTK"),
686                FixMode::FixedRtk => f.write_str("Fixed RTK"),
687            }
688        }
689    }
690
691    impl TryFrom<u8> for FixMode {
692        type Error = u8;
693        fn try_from(i: u8) -> Result<Self, u8> {
694            match i {
695                0 => Ok(FixMode::FloatRtk),
696                1 => Ok(FixMode::FixedRtk),
697                i => Err(i),
698            }
699        }
700    }
701}
702
703pub mod msg_baseline_heading_dep_a {
704    #![allow(unused_imports)]
705
706    use super::*;
707    use crate::messages::lib::*;
708
709    /// Deprecated
710    ///
711    /// Deprecated.
712    ///
713    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
714    #[allow(clippy::derive_partial_eq_without_eq)]
715    #[derive(Debug, PartialEq, Clone)]
716    pub struct MsgBaselineHeadingDepA {
717        /// The message sender_id
718        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
719        pub sender_id: Option<u16>,
720        /// GPS Time of Week
721        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
722        pub tow: u32,
723        /// Heading
724        #[cfg_attr(feature = "serde", serde(rename = "heading"))]
725        pub heading: u32,
726        /// Number of satellites used in solution
727        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
728        pub n_sats: u8,
729        /// Status flags
730        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
731        pub flags: u8,
732    }
733
734    impl MsgBaselineHeadingDepA {
735        /// Gets the [RaimRepairFlag][self::RaimRepairFlag] stored in the `flags` bitfield.
736        ///
737        /// Returns `Ok` if the bitrange contains a known `RaimRepairFlag` variant.
738        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
739        /// or because new variants of `RaimRepairFlag` were added.
740        pub fn raim_repair_flag(&self) -> Result<RaimRepairFlag, u8> {
741            get_bit_range!(self.flags, u8, u8, 4, 4).try_into()
742        }
743
744        /// Set the bitrange corresponding to the [RaimRepairFlag][RaimRepairFlag] of the `flags` bitfield.
745        pub fn set_raim_repair_flag(&mut self, raim_repair_flag: RaimRepairFlag) {
746            set_bit_range!(&mut self.flags, raim_repair_flag, u8, u8, 4, 4);
747        }
748
749        /// Gets the [RaimAvailabilityFlag][self::RaimAvailabilityFlag] stored in the `flags` bitfield.
750        ///
751        /// Returns `Ok` if the bitrange contains a known `RaimAvailabilityFlag` variant.
752        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
753        /// or because new variants of `RaimAvailabilityFlag` were added.
754        pub fn raim_availability_flag(&self) -> Result<RaimAvailabilityFlag, u8> {
755            get_bit_range!(self.flags, u8, u8, 3, 3).try_into()
756        }
757
758        /// Set the bitrange corresponding to the [RaimAvailabilityFlag][RaimAvailabilityFlag] of the `flags` bitfield.
759        pub fn set_raim_availability_flag(&mut self, raim_availability_flag: RaimAvailabilityFlag) {
760            set_bit_range!(&mut self.flags, raim_availability_flag, u8, u8, 3, 3);
761        }
762
763        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
764        ///
765        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
766        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
767        /// or because new variants of `FixMode` were added.
768        pub fn fix_mode(&self) -> Result<FixMode, u8> {
769            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
770        }
771
772        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
773        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
774            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
775        }
776    }
777
778    impl ConcreteMessage for MsgBaselineHeadingDepA {
779        const MESSAGE_TYPE: u16 = 519;
780        const MESSAGE_NAME: &'static str = "MSG_BASELINE_HEADING_DEP_A";
781    }
782
783    impl SbpMessage for MsgBaselineHeadingDepA {
784        fn message_name(&self) -> &'static str {
785            <Self as ConcreteMessage>::MESSAGE_NAME
786        }
787        fn message_type(&self) -> Option<u16> {
788            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
789        }
790        fn sender_id(&self) -> Option<u16> {
791            self.sender_id
792        }
793        fn set_sender_id(&mut self, new_id: u16) {
794            self.sender_id = Some(new_id);
795        }
796        fn encoded_len(&self) -> usize {
797            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
798        }
799        fn is_valid(&self) -> bool {
800            true
801        }
802        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
803            Ok(self)
804        }
805
806        #[cfg(feature = "swiftnav")]
807        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
808            let tow_s = (self.tow as f64) / 1000.0;
809            let gps_time = match time::GpsTime::new(0, tow_s) {
810                Ok(gps_time) => gps_time.tow(),
811                Err(e) => return Some(Err(e.into())),
812            };
813            Some(Ok(time::MessageTime::Rover(gps_time.into())))
814        }
815    }
816
817    impl FriendlyName for MsgBaselineHeadingDepA {
818        fn friendly_name() -> &'static str {
819            "BASELINE HEADING DEP A"
820        }
821    }
822
823    impl TryFrom<Sbp> for MsgBaselineHeadingDepA {
824        type Error = TryFromSbpError;
825        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
826            match msg {
827                Sbp::MsgBaselineHeadingDepA(m) => Ok(m),
828                _ => Err(TryFromSbpError(msg)),
829            }
830        }
831    }
832
833    impl WireFormat for MsgBaselineHeadingDepA {
834        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
835            + <u32 as WireFormat>::MIN_LEN
836            + <u8 as WireFormat>::MIN_LEN
837            + <u8 as WireFormat>::MIN_LEN;
838        fn len(&self) -> usize {
839            WireFormat::len(&self.tow)
840                + WireFormat::len(&self.heading)
841                + WireFormat::len(&self.n_sats)
842                + WireFormat::len(&self.flags)
843        }
844        fn write<B: BufMut>(&self, buf: &mut B) {
845            WireFormat::write(&self.tow, buf);
846            WireFormat::write(&self.heading, buf);
847            WireFormat::write(&self.n_sats, buf);
848            WireFormat::write(&self.flags, buf);
849        }
850        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
851            MsgBaselineHeadingDepA {
852                sender_id: None,
853                tow: WireFormat::parse_unchecked(buf),
854                heading: WireFormat::parse_unchecked(buf),
855                n_sats: WireFormat::parse_unchecked(buf),
856                flags: WireFormat::parse_unchecked(buf),
857            }
858        }
859    }
860
861    /// RAIM repair flag
862    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
863    pub enum RaimRepairFlag {
864        /// No repair
865        NoRepair = 0,
866
867        /// Solution came from RAIM repair
868        SolutionCameFromRaimRepair = 1,
869    }
870
871    impl std::fmt::Display for RaimRepairFlag {
872        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
873            match self {
874                RaimRepairFlag::NoRepair => f.write_str("No repair"),
875                RaimRepairFlag::SolutionCameFromRaimRepair => {
876                    f.write_str("Solution came from RAIM repair")
877                }
878            }
879        }
880    }
881
882    impl TryFrom<u8> for RaimRepairFlag {
883        type Error = u8;
884        fn try_from(i: u8) -> Result<Self, u8> {
885            match i {
886                0 => Ok(RaimRepairFlag::NoRepair),
887                1 => Ok(RaimRepairFlag::SolutionCameFromRaimRepair),
888                i => Err(i),
889            }
890        }
891    }
892
893    /// RAIM availability flag
894    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
895    pub enum RaimAvailabilityFlag {
896        /// RAIM check was explicitly disabled or unavailable
897        RaimCheckWasExplicitlyDisabledOrUnavailable = 0,
898
899        /// RAIM check was available
900        RaimCheckWasAvailable = 1,
901    }
902
903    impl std::fmt::Display for RaimAvailabilityFlag {
904        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
905            match self {
906                RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable => {
907                    f.write_str("RAIM check was explicitly disabled or unavailable")
908                }
909                RaimAvailabilityFlag::RaimCheckWasAvailable => {
910                    f.write_str("RAIM check was available")
911                }
912            }
913        }
914    }
915
916    impl TryFrom<u8> for RaimAvailabilityFlag {
917        type Error = u8;
918        fn try_from(i: u8) -> Result<Self, u8> {
919            match i {
920                0 => Ok(RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable),
921                1 => Ok(RaimAvailabilityFlag::RaimCheckWasAvailable),
922                i => Err(i),
923            }
924        }
925    }
926
927    /// Fix mode
928    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
929    pub enum FixMode {
930        /// Float RTK
931        FloatRtk = 0,
932
933        /// Fixed RTK
934        FixedRtk = 1,
935    }
936
937    impl std::fmt::Display for FixMode {
938        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
939            match self {
940                FixMode::FloatRtk => f.write_str("Float RTK"),
941                FixMode::FixedRtk => f.write_str("Fixed RTK"),
942            }
943        }
944    }
945
946    impl TryFrom<u8> for FixMode {
947        type Error = u8;
948        fn try_from(i: u8) -> Result<Self, u8> {
949            match i {
950                0 => Ok(FixMode::FloatRtk),
951                1 => Ok(FixMode::FixedRtk),
952                i => Err(i),
953            }
954        }
955    }
956}
957
958pub mod msg_baseline_ned {
959    #![allow(unused_imports)]
960
961    use super::*;
962    use crate::messages::lib::*;
963
964    /// GNSS-only Baseline in NED
965    ///
966    /// This message reports the baseline solution in North East Down (NED)
967    /// coordinates. This baseline is the relative vector distance from the base
968    /// station to the rover receiver, and NED coordinate system is defined at the
969    /// local WGS84 tangent plane centered at the base station position.  The full
970    /// GPS time is given by the preceding MSG_GPS_TIME with the matching time-of-
971    /// week (tow).
972    ///
973    /// The values in this message are from GNSS measurements only.
974    ///
975    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
976    #[allow(clippy::derive_partial_eq_without_eq)]
977    #[derive(Debug, PartialEq, Clone)]
978    pub struct MsgBaselineNed {
979        /// The message sender_id
980        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
981        pub sender_id: Option<u16>,
982        /// GPS Time of Week
983        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
984        pub tow: u32,
985        /// Baseline North coordinate
986        #[cfg_attr(feature = "serde", serde(rename = "n"))]
987        pub n: i32,
988        /// Baseline East coordinate
989        #[cfg_attr(feature = "serde", serde(rename = "e"))]
990        pub e: i32,
991        /// Baseline Down coordinate
992        #[cfg_attr(feature = "serde", serde(rename = "d"))]
993        pub d: i32,
994        /// Horizontal position estimated standard deviation
995        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
996        pub h_accuracy: u16,
997        /// Vertical position estimated standard deviation
998        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
999        pub v_accuracy: u16,
1000        /// Number of satellites used in solution
1001        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
1002        pub n_sats: u8,
1003        /// Status flags
1004        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
1005        pub flags: u8,
1006    }
1007
1008    impl MsgBaselineNed {
1009        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
1010        ///
1011        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
1012        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
1013        /// or because new variants of `FixMode` were added.
1014        pub fn fix_mode(&self) -> Result<FixMode, u8> {
1015            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
1016        }
1017
1018        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
1019        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
1020            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
1021        }
1022    }
1023
1024    impl ConcreteMessage for MsgBaselineNed {
1025        const MESSAGE_TYPE: u16 = 524;
1026        const MESSAGE_NAME: &'static str = "MSG_BASELINE_NED";
1027    }
1028
1029    impl SbpMessage for MsgBaselineNed {
1030        fn message_name(&self) -> &'static str {
1031            <Self as ConcreteMessage>::MESSAGE_NAME
1032        }
1033        fn message_type(&self) -> Option<u16> {
1034            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
1035        }
1036        fn sender_id(&self) -> Option<u16> {
1037            self.sender_id
1038        }
1039        fn set_sender_id(&mut self, new_id: u16) {
1040            self.sender_id = Some(new_id);
1041        }
1042        fn encoded_len(&self) -> usize {
1043            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
1044        }
1045        fn is_valid(&self) -> bool {
1046            true
1047        }
1048        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
1049            Ok(self)
1050        }
1051
1052        #[cfg(feature = "swiftnav")]
1053        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
1054            let tow_s = (self.tow as f64) / 1000.0;
1055            let gps_time = match time::GpsTime::new(0, tow_s) {
1056                Ok(gps_time) => gps_time.tow(),
1057                Err(e) => return Some(Err(e.into())),
1058            };
1059            Some(Ok(time::MessageTime::Rover(gps_time.into())))
1060        }
1061    }
1062
1063    impl FriendlyName for MsgBaselineNed {
1064        fn friendly_name() -> &'static str {
1065            "BASELINE NED"
1066        }
1067    }
1068
1069    impl TryFrom<Sbp> for MsgBaselineNed {
1070        type Error = TryFromSbpError;
1071        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
1072            match msg {
1073                Sbp::MsgBaselineNed(m) => Ok(m),
1074                _ => Err(TryFromSbpError(msg)),
1075            }
1076        }
1077    }
1078
1079    impl WireFormat for MsgBaselineNed {
1080        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
1081            + <i32 as WireFormat>::MIN_LEN
1082            + <i32 as WireFormat>::MIN_LEN
1083            + <i32 as WireFormat>::MIN_LEN
1084            + <u16 as WireFormat>::MIN_LEN
1085            + <u16 as WireFormat>::MIN_LEN
1086            + <u8 as WireFormat>::MIN_LEN
1087            + <u8 as WireFormat>::MIN_LEN;
1088        fn len(&self) -> usize {
1089            WireFormat::len(&self.tow)
1090                + WireFormat::len(&self.n)
1091                + WireFormat::len(&self.e)
1092                + WireFormat::len(&self.d)
1093                + WireFormat::len(&self.h_accuracy)
1094                + WireFormat::len(&self.v_accuracy)
1095                + WireFormat::len(&self.n_sats)
1096                + WireFormat::len(&self.flags)
1097        }
1098        fn write<B: BufMut>(&self, buf: &mut B) {
1099            WireFormat::write(&self.tow, buf);
1100            WireFormat::write(&self.n, buf);
1101            WireFormat::write(&self.e, buf);
1102            WireFormat::write(&self.d, buf);
1103            WireFormat::write(&self.h_accuracy, buf);
1104            WireFormat::write(&self.v_accuracy, buf);
1105            WireFormat::write(&self.n_sats, buf);
1106            WireFormat::write(&self.flags, buf);
1107        }
1108        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
1109            MsgBaselineNed {
1110                sender_id: None,
1111                tow: WireFormat::parse_unchecked(buf),
1112                n: WireFormat::parse_unchecked(buf),
1113                e: WireFormat::parse_unchecked(buf),
1114                d: WireFormat::parse_unchecked(buf),
1115                h_accuracy: WireFormat::parse_unchecked(buf),
1116                v_accuracy: WireFormat::parse_unchecked(buf),
1117                n_sats: WireFormat::parse_unchecked(buf),
1118                flags: WireFormat::parse_unchecked(buf),
1119            }
1120        }
1121    }
1122
1123    /// Fix mode
1124    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1125    pub enum FixMode {
1126        /// Invalid
1127        Invalid = 0,
1128
1129        /// Differential GNSS (DGNSS)
1130        DifferentialGnss = 2,
1131
1132        /// Float RTK
1133        FloatRtk = 3,
1134
1135        /// Fixed RTK
1136        FixedRtk = 4,
1137    }
1138
1139    impl std::fmt::Display for FixMode {
1140        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1141            match self {
1142                FixMode::Invalid => f.write_str("Invalid"),
1143                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
1144                FixMode::FloatRtk => f.write_str("Float RTK"),
1145                FixMode::FixedRtk => f.write_str("Fixed RTK"),
1146            }
1147        }
1148    }
1149
1150    impl TryFrom<u8> for FixMode {
1151        type Error = u8;
1152        fn try_from(i: u8) -> Result<Self, u8> {
1153            match i {
1154                0 => Ok(FixMode::Invalid),
1155                2 => Ok(FixMode::DifferentialGnss),
1156                3 => Ok(FixMode::FloatRtk),
1157                4 => Ok(FixMode::FixedRtk),
1158                i => Err(i),
1159            }
1160        }
1161    }
1162}
1163
1164pub mod msg_baseline_ned_dep_a {
1165    #![allow(unused_imports)]
1166
1167    use super::*;
1168    use crate::messages::lib::*;
1169
1170    /// Deprecated
1171    ///
1172    /// Deprecated.
1173    ///
1174    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1175    #[allow(clippy::derive_partial_eq_without_eq)]
1176    #[derive(Debug, PartialEq, Clone)]
1177    pub struct MsgBaselineNedDepA {
1178        /// The message sender_id
1179        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
1180        pub sender_id: Option<u16>,
1181        /// GPS Time of Week
1182        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
1183        pub tow: u32,
1184        /// Baseline North coordinate
1185        #[cfg_attr(feature = "serde", serde(rename = "n"))]
1186        pub n: i32,
1187        /// Baseline East coordinate
1188        #[cfg_attr(feature = "serde", serde(rename = "e"))]
1189        pub e: i32,
1190        /// Baseline Down coordinate
1191        #[cfg_attr(feature = "serde", serde(rename = "d"))]
1192        pub d: i32,
1193        /// Horizontal position accuracy estimate (not implemented). Defaults to 0.
1194        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
1195        pub h_accuracy: u16,
1196        /// Vertical position accuracy estimate (not implemented). Defaults to 0.
1197        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
1198        pub v_accuracy: u16,
1199        /// Number of satellites used in solution
1200        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
1201        pub n_sats: u8,
1202        /// Status flags
1203        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
1204        pub flags: u8,
1205    }
1206
1207    impl MsgBaselineNedDepA {
1208        /// Gets the [RaimRepairFlag][self::RaimRepairFlag] stored in the `flags` bitfield.
1209        ///
1210        /// Returns `Ok` if the bitrange contains a known `RaimRepairFlag` variant.
1211        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
1212        /// or because new variants of `RaimRepairFlag` were added.
1213        pub fn raim_repair_flag(&self) -> Result<RaimRepairFlag, u8> {
1214            get_bit_range!(self.flags, u8, u8, 4, 4).try_into()
1215        }
1216
1217        /// Set the bitrange corresponding to the [RaimRepairFlag][RaimRepairFlag] of the `flags` bitfield.
1218        pub fn set_raim_repair_flag(&mut self, raim_repair_flag: RaimRepairFlag) {
1219            set_bit_range!(&mut self.flags, raim_repair_flag, u8, u8, 4, 4);
1220        }
1221
1222        /// Gets the [RaimAvailabilityFlag][self::RaimAvailabilityFlag] stored in the `flags` bitfield.
1223        ///
1224        /// Returns `Ok` if the bitrange contains a known `RaimAvailabilityFlag` variant.
1225        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
1226        /// or because new variants of `RaimAvailabilityFlag` were added.
1227        pub fn raim_availability_flag(&self) -> Result<RaimAvailabilityFlag, u8> {
1228            get_bit_range!(self.flags, u8, u8, 3, 3).try_into()
1229        }
1230
1231        /// Set the bitrange corresponding to the [RaimAvailabilityFlag][RaimAvailabilityFlag] of the `flags` bitfield.
1232        pub fn set_raim_availability_flag(&mut self, raim_availability_flag: RaimAvailabilityFlag) {
1233            set_bit_range!(&mut self.flags, raim_availability_flag, u8, u8, 3, 3);
1234        }
1235
1236        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
1237        ///
1238        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
1239        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
1240        /// or because new variants of `FixMode` were added.
1241        pub fn fix_mode(&self) -> Result<FixMode, u8> {
1242            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
1243        }
1244
1245        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
1246        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
1247            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
1248        }
1249    }
1250
1251    impl ConcreteMessage for MsgBaselineNedDepA {
1252        const MESSAGE_TYPE: u16 = 515;
1253        const MESSAGE_NAME: &'static str = "MSG_BASELINE_NED_DEP_A";
1254    }
1255
1256    impl SbpMessage for MsgBaselineNedDepA {
1257        fn message_name(&self) -> &'static str {
1258            <Self as ConcreteMessage>::MESSAGE_NAME
1259        }
1260        fn message_type(&self) -> Option<u16> {
1261            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
1262        }
1263        fn sender_id(&self) -> Option<u16> {
1264            self.sender_id
1265        }
1266        fn set_sender_id(&mut self, new_id: u16) {
1267            self.sender_id = Some(new_id);
1268        }
1269        fn encoded_len(&self) -> usize {
1270            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
1271        }
1272        fn is_valid(&self) -> bool {
1273            true
1274        }
1275        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
1276            Ok(self)
1277        }
1278
1279        #[cfg(feature = "swiftnav")]
1280        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
1281            let tow_s = (self.tow as f64) / 1000.0;
1282            let gps_time = match time::GpsTime::new(0, tow_s) {
1283                Ok(gps_time) => gps_time.tow(),
1284                Err(e) => return Some(Err(e.into())),
1285            };
1286            Some(Ok(time::MessageTime::Rover(gps_time.into())))
1287        }
1288    }
1289
1290    impl FriendlyName for MsgBaselineNedDepA {
1291        fn friendly_name() -> &'static str {
1292            "BASELINE NED DEP A"
1293        }
1294    }
1295
1296    impl TryFrom<Sbp> for MsgBaselineNedDepA {
1297        type Error = TryFromSbpError;
1298        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
1299            match msg {
1300                Sbp::MsgBaselineNedDepA(m) => Ok(m),
1301                _ => Err(TryFromSbpError(msg)),
1302            }
1303        }
1304    }
1305
1306    impl WireFormat for MsgBaselineNedDepA {
1307        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
1308            + <i32 as WireFormat>::MIN_LEN
1309            + <i32 as WireFormat>::MIN_LEN
1310            + <i32 as WireFormat>::MIN_LEN
1311            + <u16 as WireFormat>::MIN_LEN
1312            + <u16 as WireFormat>::MIN_LEN
1313            + <u8 as WireFormat>::MIN_LEN
1314            + <u8 as WireFormat>::MIN_LEN;
1315        fn len(&self) -> usize {
1316            WireFormat::len(&self.tow)
1317                + WireFormat::len(&self.n)
1318                + WireFormat::len(&self.e)
1319                + WireFormat::len(&self.d)
1320                + WireFormat::len(&self.h_accuracy)
1321                + WireFormat::len(&self.v_accuracy)
1322                + WireFormat::len(&self.n_sats)
1323                + WireFormat::len(&self.flags)
1324        }
1325        fn write<B: BufMut>(&self, buf: &mut B) {
1326            WireFormat::write(&self.tow, buf);
1327            WireFormat::write(&self.n, buf);
1328            WireFormat::write(&self.e, buf);
1329            WireFormat::write(&self.d, buf);
1330            WireFormat::write(&self.h_accuracy, buf);
1331            WireFormat::write(&self.v_accuracy, buf);
1332            WireFormat::write(&self.n_sats, buf);
1333            WireFormat::write(&self.flags, buf);
1334        }
1335        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
1336            MsgBaselineNedDepA {
1337                sender_id: None,
1338                tow: WireFormat::parse_unchecked(buf),
1339                n: WireFormat::parse_unchecked(buf),
1340                e: WireFormat::parse_unchecked(buf),
1341                d: WireFormat::parse_unchecked(buf),
1342                h_accuracy: WireFormat::parse_unchecked(buf),
1343                v_accuracy: WireFormat::parse_unchecked(buf),
1344                n_sats: WireFormat::parse_unchecked(buf),
1345                flags: WireFormat::parse_unchecked(buf),
1346            }
1347        }
1348    }
1349
1350    /// RAIM repair flag
1351    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1352    pub enum RaimRepairFlag {
1353        /// No repair
1354        NoRepair = 0,
1355
1356        /// Solution came from RAIM repair
1357        SolutionCameFromRaimRepair = 1,
1358    }
1359
1360    impl std::fmt::Display for RaimRepairFlag {
1361        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1362            match self {
1363                RaimRepairFlag::NoRepair => f.write_str("No repair"),
1364                RaimRepairFlag::SolutionCameFromRaimRepair => {
1365                    f.write_str("Solution came from RAIM repair")
1366                }
1367            }
1368        }
1369    }
1370
1371    impl TryFrom<u8> for RaimRepairFlag {
1372        type Error = u8;
1373        fn try_from(i: u8) -> Result<Self, u8> {
1374            match i {
1375                0 => Ok(RaimRepairFlag::NoRepair),
1376                1 => Ok(RaimRepairFlag::SolutionCameFromRaimRepair),
1377                i => Err(i),
1378            }
1379        }
1380    }
1381
1382    /// RAIM availability flag
1383    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1384    pub enum RaimAvailabilityFlag {
1385        /// RAIM check was explicitly disabled or unavailable
1386        RaimCheckWasExplicitlyDisabledOrUnavailable = 0,
1387
1388        /// RAIM check was available
1389        RaimCheckWasAvailable = 1,
1390    }
1391
1392    impl std::fmt::Display for RaimAvailabilityFlag {
1393        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1394            match self {
1395                RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable => {
1396                    f.write_str("RAIM check was explicitly disabled or unavailable")
1397                }
1398                RaimAvailabilityFlag::RaimCheckWasAvailable => {
1399                    f.write_str("RAIM check was available")
1400                }
1401            }
1402        }
1403    }
1404
1405    impl TryFrom<u8> for RaimAvailabilityFlag {
1406        type Error = u8;
1407        fn try_from(i: u8) -> Result<Self, u8> {
1408            match i {
1409                0 => Ok(RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable),
1410                1 => Ok(RaimAvailabilityFlag::RaimCheckWasAvailable),
1411                i => Err(i),
1412            }
1413        }
1414    }
1415
1416    /// Fix mode
1417    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1418    pub enum FixMode {
1419        /// Float RTK
1420        FloatRtk = 0,
1421
1422        /// Fixed RTK
1423        FixedRtk = 1,
1424    }
1425
1426    impl std::fmt::Display for FixMode {
1427        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1428            match self {
1429                FixMode::FloatRtk => f.write_str("Float RTK"),
1430                FixMode::FixedRtk => f.write_str("Fixed RTK"),
1431            }
1432        }
1433    }
1434
1435    impl TryFrom<u8> for FixMode {
1436        type Error = u8;
1437        fn try_from(i: u8) -> Result<Self, u8> {
1438            match i {
1439                0 => Ok(FixMode::FloatRtk),
1440                1 => Ok(FixMode::FixedRtk),
1441                i => Err(i),
1442            }
1443        }
1444    }
1445}
1446
1447pub mod msg_dops {
1448    #![allow(unused_imports)]
1449
1450    use super::*;
1451    use crate::messages::lib::*;
1452
1453    /// GNSS-only Dilution of Precision
1454    ///
1455    /// This dilution of precision (DOP) message describes the effect of
1456    /// navigation satellite geometry on positional measurement precision.  The
1457    /// flags field indicated whether the DOP reported corresponds to differential
1458    /// or SPP solution.
1459    ///
1460    /// The values in this message are from GNSS measurements only.
1461    ///
1462    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1463    #[allow(clippy::derive_partial_eq_without_eq)]
1464    #[derive(Debug, PartialEq, Clone)]
1465    pub struct MsgDops {
1466        /// The message sender_id
1467        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
1468        pub sender_id: Option<u16>,
1469        /// GPS Time of Week
1470        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
1471        pub tow: u32,
1472        /// Geometric Dilution of Precision
1473        #[cfg_attr(feature = "serde", serde(rename = "gdop"))]
1474        pub gdop: u16,
1475        /// Position Dilution of Precision
1476        #[cfg_attr(feature = "serde", serde(rename = "pdop"))]
1477        pub pdop: u16,
1478        /// Time Dilution of Precision
1479        #[cfg_attr(feature = "serde", serde(rename = "tdop"))]
1480        pub tdop: u16,
1481        /// Horizontal Dilution of Precision
1482        #[cfg_attr(feature = "serde", serde(rename = "hdop"))]
1483        pub hdop: u16,
1484        /// Vertical Dilution of Precision
1485        #[cfg_attr(feature = "serde", serde(rename = "vdop"))]
1486        pub vdop: u16,
1487        /// Indicates the position solution with which the DOPS message corresponds
1488        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
1489        pub flags: u8,
1490    }
1491
1492    impl MsgDops {
1493        /// Gets the `raim_repair_flag` flag.
1494        #[allow(clippy::identity_op)]
1495        pub fn raim_repair_flag(&self) -> bool {
1496            ((self.flags >> 7) & 1) == 1
1497        }
1498
1499        /// Sets the `raim_repair_flag` flag.
1500        pub fn set_raim_repair_flag(&mut self, raim_repair_flag: bool) {
1501            self.flags ^= (!(raim_repair_flag as u8)) & (1 << 7)
1502        }
1503
1504        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
1505        ///
1506        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
1507        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
1508        /// or because new variants of `FixMode` were added.
1509        pub fn fix_mode(&self) -> Result<FixMode, u8> {
1510            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
1511        }
1512
1513        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
1514        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
1515            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
1516        }
1517    }
1518
1519    impl ConcreteMessage for MsgDops {
1520        const MESSAGE_TYPE: u16 = 520;
1521        const MESSAGE_NAME: &'static str = "MSG_DOPS";
1522    }
1523
1524    impl SbpMessage for MsgDops {
1525        fn message_name(&self) -> &'static str {
1526            <Self as ConcreteMessage>::MESSAGE_NAME
1527        }
1528        fn message_type(&self) -> Option<u16> {
1529            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
1530        }
1531        fn sender_id(&self) -> Option<u16> {
1532            self.sender_id
1533        }
1534        fn set_sender_id(&mut self, new_id: u16) {
1535            self.sender_id = Some(new_id);
1536        }
1537        fn encoded_len(&self) -> usize {
1538            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
1539        }
1540        fn is_valid(&self) -> bool {
1541            true
1542        }
1543        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
1544            Ok(self)
1545        }
1546
1547        #[cfg(feature = "swiftnav")]
1548        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
1549            let tow_s = (self.tow as f64) / 1000.0;
1550            let gps_time = match time::GpsTime::new(0, tow_s) {
1551                Ok(gps_time) => gps_time.tow(),
1552                Err(e) => return Some(Err(e.into())),
1553            };
1554            Some(Ok(time::MessageTime::Rover(gps_time.into())))
1555        }
1556    }
1557
1558    impl FriendlyName for MsgDops {
1559        fn friendly_name() -> &'static str {
1560            "DOPS"
1561        }
1562    }
1563
1564    impl TryFrom<Sbp> for MsgDops {
1565        type Error = TryFromSbpError;
1566        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
1567            match msg {
1568                Sbp::MsgDops(m) => Ok(m),
1569                _ => Err(TryFromSbpError(msg)),
1570            }
1571        }
1572    }
1573
1574    impl WireFormat for MsgDops {
1575        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
1576            + <u16 as WireFormat>::MIN_LEN
1577            + <u16 as WireFormat>::MIN_LEN
1578            + <u16 as WireFormat>::MIN_LEN
1579            + <u16 as WireFormat>::MIN_LEN
1580            + <u16 as WireFormat>::MIN_LEN
1581            + <u8 as WireFormat>::MIN_LEN;
1582        fn len(&self) -> usize {
1583            WireFormat::len(&self.tow)
1584                + WireFormat::len(&self.gdop)
1585                + WireFormat::len(&self.pdop)
1586                + WireFormat::len(&self.tdop)
1587                + WireFormat::len(&self.hdop)
1588                + WireFormat::len(&self.vdop)
1589                + WireFormat::len(&self.flags)
1590        }
1591        fn write<B: BufMut>(&self, buf: &mut B) {
1592            WireFormat::write(&self.tow, buf);
1593            WireFormat::write(&self.gdop, buf);
1594            WireFormat::write(&self.pdop, buf);
1595            WireFormat::write(&self.tdop, buf);
1596            WireFormat::write(&self.hdop, buf);
1597            WireFormat::write(&self.vdop, buf);
1598            WireFormat::write(&self.flags, buf);
1599        }
1600        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
1601            MsgDops {
1602                sender_id: None,
1603                tow: WireFormat::parse_unchecked(buf),
1604                gdop: WireFormat::parse_unchecked(buf),
1605                pdop: WireFormat::parse_unchecked(buf),
1606                tdop: WireFormat::parse_unchecked(buf),
1607                hdop: WireFormat::parse_unchecked(buf),
1608                vdop: WireFormat::parse_unchecked(buf),
1609                flags: WireFormat::parse_unchecked(buf),
1610            }
1611        }
1612    }
1613
1614    /// Fix mode
1615    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1616    pub enum FixMode {
1617        /// Invalid
1618        Invalid = 0,
1619
1620        /// Single Point Position (SPP)
1621        SinglePointPosition = 1,
1622
1623        /// Differential GNSS (DGNSS)
1624        DifferentialGnss = 2,
1625
1626        /// Float RTK
1627        FloatRtk = 3,
1628
1629        /// Fixed RTK
1630        FixedRtk = 4,
1631
1632        /// Undefined
1633        Undefined = 5,
1634
1635        /// SBAS Position
1636        SbasPosition = 6,
1637    }
1638
1639    impl std::fmt::Display for FixMode {
1640        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1641            match self {
1642                FixMode::Invalid => f.write_str("Invalid"),
1643                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
1644                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
1645                FixMode::FloatRtk => f.write_str("Float RTK"),
1646                FixMode::FixedRtk => f.write_str("Fixed RTK"),
1647                FixMode::Undefined => f.write_str("Undefined"),
1648                FixMode::SbasPosition => f.write_str("SBAS Position"),
1649            }
1650        }
1651    }
1652
1653    impl TryFrom<u8> for FixMode {
1654        type Error = u8;
1655        fn try_from(i: u8) -> Result<Self, u8> {
1656            match i {
1657                0 => Ok(FixMode::Invalid),
1658                1 => Ok(FixMode::SinglePointPosition),
1659                2 => Ok(FixMode::DifferentialGnss),
1660                3 => Ok(FixMode::FloatRtk),
1661                4 => Ok(FixMode::FixedRtk),
1662                5 => Ok(FixMode::Undefined),
1663                6 => Ok(FixMode::SbasPosition),
1664                i => Err(i),
1665            }
1666        }
1667    }
1668}
1669
1670pub mod msg_dops_dep_a {
1671    #![allow(unused_imports)]
1672
1673    use super::*;
1674    use crate::messages::lib::*;
1675
1676    /// Deprecated
1677    ///
1678    /// Deprecated.
1679    ///
1680    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1681    #[allow(clippy::derive_partial_eq_without_eq)]
1682    #[derive(Debug, PartialEq, Clone)]
1683    pub struct MsgDopsDepA {
1684        /// The message sender_id
1685        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
1686        pub sender_id: Option<u16>,
1687        /// GPS Time of Week
1688        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
1689        pub tow: u32,
1690        /// Geometric Dilution of Precision
1691        #[cfg_attr(feature = "serde", serde(rename = "gdop"))]
1692        pub gdop: u16,
1693        /// Position Dilution of Precision
1694        #[cfg_attr(feature = "serde", serde(rename = "pdop"))]
1695        pub pdop: u16,
1696        /// Time Dilution of Precision
1697        #[cfg_attr(feature = "serde", serde(rename = "tdop"))]
1698        pub tdop: u16,
1699        /// Horizontal Dilution of Precision
1700        #[cfg_attr(feature = "serde", serde(rename = "hdop"))]
1701        pub hdop: u16,
1702        /// Vertical Dilution of Precision
1703        #[cfg_attr(feature = "serde", serde(rename = "vdop"))]
1704        pub vdop: u16,
1705    }
1706
1707    impl ConcreteMessage for MsgDopsDepA {
1708        const MESSAGE_TYPE: u16 = 518;
1709        const MESSAGE_NAME: &'static str = "MSG_DOPS_DEP_A";
1710    }
1711
1712    impl SbpMessage for MsgDopsDepA {
1713        fn message_name(&self) -> &'static str {
1714            <Self as ConcreteMessage>::MESSAGE_NAME
1715        }
1716        fn message_type(&self) -> Option<u16> {
1717            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
1718        }
1719        fn sender_id(&self) -> Option<u16> {
1720            self.sender_id
1721        }
1722        fn set_sender_id(&mut self, new_id: u16) {
1723            self.sender_id = Some(new_id);
1724        }
1725        fn encoded_len(&self) -> usize {
1726            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
1727        }
1728        fn is_valid(&self) -> bool {
1729            true
1730        }
1731        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
1732            Ok(self)
1733        }
1734
1735        #[cfg(feature = "swiftnav")]
1736        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
1737            let tow_s = (self.tow as f64) / 1000.0;
1738            let gps_time = match time::GpsTime::new(0, tow_s) {
1739                Ok(gps_time) => gps_time.tow(),
1740                Err(e) => return Some(Err(e.into())),
1741            };
1742            Some(Ok(time::MessageTime::Rover(gps_time.into())))
1743        }
1744    }
1745
1746    impl FriendlyName for MsgDopsDepA {
1747        fn friendly_name() -> &'static str {
1748            "DOPS DEP A"
1749        }
1750    }
1751
1752    impl TryFrom<Sbp> for MsgDopsDepA {
1753        type Error = TryFromSbpError;
1754        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
1755            match msg {
1756                Sbp::MsgDopsDepA(m) => Ok(m),
1757                _ => Err(TryFromSbpError(msg)),
1758            }
1759        }
1760    }
1761
1762    impl WireFormat for MsgDopsDepA {
1763        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
1764            + <u16 as WireFormat>::MIN_LEN
1765            + <u16 as WireFormat>::MIN_LEN
1766            + <u16 as WireFormat>::MIN_LEN
1767            + <u16 as WireFormat>::MIN_LEN
1768            + <u16 as WireFormat>::MIN_LEN;
1769        fn len(&self) -> usize {
1770            WireFormat::len(&self.tow)
1771                + WireFormat::len(&self.gdop)
1772                + WireFormat::len(&self.pdop)
1773                + WireFormat::len(&self.tdop)
1774                + WireFormat::len(&self.hdop)
1775                + WireFormat::len(&self.vdop)
1776        }
1777        fn write<B: BufMut>(&self, buf: &mut B) {
1778            WireFormat::write(&self.tow, buf);
1779            WireFormat::write(&self.gdop, buf);
1780            WireFormat::write(&self.pdop, buf);
1781            WireFormat::write(&self.tdop, buf);
1782            WireFormat::write(&self.hdop, buf);
1783            WireFormat::write(&self.vdop, buf);
1784        }
1785        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
1786            MsgDopsDepA {
1787                sender_id: None,
1788                tow: WireFormat::parse_unchecked(buf),
1789                gdop: WireFormat::parse_unchecked(buf),
1790                pdop: WireFormat::parse_unchecked(buf),
1791                tdop: WireFormat::parse_unchecked(buf),
1792                hdop: WireFormat::parse_unchecked(buf),
1793                vdop: WireFormat::parse_unchecked(buf),
1794            }
1795        }
1796    }
1797}
1798
1799pub mod msg_gps_time {
1800    #![allow(unused_imports)]
1801
1802    use super::*;
1803    use crate::messages::lib::*;
1804
1805    /// GPS Time (GNSS + inertial)
1806    ///
1807    /// This message reports the GPS time, representing the time since the GPS
1808    /// epoch began on midnight January 6, 1980 UTC. GPS time counts the weeks and
1809    /// seconds of the week. The weeks begin at the Saturday/Sunday transition.
1810    /// GPS week 0 began at the beginning of the GPS time scale.
1811    ///
1812    /// Within each week number, the GPS time of the week is between between 0 and
1813    /// 604800 seconds (=60*60*24*7). Note that GPS time does not accumulate leap
1814    /// seconds, and as of now, has a small offset from UTC. In a message stream,
1815    /// this message precedes a set of other navigation messages referenced to the
1816    /// same time (but lacking the ns field) and indicates a more precise time of
1817    /// these messages.
1818    ///
1819    /// The values in this message are from GNSS measurements fused with inertial
1820    /// measurements. To get values from GNSS measurements only use
1821    /// MSG_GPS_TIME_GNSS.
1822    ///
1823    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1824    #[allow(clippy::derive_partial_eq_without_eq)]
1825    #[derive(Debug, PartialEq, Clone)]
1826    pub struct MsgGpsTime {
1827        /// The message sender_id
1828        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
1829        pub sender_id: Option<u16>,
1830        /// GPS week number
1831        #[cfg_attr(feature = "serde", serde(rename = "wn"))]
1832        pub wn: u16,
1833        /// GPS time of week rounded to the nearest millisecond
1834        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
1835        pub tow: u32,
1836        /// Nanosecond residual of millisecond-rounded TOW (ranges from -500000 to
1837        /// 500000)
1838        #[cfg_attr(feature = "serde", serde(rename = "ns_residual"))]
1839        pub ns_residual: i32,
1840        /// Status flags (reserved)
1841        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
1842        pub flags: u8,
1843    }
1844
1845    impl MsgGpsTime {
1846        /// Gets the [TimeSource][self::TimeSource] stored in the `flags` bitfield.
1847        ///
1848        /// Returns `Ok` if the bitrange contains a known `TimeSource` variant.
1849        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
1850        /// or because new variants of `TimeSource` were added.
1851        pub fn time_source(&self) -> Result<TimeSource, u8> {
1852            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
1853        }
1854
1855        /// Set the bitrange corresponding to the [TimeSource][TimeSource] of the `flags` bitfield.
1856        pub fn set_time_source(&mut self, time_source: TimeSource) {
1857            set_bit_range!(&mut self.flags, time_source, u8, u8, 2, 0);
1858        }
1859    }
1860
1861    impl ConcreteMessage for MsgGpsTime {
1862        const MESSAGE_TYPE: u16 = 258;
1863        const MESSAGE_NAME: &'static str = "MSG_GPS_TIME";
1864    }
1865
1866    impl SbpMessage for MsgGpsTime {
1867        fn message_name(&self) -> &'static str {
1868            <Self as ConcreteMessage>::MESSAGE_NAME
1869        }
1870        fn message_type(&self) -> Option<u16> {
1871            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
1872        }
1873        fn sender_id(&self) -> Option<u16> {
1874            self.sender_id
1875        }
1876        fn set_sender_id(&mut self, new_id: u16) {
1877            self.sender_id = Some(new_id);
1878        }
1879        fn encoded_len(&self) -> usize {
1880            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
1881        }
1882        fn is_valid(&self) -> bool {
1883            true
1884        }
1885        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
1886            Ok(self)
1887        }
1888
1889        #[cfg(feature = "swiftnav")]
1890        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
1891            if self.time_source().ok()? == TimeSource::None {
1892                return None;
1893            }
1894            let tow_s = (self.tow as f64) / 1000.0;
1895            #[allow(clippy::useless_conversion)]
1896            let wn: i16 = match self.wn.try_into() {
1897                Ok(wn) => wn,
1898                Err(e) => return Some(Err(e.into())),
1899            };
1900            let gps_time = match time::GpsTime::new(wn, tow_s) {
1901                Ok(gps_time) => gps_time,
1902                Err(e) => return Some(Err(e.into())),
1903            };
1904            Some(Ok(time::MessageTime::Rover(gps_time.into())))
1905        }
1906    }
1907
1908    impl FriendlyName for MsgGpsTime {
1909        fn friendly_name() -> &'static str {
1910            "GPS TIME"
1911        }
1912    }
1913
1914    impl TryFrom<Sbp> for MsgGpsTime {
1915        type Error = TryFromSbpError;
1916        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
1917            match msg {
1918                Sbp::MsgGpsTime(m) => Ok(m),
1919                _ => Err(TryFromSbpError(msg)),
1920            }
1921        }
1922    }
1923
1924    impl WireFormat for MsgGpsTime {
1925        const MIN_LEN: usize = <u16 as WireFormat>::MIN_LEN
1926            + <u32 as WireFormat>::MIN_LEN
1927            + <i32 as WireFormat>::MIN_LEN
1928            + <u8 as WireFormat>::MIN_LEN;
1929        fn len(&self) -> usize {
1930            WireFormat::len(&self.wn)
1931                + WireFormat::len(&self.tow)
1932                + WireFormat::len(&self.ns_residual)
1933                + WireFormat::len(&self.flags)
1934        }
1935        fn write<B: BufMut>(&self, buf: &mut B) {
1936            WireFormat::write(&self.wn, buf);
1937            WireFormat::write(&self.tow, buf);
1938            WireFormat::write(&self.ns_residual, buf);
1939            WireFormat::write(&self.flags, buf);
1940        }
1941        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
1942            MsgGpsTime {
1943                sender_id: None,
1944                wn: WireFormat::parse_unchecked(buf),
1945                tow: WireFormat::parse_unchecked(buf),
1946                ns_residual: WireFormat::parse_unchecked(buf),
1947                flags: WireFormat::parse_unchecked(buf),
1948            }
1949        }
1950    }
1951
1952    /// Time source
1953    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1954    pub enum TimeSource {
1955        /// None (invalid)
1956        None = 0,
1957
1958        /// GNSS Solution
1959        GnssSolution = 1,
1960
1961        /// Propagated
1962        Propagated = 2,
1963    }
1964
1965    impl std::fmt::Display for TimeSource {
1966        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1967            match self {
1968                TimeSource::None => f.write_str("None (invalid)"),
1969                TimeSource::GnssSolution => f.write_str("GNSS Solution"),
1970                TimeSource::Propagated => f.write_str("Propagated"),
1971            }
1972        }
1973    }
1974
1975    impl TryFrom<u8> for TimeSource {
1976        type Error = u8;
1977        fn try_from(i: u8) -> Result<Self, u8> {
1978            match i {
1979                0 => Ok(TimeSource::None),
1980                1 => Ok(TimeSource::GnssSolution),
1981                2 => Ok(TimeSource::Propagated),
1982                i => Err(i),
1983            }
1984        }
1985    }
1986}
1987
1988pub mod msg_gps_time_dep_a {
1989    #![allow(unused_imports)]
1990
1991    use super::*;
1992    use crate::messages::lib::*;
1993
1994    /// Deprecated
1995    ///
1996    /// Deprecated.
1997    ///
1998    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1999    #[allow(clippy::derive_partial_eq_without_eq)]
2000    #[derive(Debug, PartialEq, Clone)]
2001    pub struct MsgGpsTimeDepA {
2002        /// The message sender_id
2003        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
2004        pub sender_id: Option<u16>,
2005        /// GPS week number
2006        #[cfg_attr(feature = "serde", serde(rename = "wn"))]
2007        pub wn: u16,
2008        /// GPS time of week rounded to the nearest millisecond
2009        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
2010        pub tow: u32,
2011        /// Nanosecond residual of millisecond-rounded TOW (ranges from -500000 to
2012        /// 500000)
2013        #[cfg_attr(feature = "serde", serde(rename = "ns_residual"))]
2014        pub ns_residual: i32,
2015        /// Status flags (reserved)
2016        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
2017        pub flags: u8,
2018    }
2019
2020    impl ConcreteMessage for MsgGpsTimeDepA {
2021        const MESSAGE_TYPE: u16 = 256;
2022        const MESSAGE_NAME: &'static str = "MSG_GPS_TIME_DEP_A";
2023    }
2024
2025    impl SbpMessage for MsgGpsTimeDepA {
2026        fn message_name(&self) -> &'static str {
2027            <Self as ConcreteMessage>::MESSAGE_NAME
2028        }
2029        fn message_type(&self) -> Option<u16> {
2030            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
2031        }
2032        fn sender_id(&self) -> Option<u16> {
2033            self.sender_id
2034        }
2035        fn set_sender_id(&mut self, new_id: u16) {
2036            self.sender_id = Some(new_id);
2037        }
2038        fn encoded_len(&self) -> usize {
2039            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
2040        }
2041        fn is_valid(&self) -> bool {
2042            true
2043        }
2044        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
2045            Ok(self)
2046        }
2047
2048        #[cfg(feature = "swiftnav")]
2049        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
2050            let tow_s = (self.tow as f64) / 1000.0;
2051            #[allow(clippy::useless_conversion)]
2052            let wn: i16 = match self.wn.try_into() {
2053                Ok(wn) => wn,
2054                Err(e) => return Some(Err(e.into())),
2055            };
2056            let gps_time = match time::GpsTime::new(wn, tow_s) {
2057                Ok(gps_time) => gps_time,
2058                Err(e) => return Some(Err(e.into())),
2059            };
2060            Some(Ok(time::MessageTime::Rover(gps_time.into())))
2061        }
2062    }
2063
2064    impl FriendlyName for MsgGpsTimeDepA {
2065        fn friendly_name() -> &'static str {
2066            "GPS TIME DEP A"
2067        }
2068    }
2069
2070    impl TryFrom<Sbp> for MsgGpsTimeDepA {
2071        type Error = TryFromSbpError;
2072        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
2073            match msg {
2074                Sbp::MsgGpsTimeDepA(m) => Ok(m),
2075                _ => Err(TryFromSbpError(msg)),
2076            }
2077        }
2078    }
2079
2080    impl WireFormat for MsgGpsTimeDepA {
2081        const MIN_LEN: usize = <u16 as WireFormat>::MIN_LEN
2082            + <u32 as WireFormat>::MIN_LEN
2083            + <i32 as WireFormat>::MIN_LEN
2084            + <u8 as WireFormat>::MIN_LEN;
2085        fn len(&self) -> usize {
2086            WireFormat::len(&self.wn)
2087                + WireFormat::len(&self.tow)
2088                + WireFormat::len(&self.ns_residual)
2089                + WireFormat::len(&self.flags)
2090        }
2091        fn write<B: BufMut>(&self, buf: &mut B) {
2092            WireFormat::write(&self.wn, buf);
2093            WireFormat::write(&self.tow, buf);
2094            WireFormat::write(&self.ns_residual, buf);
2095            WireFormat::write(&self.flags, buf);
2096        }
2097        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
2098            MsgGpsTimeDepA {
2099                sender_id: None,
2100                wn: WireFormat::parse_unchecked(buf),
2101                tow: WireFormat::parse_unchecked(buf),
2102                ns_residual: WireFormat::parse_unchecked(buf),
2103                flags: WireFormat::parse_unchecked(buf),
2104            }
2105        }
2106    }
2107}
2108
2109pub mod msg_gps_time_gnss {
2110    #![allow(unused_imports)]
2111
2112    use super::*;
2113    use crate::messages::lib::*;
2114
2115    /// GNSS-only GPS Time
2116    ///
2117    /// This message reports the GPS time, representing the time since the GPS
2118    /// epoch began on midnight January 6, 1980 UTC. GPS time counts the weeks and
2119    /// seconds of the week. The weeks begin at the Saturday/Sunday transition.
2120    /// GPS week 0 began at the beginning of the GPS time scale.
2121    ///
2122    /// Within each week number, the GPS time of the week is between between 0 and
2123    /// 604800 seconds (=60*60*24*7). Note that GPS time does not accumulate leap
2124    /// seconds, and as of now, has a small offset from UTC. In a message stream,
2125    /// this message precedes a set of other navigation messages referenced to the
2126    /// same time (but lacking the ns field) and indicates a more precise time of
2127    /// these messages.
2128    ///
2129    /// The values in this message are from GNSS measurements only. To get values
2130    /// fused with inertial measurements use MSG_GPS_TIME.
2131    ///
2132    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2133    #[allow(clippy::derive_partial_eq_without_eq)]
2134    #[derive(Debug, PartialEq, Clone)]
2135    pub struct MsgGpsTimeGnss {
2136        /// The message sender_id
2137        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
2138        pub sender_id: Option<u16>,
2139        /// GPS week number
2140        #[cfg_attr(feature = "serde", serde(rename = "wn"))]
2141        pub wn: u16,
2142        /// GPS time of week rounded to the nearest millisecond
2143        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
2144        pub tow: u32,
2145        /// Nanosecond residual of millisecond-rounded TOW (ranges from -500000 to
2146        /// 500000)
2147        #[cfg_attr(feature = "serde", serde(rename = "ns_residual"))]
2148        pub ns_residual: i32,
2149        /// Status flags (reserved)
2150        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
2151        pub flags: u8,
2152    }
2153
2154    impl MsgGpsTimeGnss {
2155        /// Gets the [TimeSource][self::TimeSource] stored in the `flags` bitfield.
2156        ///
2157        /// Returns `Ok` if the bitrange contains a known `TimeSource` variant.
2158        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
2159        /// or because new variants of `TimeSource` were added.
2160        pub fn time_source(&self) -> Result<TimeSource, u8> {
2161            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
2162        }
2163
2164        /// Set the bitrange corresponding to the [TimeSource][TimeSource] of the `flags` bitfield.
2165        pub fn set_time_source(&mut self, time_source: TimeSource) {
2166            set_bit_range!(&mut self.flags, time_source, u8, u8, 2, 0);
2167        }
2168    }
2169
2170    impl ConcreteMessage for MsgGpsTimeGnss {
2171        const MESSAGE_TYPE: u16 = 260;
2172        const MESSAGE_NAME: &'static str = "MSG_GPS_TIME_GNSS";
2173    }
2174
2175    impl SbpMessage for MsgGpsTimeGnss {
2176        fn message_name(&self) -> &'static str {
2177            <Self as ConcreteMessage>::MESSAGE_NAME
2178        }
2179        fn message_type(&self) -> Option<u16> {
2180            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
2181        }
2182        fn sender_id(&self) -> Option<u16> {
2183            self.sender_id
2184        }
2185        fn set_sender_id(&mut self, new_id: u16) {
2186            self.sender_id = Some(new_id);
2187        }
2188        fn encoded_len(&self) -> usize {
2189            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
2190        }
2191        fn is_valid(&self) -> bool {
2192            true
2193        }
2194        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
2195            Ok(self)
2196        }
2197
2198        #[cfg(feature = "swiftnav")]
2199        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
2200            if self.time_source().ok()? == TimeSource::None {
2201                return None;
2202            }
2203            let tow_s = (self.tow as f64) / 1000.0;
2204            #[allow(clippy::useless_conversion)]
2205            let wn: i16 = match self.wn.try_into() {
2206                Ok(wn) => wn,
2207                Err(e) => return Some(Err(e.into())),
2208            };
2209            let gps_time = match time::GpsTime::new(wn, tow_s) {
2210                Ok(gps_time) => gps_time,
2211                Err(e) => return Some(Err(e.into())),
2212            };
2213            Some(Ok(time::MessageTime::Rover(gps_time.into())))
2214        }
2215    }
2216
2217    impl FriendlyName for MsgGpsTimeGnss {
2218        fn friendly_name() -> &'static str {
2219            "GPS TIME GNSS-only"
2220        }
2221    }
2222
2223    impl TryFrom<Sbp> for MsgGpsTimeGnss {
2224        type Error = TryFromSbpError;
2225        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
2226            match msg {
2227                Sbp::MsgGpsTimeGnss(m) => Ok(m),
2228                _ => Err(TryFromSbpError(msg)),
2229            }
2230        }
2231    }
2232
2233    impl WireFormat for MsgGpsTimeGnss {
2234        const MIN_LEN: usize = <u16 as WireFormat>::MIN_LEN
2235            + <u32 as WireFormat>::MIN_LEN
2236            + <i32 as WireFormat>::MIN_LEN
2237            + <u8 as WireFormat>::MIN_LEN;
2238        fn len(&self) -> usize {
2239            WireFormat::len(&self.wn)
2240                + WireFormat::len(&self.tow)
2241                + WireFormat::len(&self.ns_residual)
2242                + WireFormat::len(&self.flags)
2243        }
2244        fn write<B: BufMut>(&self, buf: &mut B) {
2245            WireFormat::write(&self.wn, buf);
2246            WireFormat::write(&self.tow, buf);
2247            WireFormat::write(&self.ns_residual, buf);
2248            WireFormat::write(&self.flags, buf);
2249        }
2250        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
2251            MsgGpsTimeGnss {
2252                sender_id: None,
2253                wn: WireFormat::parse_unchecked(buf),
2254                tow: WireFormat::parse_unchecked(buf),
2255                ns_residual: WireFormat::parse_unchecked(buf),
2256                flags: WireFormat::parse_unchecked(buf),
2257            }
2258        }
2259    }
2260
2261    /// Time source
2262    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2263    pub enum TimeSource {
2264        /// None (invalid)
2265        None = 0,
2266
2267        /// GNSS Solution
2268        GnssSolution = 1,
2269
2270        /// Propagated
2271        Propagated = 2,
2272    }
2273
2274    impl std::fmt::Display for TimeSource {
2275        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2276            match self {
2277                TimeSource::None => f.write_str("None (invalid)"),
2278                TimeSource::GnssSolution => f.write_str("GNSS Solution"),
2279                TimeSource::Propagated => f.write_str("Propagated"),
2280            }
2281        }
2282    }
2283
2284    impl TryFrom<u8> for TimeSource {
2285        type Error = u8;
2286        fn try_from(i: u8) -> Result<Self, u8> {
2287            match i {
2288                0 => Ok(TimeSource::None),
2289                1 => Ok(TimeSource::GnssSolution),
2290                2 => Ok(TimeSource::Propagated),
2291                i => Err(i),
2292            }
2293        }
2294    }
2295}
2296
2297pub mod msg_pose_relative {
2298    #![allow(unused_imports)]
2299
2300    use super::*;
2301    use crate::messages::lib::*;
2302
2303    /// Relative Pose
2304    ///
2305    /// This solution message reports the relative pose of a sensor between two
2306    /// time instances. The relative pose comprises of a rotation and a
2307    /// translation which relates the sensor (e.g. camera) frame at a given time
2308    /// (first keyframe) to the sensor frame at another time (second keyframe).
2309    /// The relative translations is a 3x1 vector described in the first keyframe.
2310    /// Relative rotation is described by a quaternion from second keyframe to the
2311    /// first keyframe.
2312    ///
2313    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2314    #[allow(clippy::derive_partial_eq_without_eq)]
2315    #[derive(Debug, PartialEq, Clone)]
2316    pub struct MsgPoseRelative {
2317        /// The message sender_id
2318        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
2319        pub sender_id: Option<u16>,
2320        /// GPS Time of Week
2321        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
2322        pub tow: u32,
2323        /// ID of the sensor producing this message
2324        #[cfg_attr(feature = "serde", serde(rename = "sensor_id"))]
2325        pub sensor_id: u8,
2326        /// Timestamp of first keyframe
2327        #[cfg_attr(feature = "serde", serde(rename = "timestamp_1"))]
2328        pub timestamp_1: u32,
2329        /// Timestamp of second keyframe
2330        #[cfg_attr(feature = "serde", serde(rename = "timestamp_2"))]
2331        pub timestamp_2: u32,
2332        /// Relative translation \[x,y,z\] described in first keyframe
2333        #[cfg_attr(feature = "serde", serde(rename = "trans"))]
2334        pub trans: [i32; 3],
2335        /// Real component of quaternion to describe relative rotation (second to
2336        /// first keyframe)
2337        #[cfg_attr(feature = "serde", serde(rename = "w"))]
2338        pub w: i32,
2339        /// 1st imaginary component of quaternion to describe relative rotation
2340        /// (second to first keyframe)
2341        #[cfg_attr(feature = "serde", serde(rename = "x"))]
2342        pub x: i32,
2343        /// 2nd imaginary component of quaternion to describe relative rotation
2344        /// (second to first keyframe)
2345        #[cfg_attr(feature = "serde", serde(rename = "y"))]
2346        pub y: i32,
2347        /// 3rd imaginary component of quaternion to describe relative rotation
2348        /// (second to first keyframe)
2349        #[cfg_attr(feature = "serde", serde(rename = "z"))]
2350        pub z: i32,
2351        /// Estimated variance of x (relative translation)
2352        #[cfg_attr(feature = "serde", serde(rename = "cov_r_x_x"))]
2353        pub cov_r_x_x: f32,
2354        /// Covariance of x and y (relative translation)
2355        #[cfg_attr(feature = "serde", serde(rename = "cov_r_x_y"))]
2356        pub cov_r_x_y: f32,
2357        /// Covariance of x and z (relative translation)
2358        #[cfg_attr(feature = "serde", serde(rename = "cov_r_x_z"))]
2359        pub cov_r_x_z: f32,
2360        /// Estimated variance of y (relative translation)
2361        #[cfg_attr(feature = "serde", serde(rename = "cov_r_y_y"))]
2362        pub cov_r_y_y: f32,
2363        /// Covariance of y and z (relative translation)
2364        #[cfg_attr(feature = "serde", serde(rename = "cov_r_y_z"))]
2365        pub cov_r_y_z: f32,
2366        /// Estimated variance of z (relative translation)
2367        #[cfg_attr(feature = "serde", serde(rename = "cov_r_z_z"))]
2368        pub cov_r_z_z: f32,
2369        /// Estimated variance of x (relative rotation)
2370        #[cfg_attr(feature = "serde", serde(rename = "cov_c_x_x"))]
2371        pub cov_c_x_x: f32,
2372        /// Covariance of x and y (relative rotation)
2373        #[cfg_attr(feature = "serde", serde(rename = "cov_c_x_y"))]
2374        pub cov_c_x_y: f32,
2375        /// Covariance of x and z (relative rotation)
2376        #[cfg_attr(feature = "serde", serde(rename = "cov_c_x_z"))]
2377        pub cov_c_x_z: f32,
2378        /// Estimated variance of y (relative rotation)
2379        #[cfg_attr(feature = "serde", serde(rename = "cov_c_y_y"))]
2380        pub cov_c_y_y: f32,
2381        /// Covariance of y and z (relative rotation)
2382        #[cfg_attr(feature = "serde", serde(rename = "cov_c_y_z"))]
2383        pub cov_c_y_z: f32,
2384        /// Estimated variance of z (relative rotation)
2385        #[cfg_attr(feature = "serde", serde(rename = "cov_c_z_z"))]
2386        pub cov_c_z_z: f32,
2387        /// Status flags of relative translation and rotation
2388        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
2389        pub flags: u8,
2390    }
2391
2392    impl MsgPoseRelative {
2393        /// Gets the [TimeSource][self::TimeSource] stored in the `flags` bitfield.
2394        ///
2395        /// Returns `Ok` if the bitrange contains a known `TimeSource` variant.
2396        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
2397        /// or because new variants of `TimeSource` were added.
2398        pub fn time_source(&self) -> Result<TimeSource, u8> {
2399            get_bit_range!(self.flags, u8, u8, 5, 4).try_into()
2400        }
2401
2402        /// Set the bitrange corresponding to the [TimeSource][TimeSource] of the `flags` bitfield.
2403        pub fn set_time_source(&mut self, time_source: TimeSource) {
2404            set_bit_range!(&mut self.flags, time_source, u8, u8, 5, 4);
2405        }
2406
2407        /// Gets the [RelativeTranslationStatus][self::RelativeTranslationStatus] stored in the `flags` bitfield.
2408        ///
2409        /// Returns `Ok` if the bitrange contains a known `RelativeTranslationStatus` variant.
2410        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
2411        /// or because new variants of `RelativeTranslationStatus` were added.
2412        pub fn relative_translation_status(&self) -> Result<RelativeTranslationStatus, u8> {
2413            get_bit_range!(self.flags, u8, u8, 3, 2).try_into()
2414        }
2415
2416        /// Set the bitrange corresponding to the [RelativeTranslationStatus][RelativeTranslationStatus] of the `flags` bitfield.
2417        pub fn set_relative_translation_status(
2418            &mut self,
2419            relative_translation_status: RelativeTranslationStatus,
2420        ) {
2421            set_bit_range!(&mut self.flags, relative_translation_status, u8, u8, 3, 2);
2422        }
2423
2424        /// Gets the [RelativeRotationStatus][self::RelativeRotationStatus] stored in the `flags` bitfield.
2425        ///
2426        /// Returns `Ok` if the bitrange contains a known `RelativeRotationStatus` variant.
2427        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
2428        /// or because new variants of `RelativeRotationStatus` were added.
2429        pub fn relative_rotation_status(&self) -> Result<RelativeRotationStatus, u8> {
2430            get_bit_range!(self.flags, u8, u8, 1, 0).try_into()
2431        }
2432
2433        /// Set the bitrange corresponding to the [RelativeRotationStatus][RelativeRotationStatus] of the `flags` bitfield.
2434        pub fn set_relative_rotation_status(
2435            &mut self,
2436            relative_rotation_status: RelativeRotationStatus,
2437        ) {
2438            set_bit_range!(&mut self.flags, relative_rotation_status, u8, u8, 1, 0);
2439        }
2440    }
2441
2442    impl ConcreteMessage for MsgPoseRelative {
2443        const MESSAGE_TYPE: u16 = 581;
2444        const MESSAGE_NAME: &'static str = "MSG_POSE_RELATIVE";
2445    }
2446
2447    impl SbpMessage for MsgPoseRelative {
2448        fn message_name(&self) -> &'static str {
2449            <Self as ConcreteMessage>::MESSAGE_NAME
2450        }
2451        fn message_type(&self) -> Option<u16> {
2452            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
2453        }
2454        fn sender_id(&self) -> Option<u16> {
2455            self.sender_id
2456        }
2457        fn set_sender_id(&mut self, new_id: u16) {
2458            self.sender_id = Some(new_id);
2459        }
2460        fn encoded_len(&self) -> usize {
2461            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
2462        }
2463        fn is_valid(&self) -> bool {
2464            true
2465        }
2466        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
2467            Ok(self)
2468        }
2469
2470        #[cfg(feature = "swiftnav")]
2471        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
2472            if self.time_source().ok()? == TimeSource::None {
2473                return None;
2474            }
2475            let tow_s = (self.tow as f64) / 1000.0;
2476            let gps_time = match time::GpsTime::new(0, tow_s) {
2477                Ok(gps_time) => gps_time.tow(),
2478                Err(e) => return Some(Err(e.into())),
2479            };
2480            Some(Ok(time::MessageTime::Rover(gps_time.into())))
2481        }
2482    }
2483
2484    impl FriendlyName for MsgPoseRelative {
2485        fn friendly_name() -> &'static str {
2486            "POSE RELATIVE"
2487        }
2488    }
2489
2490    impl TryFrom<Sbp> for MsgPoseRelative {
2491        type Error = TryFromSbpError;
2492        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
2493            match msg {
2494                Sbp::MsgPoseRelative(m) => Ok(m),
2495                _ => Err(TryFromSbpError(msg)),
2496            }
2497        }
2498    }
2499
2500    impl WireFormat for MsgPoseRelative {
2501        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
2502            + <u8 as WireFormat>::MIN_LEN
2503            + <u32 as WireFormat>::MIN_LEN
2504            + <u32 as WireFormat>::MIN_LEN
2505            + <[i32; 3] as WireFormat>::MIN_LEN
2506            + <i32 as WireFormat>::MIN_LEN
2507            + <i32 as WireFormat>::MIN_LEN
2508            + <i32 as WireFormat>::MIN_LEN
2509            + <i32 as WireFormat>::MIN_LEN
2510            + <f32 as WireFormat>::MIN_LEN
2511            + <f32 as WireFormat>::MIN_LEN
2512            + <f32 as WireFormat>::MIN_LEN
2513            + <f32 as WireFormat>::MIN_LEN
2514            + <f32 as WireFormat>::MIN_LEN
2515            + <f32 as WireFormat>::MIN_LEN
2516            + <f32 as WireFormat>::MIN_LEN
2517            + <f32 as WireFormat>::MIN_LEN
2518            + <f32 as WireFormat>::MIN_LEN
2519            + <f32 as WireFormat>::MIN_LEN
2520            + <f32 as WireFormat>::MIN_LEN
2521            + <f32 as WireFormat>::MIN_LEN
2522            + <u8 as WireFormat>::MIN_LEN;
2523        fn len(&self) -> usize {
2524            WireFormat::len(&self.tow)
2525                + WireFormat::len(&self.sensor_id)
2526                + WireFormat::len(&self.timestamp_1)
2527                + WireFormat::len(&self.timestamp_2)
2528                + WireFormat::len(&self.trans)
2529                + WireFormat::len(&self.w)
2530                + WireFormat::len(&self.x)
2531                + WireFormat::len(&self.y)
2532                + WireFormat::len(&self.z)
2533                + WireFormat::len(&self.cov_r_x_x)
2534                + WireFormat::len(&self.cov_r_x_y)
2535                + WireFormat::len(&self.cov_r_x_z)
2536                + WireFormat::len(&self.cov_r_y_y)
2537                + WireFormat::len(&self.cov_r_y_z)
2538                + WireFormat::len(&self.cov_r_z_z)
2539                + WireFormat::len(&self.cov_c_x_x)
2540                + WireFormat::len(&self.cov_c_x_y)
2541                + WireFormat::len(&self.cov_c_x_z)
2542                + WireFormat::len(&self.cov_c_y_y)
2543                + WireFormat::len(&self.cov_c_y_z)
2544                + WireFormat::len(&self.cov_c_z_z)
2545                + WireFormat::len(&self.flags)
2546        }
2547        fn write<B: BufMut>(&self, buf: &mut B) {
2548            WireFormat::write(&self.tow, buf);
2549            WireFormat::write(&self.sensor_id, buf);
2550            WireFormat::write(&self.timestamp_1, buf);
2551            WireFormat::write(&self.timestamp_2, buf);
2552            WireFormat::write(&self.trans, buf);
2553            WireFormat::write(&self.w, buf);
2554            WireFormat::write(&self.x, buf);
2555            WireFormat::write(&self.y, buf);
2556            WireFormat::write(&self.z, buf);
2557            WireFormat::write(&self.cov_r_x_x, buf);
2558            WireFormat::write(&self.cov_r_x_y, buf);
2559            WireFormat::write(&self.cov_r_x_z, buf);
2560            WireFormat::write(&self.cov_r_y_y, buf);
2561            WireFormat::write(&self.cov_r_y_z, buf);
2562            WireFormat::write(&self.cov_r_z_z, buf);
2563            WireFormat::write(&self.cov_c_x_x, buf);
2564            WireFormat::write(&self.cov_c_x_y, buf);
2565            WireFormat::write(&self.cov_c_x_z, buf);
2566            WireFormat::write(&self.cov_c_y_y, buf);
2567            WireFormat::write(&self.cov_c_y_z, buf);
2568            WireFormat::write(&self.cov_c_z_z, buf);
2569            WireFormat::write(&self.flags, buf);
2570        }
2571        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
2572            MsgPoseRelative {
2573                sender_id: None,
2574                tow: WireFormat::parse_unchecked(buf),
2575                sensor_id: WireFormat::parse_unchecked(buf),
2576                timestamp_1: WireFormat::parse_unchecked(buf),
2577                timestamp_2: WireFormat::parse_unchecked(buf),
2578                trans: WireFormat::parse_unchecked(buf),
2579                w: WireFormat::parse_unchecked(buf),
2580                x: WireFormat::parse_unchecked(buf),
2581                y: WireFormat::parse_unchecked(buf),
2582                z: WireFormat::parse_unchecked(buf),
2583                cov_r_x_x: WireFormat::parse_unchecked(buf),
2584                cov_r_x_y: WireFormat::parse_unchecked(buf),
2585                cov_r_x_z: WireFormat::parse_unchecked(buf),
2586                cov_r_y_y: WireFormat::parse_unchecked(buf),
2587                cov_r_y_z: WireFormat::parse_unchecked(buf),
2588                cov_r_z_z: WireFormat::parse_unchecked(buf),
2589                cov_c_x_x: WireFormat::parse_unchecked(buf),
2590                cov_c_x_y: WireFormat::parse_unchecked(buf),
2591                cov_c_x_z: WireFormat::parse_unchecked(buf),
2592                cov_c_y_y: WireFormat::parse_unchecked(buf),
2593                cov_c_y_z: WireFormat::parse_unchecked(buf),
2594                cov_c_z_z: WireFormat::parse_unchecked(buf),
2595                flags: WireFormat::parse_unchecked(buf),
2596            }
2597        }
2598    }
2599
2600    /// Time source
2601    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2602    pub enum TimeSource {
2603        /// None (invalid)
2604        None = 0,
2605
2606        /// GNSS Solution (ms in week)
2607        GnssSolution = 1,
2608
2609        /// Local CPU Time (ms)
2610        LocalCpuTime = 2,
2611    }
2612
2613    impl std::fmt::Display for TimeSource {
2614        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2615            match self {
2616                TimeSource::None => f.write_str("None (invalid)"),
2617                TimeSource::GnssSolution => f.write_str("GNSS Solution (ms in week)"),
2618                TimeSource::LocalCpuTime => f.write_str("Local CPU Time (ms)"),
2619            }
2620        }
2621    }
2622
2623    impl TryFrom<u8> for TimeSource {
2624        type Error = u8;
2625        fn try_from(i: u8) -> Result<Self, u8> {
2626            match i {
2627                0 => Ok(TimeSource::None),
2628                1 => Ok(TimeSource::GnssSolution),
2629                2 => Ok(TimeSource::LocalCpuTime),
2630                i => Err(i),
2631            }
2632        }
2633    }
2634
2635    /// Relative translation status
2636    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2637    pub enum RelativeTranslationStatus {
2638        /// Invalid
2639        Invalid = 0,
2640
2641        /// Valid
2642        Valid = 1,
2643    }
2644
2645    impl std::fmt::Display for RelativeTranslationStatus {
2646        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2647            match self {
2648                RelativeTranslationStatus::Invalid => f.write_str("Invalid"),
2649                RelativeTranslationStatus::Valid => f.write_str("Valid"),
2650            }
2651        }
2652    }
2653
2654    impl TryFrom<u8> for RelativeTranslationStatus {
2655        type Error = u8;
2656        fn try_from(i: u8) -> Result<Self, u8> {
2657            match i {
2658                0 => Ok(RelativeTranslationStatus::Invalid),
2659                1 => Ok(RelativeTranslationStatus::Valid),
2660                i => Err(i),
2661            }
2662        }
2663    }
2664
2665    /// Relative rotation status
2666    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2667    pub enum RelativeRotationStatus {
2668        /// Invalid
2669        Invalid = 0,
2670
2671        /// Valid
2672        Valid = 1,
2673    }
2674
2675    impl std::fmt::Display for RelativeRotationStatus {
2676        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2677            match self {
2678                RelativeRotationStatus::Invalid => f.write_str("Invalid"),
2679                RelativeRotationStatus::Valid => f.write_str("Valid"),
2680            }
2681        }
2682    }
2683
2684    impl TryFrom<u8> for RelativeRotationStatus {
2685        type Error = u8;
2686        fn try_from(i: u8) -> Result<Self, u8> {
2687            match i {
2688                0 => Ok(RelativeRotationStatus::Invalid),
2689                1 => Ok(RelativeRotationStatus::Valid),
2690                i => Err(i),
2691            }
2692        }
2693    }
2694}
2695
2696pub mod msg_pos_ecef {
2697    #![allow(unused_imports)]
2698
2699    use super::*;
2700    use crate::messages::lib::*;
2701
2702    /// Position in ECEF
2703    ///
2704    /// The position solution message reports absolute Earth Centered Earth Fixed
2705    /// (ECEF) coordinates and the status (single point vs pseudo-absolute RTK) of
2706    /// the position solution. If the rover receiver knows the surveyed position
2707    /// of the base station and has an RTK solution, this reports a pseudo-
2708    /// absolute position solution using the base station position and the rover's
2709    /// RTK baseline vector. The full GPS time is given by the preceding
2710    /// MSG_GPS_TIME with the matching time-of-week (tow).
2711    ///
2712    /// The values in this message are from GNSS measurements fused with inertial
2713    /// measurements. To get values from GNSS measurements only use
2714    /// MSG_POS_ECEF_GNSS.
2715    ///
2716    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2717    #[allow(clippy::derive_partial_eq_without_eq)]
2718    #[derive(Debug, PartialEq, Clone)]
2719    pub struct MsgPosEcef {
2720        /// The message sender_id
2721        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
2722        pub sender_id: Option<u16>,
2723        /// GPS Time of Week
2724        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
2725        pub tow: u32,
2726        /// ECEF X coordinate
2727        #[cfg_attr(feature = "serde", serde(rename = "x"))]
2728        pub x: f64,
2729        /// ECEF Y coordinate
2730        #[cfg_attr(feature = "serde", serde(rename = "y"))]
2731        pub y: f64,
2732        /// ECEF Z coordinate
2733        #[cfg_attr(feature = "serde", serde(rename = "z"))]
2734        pub z: f64,
2735        /// Position estimated standard deviation
2736        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
2737        pub accuracy: u16,
2738        /// Number of satellites used in solution
2739        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
2740        pub n_sats: u8,
2741        /// Status flags
2742        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
2743        pub flags: u8,
2744    }
2745
2746    impl MsgPosEcef {
2747        /// Gets the [TowType][self::TowType] stored in the `flags` bitfield.
2748        ///
2749        /// Returns `Ok` if the bitrange contains a known `TowType` variant.
2750        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
2751        /// or because new variants of `TowType` were added.
2752        pub fn tow_type(&self) -> Result<TowType, u8> {
2753            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
2754        }
2755
2756        /// Set the bitrange corresponding to the [TowType][TowType] of the `flags` bitfield.
2757        pub fn set_tow_type(&mut self, tow_type: TowType) {
2758            set_bit_range!(&mut self.flags, tow_type, u8, u8, 5, 5);
2759        }
2760
2761        /// Gets the [InertialNavigationMode][self::InertialNavigationMode] stored in the `flags` bitfield.
2762        ///
2763        /// Returns `Ok` if the bitrange contains a known `InertialNavigationMode` variant.
2764        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
2765        /// or because new variants of `InertialNavigationMode` were added.
2766        pub fn inertial_navigation_mode(&self) -> Result<InertialNavigationMode, u8> {
2767            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
2768        }
2769
2770        /// Set the bitrange corresponding to the [InertialNavigationMode][InertialNavigationMode] of the `flags` bitfield.
2771        pub fn set_inertial_navigation_mode(
2772            &mut self,
2773            inertial_navigation_mode: InertialNavigationMode,
2774        ) {
2775            set_bit_range!(&mut self.flags, inertial_navigation_mode, u8, u8, 4, 3);
2776        }
2777
2778        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
2779        ///
2780        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
2781        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
2782        /// or because new variants of `FixMode` were added.
2783        pub fn fix_mode(&self) -> Result<FixMode, u8> {
2784            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
2785        }
2786
2787        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
2788        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
2789            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
2790        }
2791    }
2792
2793    impl ConcreteMessage for MsgPosEcef {
2794        const MESSAGE_TYPE: u16 = 521;
2795        const MESSAGE_NAME: &'static str = "MSG_POS_ECEF";
2796    }
2797
2798    impl SbpMessage for MsgPosEcef {
2799        fn message_name(&self) -> &'static str {
2800            <Self as ConcreteMessage>::MESSAGE_NAME
2801        }
2802        fn message_type(&self) -> Option<u16> {
2803            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
2804        }
2805        fn sender_id(&self) -> Option<u16> {
2806            self.sender_id
2807        }
2808        fn set_sender_id(&mut self, new_id: u16) {
2809            self.sender_id = Some(new_id);
2810        }
2811        fn encoded_len(&self) -> usize {
2812            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
2813        }
2814        fn is_valid(&self) -> bool {
2815            true
2816        }
2817        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
2818            Ok(self)
2819        }
2820
2821        #[cfg(feature = "swiftnav")]
2822        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
2823            let tow_s = (self.tow as f64) / 1000.0;
2824            let gps_time = match time::GpsTime::new(0, tow_s) {
2825                Ok(gps_time) => gps_time.tow(),
2826                Err(e) => return Some(Err(e.into())),
2827            };
2828            Some(Ok(time::MessageTime::Rover(gps_time.into())))
2829        }
2830    }
2831
2832    impl FriendlyName for MsgPosEcef {
2833        fn friendly_name() -> &'static str {
2834            "POS ECEF"
2835        }
2836    }
2837
2838    impl TryFrom<Sbp> for MsgPosEcef {
2839        type Error = TryFromSbpError;
2840        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
2841            match msg {
2842                Sbp::MsgPosEcef(m) => Ok(m),
2843                _ => Err(TryFromSbpError(msg)),
2844            }
2845        }
2846    }
2847
2848    impl WireFormat for MsgPosEcef {
2849        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
2850            + <f64 as WireFormat>::MIN_LEN
2851            + <f64 as WireFormat>::MIN_LEN
2852            + <f64 as WireFormat>::MIN_LEN
2853            + <u16 as WireFormat>::MIN_LEN
2854            + <u8 as WireFormat>::MIN_LEN
2855            + <u8 as WireFormat>::MIN_LEN;
2856        fn len(&self) -> usize {
2857            WireFormat::len(&self.tow)
2858                + WireFormat::len(&self.x)
2859                + WireFormat::len(&self.y)
2860                + WireFormat::len(&self.z)
2861                + WireFormat::len(&self.accuracy)
2862                + WireFormat::len(&self.n_sats)
2863                + WireFormat::len(&self.flags)
2864        }
2865        fn write<B: BufMut>(&self, buf: &mut B) {
2866            WireFormat::write(&self.tow, buf);
2867            WireFormat::write(&self.x, buf);
2868            WireFormat::write(&self.y, buf);
2869            WireFormat::write(&self.z, buf);
2870            WireFormat::write(&self.accuracy, buf);
2871            WireFormat::write(&self.n_sats, buf);
2872            WireFormat::write(&self.flags, buf);
2873        }
2874        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
2875            MsgPosEcef {
2876                sender_id: None,
2877                tow: WireFormat::parse_unchecked(buf),
2878                x: WireFormat::parse_unchecked(buf),
2879                y: WireFormat::parse_unchecked(buf),
2880                z: WireFormat::parse_unchecked(buf),
2881                accuracy: WireFormat::parse_unchecked(buf),
2882                n_sats: WireFormat::parse_unchecked(buf),
2883                flags: WireFormat::parse_unchecked(buf),
2884            }
2885        }
2886    }
2887
2888    /// TOW type
2889    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2890    pub enum TowType {
2891        /// Time of Measurement
2892        TimeOfMeasurement = 0,
2893
2894        /// Other
2895        Other = 1,
2896    }
2897
2898    impl std::fmt::Display for TowType {
2899        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2900            match self {
2901                TowType::TimeOfMeasurement => f.write_str("Time of Measurement"),
2902                TowType::Other => f.write_str("Other"),
2903            }
2904        }
2905    }
2906
2907    impl TryFrom<u8> for TowType {
2908        type Error = u8;
2909        fn try_from(i: u8) -> Result<Self, u8> {
2910            match i {
2911                0 => Ok(TowType::TimeOfMeasurement),
2912                1 => Ok(TowType::Other),
2913                i => Err(i),
2914            }
2915        }
2916    }
2917
2918    /// Inertial Navigation Mode
2919    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2920    pub enum InertialNavigationMode {
2921        /// None
2922        None = 0,
2923
2924        /// INS used
2925        InsUsed = 1,
2926    }
2927
2928    impl std::fmt::Display for InertialNavigationMode {
2929        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2930            match self {
2931                InertialNavigationMode::None => f.write_str("None"),
2932                InertialNavigationMode::InsUsed => f.write_str("INS used"),
2933            }
2934        }
2935    }
2936
2937    impl TryFrom<u8> for InertialNavigationMode {
2938        type Error = u8;
2939        fn try_from(i: u8) -> Result<Self, u8> {
2940            match i {
2941                0 => Ok(InertialNavigationMode::None),
2942                1 => Ok(InertialNavigationMode::InsUsed),
2943                i => Err(i),
2944            }
2945        }
2946    }
2947
2948    /// Fix mode
2949    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2950    pub enum FixMode {
2951        /// Invalid
2952        Invalid = 0,
2953
2954        /// Single Point Position (SPP)
2955        SinglePointPosition = 1,
2956
2957        /// Differential GNSS (DGNSS)
2958        DifferentialGnss = 2,
2959
2960        /// Float RTK
2961        FloatRtk = 3,
2962
2963        /// Fixed RTK
2964        FixedRtk = 4,
2965
2966        /// Dead Reckoning
2967        DeadReckoning = 5,
2968
2969        /// SBAS Position
2970        SbasPosition = 6,
2971    }
2972
2973    impl std::fmt::Display for FixMode {
2974        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2975            match self {
2976                FixMode::Invalid => f.write_str("Invalid"),
2977                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
2978                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
2979                FixMode::FloatRtk => f.write_str("Float RTK"),
2980                FixMode::FixedRtk => f.write_str("Fixed RTK"),
2981                FixMode::DeadReckoning => f.write_str("Dead Reckoning"),
2982                FixMode::SbasPosition => f.write_str("SBAS Position"),
2983            }
2984        }
2985    }
2986
2987    impl TryFrom<u8> for FixMode {
2988        type Error = u8;
2989        fn try_from(i: u8) -> Result<Self, u8> {
2990            match i {
2991                0 => Ok(FixMode::Invalid),
2992                1 => Ok(FixMode::SinglePointPosition),
2993                2 => Ok(FixMode::DifferentialGnss),
2994                3 => Ok(FixMode::FloatRtk),
2995                4 => Ok(FixMode::FixedRtk),
2996                5 => Ok(FixMode::DeadReckoning),
2997                6 => Ok(FixMode::SbasPosition),
2998                i => Err(i),
2999            }
3000        }
3001    }
3002}
3003
3004pub mod msg_pos_ecef_cov {
3005    #![allow(unused_imports)]
3006
3007    use super::*;
3008    use crate::messages::lib::*;
3009
3010    /// Position in ECEF with Covariances
3011    ///
3012    /// The position solution message reports absolute Earth Centered Earth Fixed
3013    /// (ECEF) coordinates and the status (single point vs pseudo-absolute RTK) of
3014    /// the position solution. The message also reports the upper triangular
3015    /// portion of the 3x3 covariance matrix. If the receiver knows the surveyed
3016    /// position of the base station and has an RTK solution, this reports a
3017    /// pseudo-absolute position solution using the base station position and the
3018    /// rover's RTK baseline vector. The full GPS time is given by the preceding
3019    /// MSG_GPS_TIME with the matching time-of-week (tow).
3020    ///
3021    /// The values in this message are from GNSS measurements fused with inertial
3022    /// measurements. To get values from GNSS measurements only use
3023    /// MSG_POS_ECEF_COV_GNSS.
3024    ///
3025    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3026    #[allow(clippy::derive_partial_eq_without_eq)]
3027    #[derive(Debug, PartialEq, Clone)]
3028    pub struct MsgPosEcefCov {
3029        /// The message sender_id
3030        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
3031        pub sender_id: Option<u16>,
3032        /// GPS Time of Week
3033        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
3034        pub tow: u32,
3035        /// ECEF X coordinate
3036        #[cfg_attr(feature = "serde", serde(rename = "x"))]
3037        pub x: f64,
3038        /// ECEF Y coordinate
3039        #[cfg_attr(feature = "serde", serde(rename = "y"))]
3040        pub y: f64,
3041        /// ECEF Z coordinate
3042        #[cfg_attr(feature = "serde", serde(rename = "z"))]
3043        pub z: f64,
3044        /// Estimated variance of x
3045        #[cfg_attr(feature = "serde", serde(rename = "cov_x_x"))]
3046        pub cov_x_x: f32,
3047        /// Estimated covariance of x and y
3048        #[cfg_attr(feature = "serde", serde(rename = "cov_x_y"))]
3049        pub cov_x_y: f32,
3050        /// Estimated covariance of x and z
3051        #[cfg_attr(feature = "serde", serde(rename = "cov_x_z"))]
3052        pub cov_x_z: f32,
3053        /// Estimated variance of y
3054        #[cfg_attr(feature = "serde", serde(rename = "cov_y_y"))]
3055        pub cov_y_y: f32,
3056        /// Estimated covariance of y and z
3057        #[cfg_attr(feature = "serde", serde(rename = "cov_y_z"))]
3058        pub cov_y_z: f32,
3059        /// Estimated variance of z
3060        #[cfg_attr(feature = "serde", serde(rename = "cov_z_z"))]
3061        pub cov_z_z: f32,
3062        /// Number of satellites used in solution
3063        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
3064        pub n_sats: u8,
3065        /// Status flags
3066        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
3067        pub flags: u8,
3068    }
3069
3070    impl MsgPosEcefCov {
3071        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
3072        ///
3073        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
3074        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3075        /// or because new variants of `TypeOfReportedTow` were added.
3076        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
3077            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
3078        }
3079
3080        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
3081        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
3082            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
3083        }
3084
3085        /// Gets the [InertialNavigationMode][self::InertialNavigationMode] stored in the `flags` bitfield.
3086        ///
3087        /// Returns `Ok` if the bitrange contains a known `InertialNavigationMode` variant.
3088        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3089        /// or because new variants of `InertialNavigationMode` were added.
3090        pub fn inertial_navigation_mode(&self) -> Result<InertialNavigationMode, u8> {
3091            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
3092        }
3093
3094        /// Set the bitrange corresponding to the [InertialNavigationMode][InertialNavigationMode] of the `flags` bitfield.
3095        pub fn set_inertial_navigation_mode(
3096            &mut self,
3097            inertial_navigation_mode: InertialNavigationMode,
3098        ) {
3099            set_bit_range!(&mut self.flags, inertial_navigation_mode, u8, u8, 4, 3);
3100        }
3101
3102        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
3103        ///
3104        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
3105        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3106        /// or because new variants of `FixMode` were added.
3107        pub fn fix_mode(&self) -> Result<FixMode, u8> {
3108            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
3109        }
3110
3111        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
3112        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
3113            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
3114        }
3115    }
3116
3117    impl ConcreteMessage for MsgPosEcefCov {
3118        const MESSAGE_TYPE: u16 = 532;
3119        const MESSAGE_NAME: &'static str = "MSG_POS_ECEF_COV";
3120    }
3121
3122    impl SbpMessage for MsgPosEcefCov {
3123        fn message_name(&self) -> &'static str {
3124            <Self as ConcreteMessage>::MESSAGE_NAME
3125        }
3126        fn message_type(&self) -> Option<u16> {
3127            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
3128        }
3129        fn sender_id(&self) -> Option<u16> {
3130            self.sender_id
3131        }
3132        fn set_sender_id(&mut self, new_id: u16) {
3133            self.sender_id = Some(new_id);
3134        }
3135        fn encoded_len(&self) -> usize {
3136            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
3137        }
3138        fn is_valid(&self) -> bool {
3139            true
3140        }
3141        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
3142            Ok(self)
3143        }
3144
3145        #[cfg(feature = "swiftnav")]
3146        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
3147            let tow_s = (self.tow as f64) / 1000.0;
3148            let gps_time = match time::GpsTime::new(0, tow_s) {
3149                Ok(gps_time) => gps_time.tow(),
3150                Err(e) => return Some(Err(e.into())),
3151            };
3152            Some(Ok(time::MessageTime::Rover(gps_time.into())))
3153        }
3154    }
3155
3156    impl FriendlyName for MsgPosEcefCov {
3157        fn friendly_name() -> &'static str {
3158            "POS ECEF COV"
3159        }
3160    }
3161
3162    impl TryFrom<Sbp> for MsgPosEcefCov {
3163        type Error = TryFromSbpError;
3164        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
3165            match msg {
3166                Sbp::MsgPosEcefCov(m) => Ok(m),
3167                _ => Err(TryFromSbpError(msg)),
3168            }
3169        }
3170    }
3171
3172    impl WireFormat for MsgPosEcefCov {
3173        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
3174            + <f64 as WireFormat>::MIN_LEN
3175            + <f64 as WireFormat>::MIN_LEN
3176            + <f64 as WireFormat>::MIN_LEN
3177            + <f32 as WireFormat>::MIN_LEN
3178            + <f32 as WireFormat>::MIN_LEN
3179            + <f32 as WireFormat>::MIN_LEN
3180            + <f32 as WireFormat>::MIN_LEN
3181            + <f32 as WireFormat>::MIN_LEN
3182            + <f32 as WireFormat>::MIN_LEN
3183            + <u8 as WireFormat>::MIN_LEN
3184            + <u8 as WireFormat>::MIN_LEN;
3185        fn len(&self) -> usize {
3186            WireFormat::len(&self.tow)
3187                + WireFormat::len(&self.x)
3188                + WireFormat::len(&self.y)
3189                + WireFormat::len(&self.z)
3190                + WireFormat::len(&self.cov_x_x)
3191                + WireFormat::len(&self.cov_x_y)
3192                + WireFormat::len(&self.cov_x_z)
3193                + WireFormat::len(&self.cov_y_y)
3194                + WireFormat::len(&self.cov_y_z)
3195                + WireFormat::len(&self.cov_z_z)
3196                + WireFormat::len(&self.n_sats)
3197                + WireFormat::len(&self.flags)
3198        }
3199        fn write<B: BufMut>(&self, buf: &mut B) {
3200            WireFormat::write(&self.tow, buf);
3201            WireFormat::write(&self.x, buf);
3202            WireFormat::write(&self.y, buf);
3203            WireFormat::write(&self.z, buf);
3204            WireFormat::write(&self.cov_x_x, buf);
3205            WireFormat::write(&self.cov_x_y, buf);
3206            WireFormat::write(&self.cov_x_z, buf);
3207            WireFormat::write(&self.cov_y_y, buf);
3208            WireFormat::write(&self.cov_y_z, buf);
3209            WireFormat::write(&self.cov_z_z, buf);
3210            WireFormat::write(&self.n_sats, buf);
3211            WireFormat::write(&self.flags, buf);
3212        }
3213        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
3214            MsgPosEcefCov {
3215                sender_id: None,
3216                tow: WireFormat::parse_unchecked(buf),
3217                x: WireFormat::parse_unchecked(buf),
3218                y: WireFormat::parse_unchecked(buf),
3219                z: WireFormat::parse_unchecked(buf),
3220                cov_x_x: WireFormat::parse_unchecked(buf),
3221                cov_x_y: WireFormat::parse_unchecked(buf),
3222                cov_x_z: WireFormat::parse_unchecked(buf),
3223                cov_y_y: WireFormat::parse_unchecked(buf),
3224                cov_y_z: WireFormat::parse_unchecked(buf),
3225                cov_z_z: WireFormat::parse_unchecked(buf),
3226                n_sats: WireFormat::parse_unchecked(buf),
3227                flags: WireFormat::parse_unchecked(buf),
3228            }
3229        }
3230    }
3231
3232    /// Type of reported TOW
3233    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3234    pub enum TypeOfReportedTow {
3235        /// Time of Measurement
3236        TimeOfMeasurement = 0,
3237
3238        /// Other
3239        Other = 1,
3240    }
3241
3242    impl std::fmt::Display for TypeOfReportedTow {
3243        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3244            match self {
3245                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
3246                TypeOfReportedTow::Other => f.write_str("Other"),
3247            }
3248        }
3249    }
3250
3251    impl TryFrom<u8> for TypeOfReportedTow {
3252        type Error = u8;
3253        fn try_from(i: u8) -> Result<Self, u8> {
3254            match i {
3255                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
3256                1 => Ok(TypeOfReportedTow::Other),
3257                i => Err(i),
3258            }
3259        }
3260    }
3261
3262    /// Inertial Navigation Mode
3263    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3264    pub enum InertialNavigationMode {
3265        /// None
3266        None = 0,
3267
3268        /// INS used
3269        InsUsed = 1,
3270    }
3271
3272    impl std::fmt::Display for InertialNavigationMode {
3273        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3274            match self {
3275                InertialNavigationMode::None => f.write_str("None"),
3276                InertialNavigationMode::InsUsed => f.write_str("INS used"),
3277            }
3278        }
3279    }
3280
3281    impl TryFrom<u8> for InertialNavigationMode {
3282        type Error = u8;
3283        fn try_from(i: u8) -> Result<Self, u8> {
3284            match i {
3285                0 => Ok(InertialNavigationMode::None),
3286                1 => Ok(InertialNavigationMode::InsUsed),
3287                i => Err(i),
3288            }
3289        }
3290    }
3291
3292    /// Fix mode
3293    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3294    pub enum FixMode {
3295        /// Invalid
3296        Invalid = 0,
3297
3298        /// Single Point Position (SPP)
3299        SinglePointPosition = 1,
3300
3301        /// Differential GNSS (DGNSS)
3302        DifferentialGnss = 2,
3303
3304        /// Float RTK
3305        FloatRtk = 3,
3306
3307        /// Fixed RTK
3308        FixedRtk = 4,
3309
3310        /// Dead Reckoning
3311        DeadReckoning = 5,
3312
3313        /// SBAS Position
3314        SbasPosition = 6,
3315    }
3316
3317    impl std::fmt::Display for FixMode {
3318        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3319            match self {
3320                FixMode::Invalid => f.write_str("Invalid"),
3321                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
3322                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
3323                FixMode::FloatRtk => f.write_str("Float RTK"),
3324                FixMode::FixedRtk => f.write_str("Fixed RTK"),
3325                FixMode::DeadReckoning => f.write_str("Dead Reckoning"),
3326                FixMode::SbasPosition => f.write_str("SBAS Position"),
3327            }
3328        }
3329    }
3330
3331    impl TryFrom<u8> for FixMode {
3332        type Error = u8;
3333        fn try_from(i: u8) -> Result<Self, u8> {
3334            match i {
3335                0 => Ok(FixMode::Invalid),
3336                1 => Ok(FixMode::SinglePointPosition),
3337                2 => Ok(FixMode::DifferentialGnss),
3338                3 => Ok(FixMode::FloatRtk),
3339                4 => Ok(FixMode::FixedRtk),
3340                5 => Ok(FixMode::DeadReckoning),
3341                6 => Ok(FixMode::SbasPosition),
3342                i => Err(i),
3343            }
3344        }
3345    }
3346}
3347
3348pub mod msg_pos_ecef_cov_gnss {
3349    #![allow(unused_imports)]
3350
3351    use super::*;
3352    use crate::messages::lib::*;
3353
3354    /// GNSS-only Position in ECEF with Covariances
3355    ///
3356    /// The position solution message reports absolute Earth Centered Earth Fixed
3357    /// (ECEF) coordinates and the status (single point vs pseudo-absolute RTK) of
3358    /// the position solution. The message also reports the upper triangular
3359    /// portion of the 3x3 covariance matrix. If the receiver knows the surveyed
3360    /// position of the base station and has an RTK solution, this reports a
3361    /// pseudo-absolute position solution using the base station position and the
3362    /// rover's RTK baseline vector. The full GPS time is given by the preceding
3363    /// MSG_GPS_TIME_GNSS with the matching time-of-week (tow).
3364    ///
3365    /// The values in this message are from GNSS measurements only. To get values
3366    /// fused with inertial measurements use MSG_POS_ECEF_COV.
3367    ///
3368    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3369    #[allow(clippy::derive_partial_eq_without_eq)]
3370    #[derive(Debug, PartialEq, Clone)]
3371    pub struct MsgPosEcefCovGnss {
3372        /// The message sender_id
3373        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
3374        pub sender_id: Option<u16>,
3375        /// GPS Time of Week
3376        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
3377        pub tow: u32,
3378        /// ECEF X coordinate
3379        #[cfg_attr(feature = "serde", serde(rename = "x"))]
3380        pub x: f64,
3381        /// ECEF Y coordinate
3382        #[cfg_attr(feature = "serde", serde(rename = "y"))]
3383        pub y: f64,
3384        /// ECEF Z coordinate
3385        #[cfg_attr(feature = "serde", serde(rename = "z"))]
3386        pub z: f64,
3387        /// Estimated variance of x
3388        #[cfg_attr(feature = "serde", serde(rename = "cov_x_x"))]
3389        pub cov_x_x: f32,
3390        /// Estimated covariance of x and y
3391        #[cfg_attr(feature = "serde", serde(rename = "cov_x_y"))]
3392        pub cov_x_y: f32,
3393        /// Estimated covariance of x and z
3394        #[cfg_attr(feature = "serde", serde(rename = "cov_x_z"))]
3395        pub cov_x_z: f32,
3396        /// Estimated variance of y
3397        #[cfg_attr(feature = "serde", serde(rename = "cov_y_y"))]
3398        pub cov_y_y: f32,
3399        /// Estimated covariance of y and z
3400        #[cfg_attr(feature = "serde", serde(rename = "cov_y_z"))]
3401        pub cov_y_z: f32,
3402        /// Estimated variance of z
3403        #[cfg_attr(feature = "serde", serde(rename = "cov_z_z"))]
3404        pub cov_z_z: f32,
3405        /// Number of satellites used in solution
3406        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
3407        pub n_sats: u8,
3408        /// Status flags
3409        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
3410        pub flags: u8,
3411    }
3412
3413    impl MsgPosEcefCovGnss {
3414        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
3415        ///
3416        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
3417        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3418        /// or because new variants of `FixMode` were added.
3419        pub fn fix_mode(&self) -> Result<FixMode, u8> {
3420            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
3421        }
3422
3423        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
3424        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
3425            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
3426        }
3427    }
3428
3429    impl ConcreteMessage for MsgPosEcefCovGnss {
3430        const MESSAGE_TYPE: u16 = 564;
3431        const MESSAGE_NAME: &'static str = "MSG_POS_ECEF_COV_GNSS";
3432    }
3433
3434    impl SbpMessage for MsgPosEcefCovGnss {
3435        fn message_name(&self) -> &'static str {
3436            <Self as ConcreteMessage>::MESSAGE_NAME
3437        }
3438        fn message_type(&self) -> Option<u16> {
3439            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
3440        }
3441        fn sender_id(&self) -> Option<u16> {
3442            self.sender_id
3443        }
3444        fn set_sender_id(&mut self, new_id: u16) {
3445            self.sender_id = Some(new_id);
3446        }
3447        fn encoded_len(&self) -> usize {
3448            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
3449        }
3450        fn is_valid(&self) -> bool {
3451            true
3452        }
3453        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
3454            Ok(self)
3455        }
3456
3457        #[cfg(feature = "swiftnav")]
3458        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
3459            let tow_s = (self.tow as f64) / 1000.0;
3460            let gps_time = match time::GpsTime::new(0, tow_s) {
3461                Ok(gps_time) => gps_time.tow(),
3462                Err(e) => return Some(Err(e.into())),
3463            };
3464            Some(Ok(time::MessageTime::Rover(gps_time.into())))
3465        }
3466    }
3467
3468    impl FriendlyName for MsgPosEcefCovGnss {
3469        fn friendly_name() -> &'static str {
3470            "POS ECEF COV GNSS-only"
3471        }
3472    }
3473
3474    impl TryFrom<Sbp> for MsgPosEcefCovGnss {
3475        type Error = TryFromSbpError;
3476        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
3477            match msg {
3478                Sbp::MsgPosEcefCovGnss(m) => Ok(m),
3479                _ => Err(TryFromSbpError(msg)),
3480            }
3481        }
3482    }
3483
3484    impl WireFormat for MsgPosEcefCovGnss {
3485        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
3486            + <f64 as WireFormat>::MIN_LEN
3487            + <f64 as WireFormat>::MIN_LEN
3488            + <f64 as WireFormat>::MIN_LEN
3489            + <f32 as WireFormat>::MIN_LEN
3490            + <f32 as WireFormat>::MIN_LEN
3491            + <f32 as WireFormat>::MIN_LEN
3492            + <f32 as WireFormat>::MIN_LEN
3493            + <f32 as WireFormat>::MIN_LEN
3494            + <f32 as WireFormat>::MIN_LEN
3495            + <u8 as WireFormat>::MIN_LEN
3496            + <u8 as WireFormat>::MIN_LEN;
3497        fn len(&self) -> usize {
3498            WireFormat::len(&self.tow)
3499                + WireFormat::len(&self.x)
3500                + WireFormat::len(&self.y)
3501                + WireFormat::len(&self.z)
3502                + WireFormat::len(&self.cov_x_x)
3503                + WireFormat::len(&self.cov_x_y)
3504                + WireFormat::len(&self.cov_x_z)
3505                + WireFormat::len(&self.cov_y_y)
3506                + WireFormat::len(&self.cov_y_z)
3507                + WireFormat::len(&self.cov_z_z)
3508                + WireFormat::len(&self.n_sats)
3509                + WireFormat::len(&self.flags)
3510        }
3511        fn write<B: BufMut>(&self, buf: &mut B) {
3512            WireFormat::write(&self.tow, buf);
3513            WireFormat::write(&self.x, buf);
3514            WireFormat::write(&self.y, buf);
3515            WireFormat::write(&self.z, buf);
3516            WireFormat::write(&self.cov_x_x, buf);
3517            WireFormat::write(&self.cov_x_y, buf);
3518            WireFormat::write(&self.cov_x_z, buf);
3519            WireFormat::write(&self.cov_y_y, buf);
3520            WireFormat::write(&self.cov_y_z, buf);
3521            WireFormat::write(&self.cov_z_z, buf);
3522            WireFormat::write(&self.n_sats, buf);
3523            WireFormat::write(&self.flags, buf);
3524        }
3525        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
3526            MsgPosEcefCovGnss {
3527                sender_id: None,
3528                tow: WireFormat::parse_unchecked(buf),
3529                x: WireFormat::parse_unchecked(buf),
3530                y: WireFormat::parse_unchecked(buf),
3531                z: WireFormat::parse_unchecked(buf),
3532                cov_x_x: WireFormat::parse_unchecked(buf),
3533                cov_x_y: WireFormat::parse_unchecked(buf),
3534                cov_x_z: WireFormat::parse_unchecked(buf),
3535                cov_y_y: WireFormat::parse_unchecked(buf),
3536                cov_y_z: WireFormat::parse_unchecked(buf),
3537                cov_z_z: WireFormat::parse_unchecked(buf),
3538                n_sats: WireFormat::parse_unchecked(buf),
3539                flags: WireFormat::parse_unchecked(buf),
3540            }
3541        }
3542    }
3543
3544    /// Fix mode
3545    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3546    pub enum FixMode {
3547        /// Invalid
3548        Invalid = 0,
3549
3550        /// Single Point Position (SPP)
3551        SinglePointPosition = 1,
3552
3553        /// Differential GNSS (DGNSS)
3554        DifferentialGnss = 2,
3555
3556        /// Float RTK
3557        FloatRtk = 3,
3558
3559        /// Fixed RTK
3560        FixedRtk = 4,
3561
3562        /// SBAS Position
3563        SbasPosition = 6,
3564    }
3565
3566    impl std::fmt::Display for FixMode {
3567        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3568            match self {
3569                FixMode::Invalid => f.write_str("Invalid"),
3570                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
3571                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
3572                FixMode::FloatRtk => f.write_str("Float RTK"),
3573                FixMode::FixedRtk => f.write_str("Fixed RTK"),
3574                FixMode::SbasPosition => f.write_str("SBAS Position"),
3575            }
3576        }
3577    }
3578
3579    impl TryFrom<u8> for FixMode {
3580        type Error = u8;
3581        fn try_from(i: u8) -> Result<Self, u8> {
3582            match i {
3583                0 => Ok(FixMode::Invalid),
3584                1 => Ok(FixMode::SinglePointPosition),
3585                2 => Ok(FixMode::DifferentialGnss),
3586                3 => Ok(FixMode::FloatRtk),
3587                4 => Ok(FixMode::FixedRtk),
3588                6 => Ok(FixMode::SbasPosition),
3589                i => Err(i),
3590            }
3591        }
3592    }
3593}
3594
3595pub mod msg_pos_ecef_dep_a {
3596    #![allow(unused_imports)]
3597
3598    use super::*;
3599    use crate::messages::lib::*;
3600
3601    /// Deprecated
3602    ///
3603    /// Deprecated.
3604    ///
3605    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3606    #[allow(clippy::derive_partial_eq_without_eq)]
3607    #[derive(Debug, PartialEq, Clone)]
3608    pub struct MsgPosEcefDepA {
3609        /// The message sender_id
3610        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
3611        pub sender_id: Option<u16>,
3612        /// GPS Time of Week
3613        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
3614        pub tow: u32,
3615        /// ECEF X coordinate
3616        #[cfg_attr(feature = "serde", serde(rename = "x"))]
3617        pub x: f64,
3618        /// ECEF Y coordinate
3619        #[cfg_attr(feature = "serde", serde(rename = "y"))]
3620        pub y: f64,
3621        /// ECEF Z coordinate
3622        #[cfg_attr(feature = "serde", serde(rename = "z"))]
3623        pub z: f64,
3624        /// Position accuracy estimate (not implemented). Defaults to 0.
3625        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
3626        pub accuracy: u16,
3627        /// Number of satellites used in solution
3628        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
3629        pub n_sats: u8,
3630        /// Status flags
3631        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
3632        pub flags: u8,
3633    }
3634
3635    impl MsgPosEcefDepA {
3636        /// Gets the [RaimRepairFlag][self::RaimRepairFlag] stored in the `flags` bitfield.
3637        ///
3638        /// Returns `Ok` if the bitrange contains a known `RaimRepairFlag` variant.
3639        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3640        /// or because new variants of `RaimRepairFlag` were added.
3641        pub fn raim_repair_flag(&self) -> Result<RaimRepairFlag, u8> {
3642            get_bit_range!(self.flags, u8, u8, 4, 4).try_into()
3643        }
3644
3645        /// Set the bitrange corresponding to the [RaimRepairFlag][RaimRepairFlag] of the `flags` bitfield.
3646        pub fn set_raim_repair_flag(&mut self, raim_repair_flag: RaimRepairFlag) {
3647            set_bit_range!(&mut self.flags, raim_repair_flag, u8, u8, 4, 4);
3648        }
3649
3650        /// Gets the [RaimAvailabilityFlag][self::RaimAvailabilityFlag] stored in the `flags` bitfield.
3651        ///
3652        /// Returns `Ok` if the bitrange contains a known `RaimAvailabilityFlag` variant.
3653        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3654        /// or because new variants of `RaimAvailabilityFlag` were added.
3655        pub fn raim_availability_flag(&self) -> Result<RaimAvailabilityFlag, u8> {
3656            get_bit_range!(self.flags, u8, u8, 3, 3).try_into()
3657        }
3658
3659        /// Set the bitrange corresponding to the [RaimAvailabilityFlag][RaimAvailabilityFlag] of the `flags` bitfield.
3660        pub fn set_raim_availability_flag(&mut self, raim_availability_flag: RaimAvailabilityFlag) {
3661            set_bit_range!(&mut self.flags, raim_availability_flag, u8, u8, 3, 3);
3662        }
3663
3664        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
3665        ///
3666        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
3667        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3668        /// or because new variants of `FixMode` were added.
3669        pub fn fix_mode(&self) -> Result<FixMode, u8> {
3670            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
3671        }
3672
3673        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
3674        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
3675            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
3676        }
3677    }
3678
3679    impl ConcreteMessage for MsgPosEcefDepA {
3680        const MESSAGE_TYPE: u16 = 512;
3681        const MESSAGE_NAME: &'static str = "MSG_POS_ECEF_DEP_A";
3682    }
3683
3684    impl SbpMessage for MsgPosEcefDepA {
3685        fn message_name(&self) -> &'static str {
3686            <Self as ConcreteMessage>::MESSAGE_NAME
3687        }
3688        fn message_type(&self) -> Option<u16> {
3689            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
3690        }
3691        fn sender_id(&self) -> Option<u16> {
3692            self.sender_id
3693        }
3694        fn set_sender_id(&mut self, new_id: u16) {
3695            self.sender_id = Some(new_id);
3696        }
3697        fn encoded_len(&self) -> usize {
3698            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
3699        }
3700        fn is_valid(&self) -> bool {
3701            true
3702        }
3703        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
3704            Ok(self)
3705        }
3706
3707        #[cfg(feature = "swiftnav")]
3708        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
3709            let tow_s = (self.tow as f64) / 1000.0;
3710            let gps_time = match time::GpsTime::new(0, tow_s) {
3711                Ok(gps_time) => gps_time.tow(),
3712                Err(e) => return Some(Err(e.into())),
3713            };
3714            Some(Ok(time::MessageTime::Rover(gps_time.into())))
3715        }
3716    }
3717
3718    impl FriendlyName for MsgPosEcefDepA {
3719        fn friendly_name() -> &'static str {
3720            "POS ECEF DEP A"
3721        }
3722    }
3723
3724    impl TryFrom<Sbp> for MsgPosEcefDepA {
3725        type Error = TryFromSbpError;
3726        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
3727            match msg {
3728                Sbp::MsgPosEcefDepA(m) => Ok(m),
3729                _ => Err(TryFromSbpError(msg)),
3730            }
3731        }
3732    }
3733
3734    impl WireFormat for MsgPosEcefDepA {
3735        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
3736            + <f64 as WireFormat>::MIN_LEN
3737            + <f64 as WireFormat>::MIN_LEN
3738            + <f64 as WireFormat>::MIN_LEN
3739            + <u16 as WireFormat>::MIN_LEN
3740            + <u8 as WireFormat>::MIN_LEN
3741            + <u8 as WireFormat>::MIN_LEN;
3742        fn len(&self) -> usize {
3743            WireFormat::len(&self.tow)
3744                + WireFormat::len(&self.x)
3745                + WireFormat::len(&self.y)
3746                + WireFormat::len(&self.z)
3747                + WireFormat::len(&self.accuracy)
3748                + WireFormat::len(&self.n_sats)
3749                + WireFormat::len(&self.flags)
3750        }
3751        fn write<B: BufMut>(&self, buf: &mut B) {
3752            WireFormat::write(&self.tow, buf);
3753            WireFormat::write(&self.x, buf);
3754            WireFormat::write(&self.y, buf);
3755            WireFormat::write(&self.z, buf);
3756            WireFormat::write(&self.accuracy, buf);
3757            WireFormat::write(&self.n_sats, buf);
3758            WireFormat::write(&self.flags, buf);
3759        }
3760        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
3761            MsgPosEcefDepA {
3762                sender_id: None,
3763                tow: WireFormat::parse_unchecked(buf),
3764                x: WireFormat::parse_unchecked(buf),
3765                y: WireFormat::parse_unchecked(buf),
3766                z: WireFormat::parse_unchecked(buf),
3767                accuracy: WireFormat::parse_unchecked(buf),
3768                n_sats: WireFormat::parse_unchecked(buf),
3769                flags: WireFormat::parse_unchecked(buf),
3770            }
3771        }
3772    }
3773
3774    /// RAIM repair flag
3775    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3776    pub enum RaimRepairFlag {
3777        /// No repair
3778        NoRepair = 0,
3779
3780        /// Solution came from RAIM repair
3781        SolutionCameFromRaimRepair = 1,
3782    }
3783
3784    impl std::fmt::Display for RaimRepairFlag {
3785        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3786            match self {
3787                RaimRepairFlag::NoRepair => f.write_str("No repair"),
3788                RaimRepairFlag::SolutionCameFromRaimRepair => {
3789                    f.write_str("Solution came from RAIM repair")
3790                }
3791            }
3792        }
3793    }
3794
3795    impl TryFrom<u8> for RaimRepairFlag {
3796        type Error = u8;
3797        fn try_from(i: u8) -> Result<Self, u8> {
3798            match i {
3799                0 => Ok(RaimRepairFlag::NoRepair),
3800                1 => Ok(RaimRepairFlag::SolutionCameFromRaimRepair),
3801                i => Err(i),
3802            }
3803        }
3804    }
3805
3806    /// RAIM availability flag
3807    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3808    pub enum RaimAvailabilityFlag {
3809        /// RAIM check was explicitly disabled or unavailable
3810        RaimCheckWasExplicitlyDisabledOrUnavailable = 0,
3811
3812        /// RAIM check was available
3813        RaimCheckWasAvailable = 1,
3814    }
3815
3816    impl std::fmt::Display for RaimAvailabilityFlag {
3817        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3818            match self {
3819                RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable => {
3820                    f.write_str("RAIM check was explicitly disabled or unavailable")
3821                }
3822                RaimAvailabilityFlag::RaimCheckWasAvailable => {
3823                    f.write_str("RAIM check was available")
3824                }
3825            }
3826        }
3827    }
3828
3829    impl TryFrom<u8> for RaimAvailabilityFlag {
3830        type Error = u8;
3831        fn try_from(i: u8) -> Result<Self, u8> {
3832            match i {
3833                0 => Ok(RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable),
3834                1 => Ok(RaimAvailabilityFlag::RaimCheckWasAvailable),
3835                i => Err(i),
3836            }
3837        }
3838    }
3839
3840    /// Fix mode
3841    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3842    pub enum FixMode {
3843        /// Single Point Positioning (SPP)
3844        SinglePointPositioning = 0,
3845
3846        /// Fixed RTK
3847        FixedRtk = 1,
3848
3849        /// Float RTK
3850        FloatRtk = 2,
3851    }
3852
3853    impl std::fmt::Display for FixMode {
3854        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3855            match self {
3856                FixMode::SinglePointPositioning => f.write_str("Single Point Positioning (SPP)"),
3857                FixMode::FixedRtk => f.write_str("Fixed RTK"),
3858                FixMode::FloatRtk => f.write_str("Float RTK"),
3859            }
3860        }
3861    }
3862
3863    impl TryFrom<u8> for FixMode {
3864        type Error = u8;
3865        fn try_from(i: u8) -> Result<Self, u8> {
3866            match i {
3867                0 => Ok(FixMode::SinglePointPositioning),
3868                1 => Ok(FixMode::FixedRtk),
3869                2 => Ok(FixMode::FloatRtk),
3870                i => Err(i),
3871            }
3872        }
3873    }
3874}
3875
3876pub mod msg_pos_ecef_gnss {
3877    #![allow(unused_imports)]
3878
3879    use super::*;
3880    use crate::messages::lib::*;
3881
3882    /// GNSS-only Position in ECEF
3883    ///
3884    /// The position solution message reports absolute Earth Centered Earth Fixed
3885    /// (ECEF) coordinates and the status (single point vs pseudo-absolute RTK) of
3886    /// the position solution. If the rover receiver knows the surveyed position
3887    /// of the base station and has an RTK solution, this reports a pseudo-
3888    /// absolute position solution using the base station position and the rover's
3889    /// RTK baseline vector. The full GPS time is given by the preceding
3890    /// MSG_GPS_TIME_GNSS with the matching time-of-week (tow).
3891    ///
3892    /// The values in this message are from GNSS measurements only. To get values
3893    /// fused with inertial measurements use MSG_POS_ECEF.
3894    ///
3895    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3896    #[allow(clippy::derive_partial_eq_without_eq)]
3897    #[derive(Debug, PartialEq, Clone)]
3898    pub struct MsgPosEcefGnss {
3899        /// The message sender_id
3900        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
3901        pub sender_id: Option<u16>,
3902        /// GPS Time of Week
3903        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
3904        pub tow: u32,
3905        /// ECEF X coordinate
3906        #[cfg_attr(feature = "serde", serde(rename = "x"))]
3907        pub x: f64,
3908        /// ECEF Y coordinate
3909        #[cfg_attr(feature = "serde", serde(rename = "y"))]
3910        pub y: f64,
3911        /// ECEF Z coordinate
3912        #[cfg_attr(feature = "serde", serde(rename = "z"))]
3913        pub z: f64,
3914        /// Position estimated standard deviation
3915        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
3916        pub accuracy: u16,
3917        /// Number of satellites used in solution
3918        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
3919        pub n_sats: u8,
3920        /// Status flags
3921        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
3922        pub flags: u8,
3923    }
3924
3925    impl MsgPosEcefGnss {
3926        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
3927        ///
3928        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
3929        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
3930        /// or because new variants of `FixMode` were added.
3931        pub fn fix_mode(&self) -> Result<FixMode, u8> {
3932            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
3933        }
3934
3935        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
3936        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
3937            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
3938        }
3939    }
3940
3941    impl ConcreteMessage for MsgPosEcefGnss {
3942        const MESSAGE_TYPE: u16 = 553;
3943        const MESSAGE_NAME: &'static str = "MSG_POS_ECEF_GNSS";
3944    }
3945
3946    impl SbpMessage for MsgPosEcefGnss {
3947        fn message_name(&self) -> &'static str {
3948            <Self as ConcreteMessage>::MESSAGE_NAME
3949        }
3950        fn message_type(&self) -> Option<u16> {
3951            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
3952        }
3953        fn sender_id(&self) -> Option<u16> {
3954            self.sender_id
3955        }
3956        fn set_sender_id(&mut self, new_id: u16) {
3957            self.sender_id = Some(new_id);
3958        }
3959        fn encoded_len(&self) -> usize {
3960            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
3961        }
3962        fn is_valid(&self) -> bool {
3963            true
3964        }
3965        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
3966            Ok(self)
3967        }
3968
3969        #[cfg(feature = "swiftnav")]
3970        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
3971            let tow_s = (self.tow as f64) / 1000.0;
3972            let gps_time = match time::GpsTime::new(0, tow_s) {
3973                Ok(gps_time) => gps_time.tow(),
3974                Err(e) => return Some(Err(e.into())),
3975            };
3976            Some(Ok(time::MessageTime::Rover(gps_time.into())))
3977        }
3978    }
3979
3980    impl FriendlyName for MsgPosEcefGnss {
3981        fn friendly_name() -> &'static str {
3982            "POS ECEF GNSS-only"
3983        }
3984    }
3985
3986    impl TryFrom<Sbp> for MsgPosEcefGnss {
3987        type Error = TryFromSbpError;
3988        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
3989            match msg {
3990                Sbp::MsgPosEcefGnss(m) => Ok(m),
3991                _ => Err(TryFromSbpError(msg)),
3992            }
3993        }
3994    }
3995
3996    impl WireFormat for MsgPosEcefGnss {
3997        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
3998            + <f64 as WireFormat>::MIN_LEN
3999            + <f64 as WireFormat>::MIN_LEN
4000            + <f64 as WireFormat>::MIN_LEN
4001            + <u16 as WireFormat>::MIN_LEN
4002            + <u8 as WireFormat>::MIN_LEN
4003            + <u8 as WireFormat>::MIN_LEN;
4004        fn len(&self) -> usize {
4005            WireFormat::len(&self.tow)
4006                + WireFormat::len(&self.x)
4007                + WireFormat::len(&self.y)
4008                + WireFormat::len(&self.z)
4009                + WireFormat::len(&self.accuracy)
4010                + WireFormat::len(&self.n_sats)
4011                + WireFormat::len(&self.flags)
4012        }
4013        fn write<B: BufMut>(&self, buf: &mut B) {
4014            WireFormat::write(&self.tow, buf);
4015            WireFormat::write(&self.x, buf);
4016            WireFormat::write(&self.y, buf);
4017            WireFormat::write(&self.z, buf);
4018            WireFormat::write(&self.accuracy, buf);
4019            WireFormat::write(&self.n_sats, buf);
4020            WireFormat::write(&self.flags, buf);
4021        }
4022        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
4023            MsgPosEcefGnss {
4024                sender_id: None,
4025                tow: WireFormat::parse_unchecked(buf),
4026                x: WireFormat::parse_unchecked(buf),
4027                y: WireFormat::parse_unchecked(buf),
4028                z: WireFormat::parse_unchecked(buf),
4029                accuracy: WireFormat::parse_unchecked(buf),
4030                n_sats: WireFormat::parse_unchecked(buf),
4031                flags: WireFormat::parse_unchecked(buf),
4032            }
4033        }
4034    }
4035
4036    /// Fix mode
4037    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4038    pub enum FixMode {
4039        /// Invalid
4040        Invalid = 0,
4041
4042        /// Single Point Position (SPP)
4043        SinglePointPosition = 1,
4044
4045        /// Differential GNSS (DGNSS)
4046        DifferentialGnss = 2,
4047
4048        /// Float RTK
4049        FloatRtk = 3,
4050
4051        /// Fixed RTK
4052        FixedRtk = 4,
4053
4054        /// SBAS Position
4055        SbasPosition = 6,
4056    }
4057
4058    impl std::fmt::Display for FixMode {
4059        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4060            match self {
4061                FixMode::Invalid => f.write_str("Invalid"),
4062                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
4063                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
4064                FixMode::FloatRtk => f.write_str("Float RTK"),
4065                FixMode::FixedRtk => f.write_str("Fixed RTK"),
4066                FixMode::SbasPosition => f.write_str("SBAS Position"),
4067            }
4068        }
4069    }
4070
4071    impl TryFrom<u8> for FixMode {
4072        type Error = u8;
4073        fn try_from(i: u8) -> Result<Self, u8> {
4074            match i {
4075                0 => Ok(FixMode::Invalid),
4076                1 => Ok(FixMode::SinglePointPosition),
4077                2 => Ok(FixMode::DifferentialGnss),
4078                3 => Ok(FixMode::FloatRtk),
4079                4 => Ok(FixMode::FixedRtk),
4080                6 => Ok(FixMode::SbasPosition),
4081                i => Err(i),
4082            }
4083        }
4084    }
4085}
4086
4087pub mod msg_pos_llh {
4088    #![allow(unused_imports)]
4089
4090    use super::*;
4091    use crate::messages::lib::*;
4092
4093    /// Geodetic Position
4094    ///
4095    /// This position solution message reports the absolute geodetic coordinates
4096    /// and the status (single point vs pseudo-absolute RTK) of the position
4097    /// solution. If the rover receiver knows the surveyed position of the base
4098    /// station and has an RTK solution, this reports a pseudo-absolute position
4099    /// solution using the base station position and the rover's RTK baseline
4100    /// vector. The full GPS time is given by the preceding MSG_GPS_TIME with the
4101    /// matching time-of-week (tow).
4102    ///
4103    /// The values in this message are from GNSS measurements fused with inertial
4104    /// measurements. To get values from GNSS measurements only use
4105    /// MSG_POS_LLH_GNSS.
4106    ///
4107    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4108    #[allow(clippy::derive_partial_eq_without_eq)]
4109    #[derive(Debug, PartialEq, Clone)]
4110    pub struct MsgPosLlh {
4111        /// The message sender_id
4112        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
4113        pub sender_id: Option<u16>,
4114        /// GPS Time of Week
4115        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
4116        pub tow: u32,
4117        /// Latitude
4118        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
4119        pub lat: f64,
4120        /// Longitude
4121        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
4122        pub lon: f64,
4123        /// Height above WGS84 ellipsoid
4124        #[cfg_attr(feature = "serde", serde(rename = "height"))]
4125        pub height: f64,
4126        /// Horizontal position estimated standard deviation
4127        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
4128        pub h_accuracy: u16,
4129        /// Vertical position estimated standard deviation
4130        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
4131        pub v_accuracy: u16,
4132        /// Number of satellites used in solution.
4133        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
4134        pub n_sats: u8,
4135        /// Status flags
4136        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
4137        pub flags: u8,
4138    }
4139
4140    impl MsgPosLlh {
4141        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
4142        ///
4143        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
4144        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4145        /// or because new variants of `TypeOfReportedTow` were added.
4146        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
4147            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
4148        }
4149
4150        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
4151        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
4152            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
4153        }
4154
4155        /// Gets the [InertialNavigationMode][self::InertialNavigationMode] stored in the `flags` bitfield.
4156        ///
4157        /// Returns `Ok` if the bitrange contains a known `InertialNavigationMode` variant.
4158        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4159        /// or because new variants of `InertialNavigationMode` were added.
4160        pub fn inertial_navigation_mode(&self) -> Result<InertialNavigationMode, u8> {
4161            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
4162        }
4163
4164        /// Set the bitrange corresponding to the [InertialNavigationMode][InertialNavigationMode] of the `flags` bitfield.
4165        pub fn set_inertial_navigation_mode(
4166            &mut self,
4167            inertial_navigation_mode: InertialNavigationMode,
4168        ) {
4169            set_bit_range!(&mut self.flags, inertial_navigation_mode, u8, u8, 4, 3);
4170        }
4171
4172        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
4173        ///
4174        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
4175        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4176        /// or because new variants of `FixMode` were added.
4177        pub fn fix_mode(&self) -> Result<FixMode, u8> {
4178            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
4179        }
4180
4181        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
4182        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
4183            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
4184        }
4185    }
4186
4187    impl ConcreteMessage for MsgPosLlh {
4188        const MESSAGE_TYPE: u16 = 522;
4189        const MESSAGE_NAME: &'static str = "MSG_POS_LLH";
4190    }
4191
4192    impl SbpMessage for MsgPosLlh {
4193        fn message_name(&self) -> &'static str {
4194            <Self as ConcreteMessage>::MESSAGE_NAME
4195        }
4196        fn message_type(&self) -> Option<u16> {
4197            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
4198        }
4199        fn sender_id(&self) -> Option<u16> {
4200            self.sender_id
4201        }
4202        fn set_sender_id(&mut self, new_id: u16) {
4203            self.sender_id = Some(new_id);
4204        }
4205        fn encoded_len(&self) -> usize {
4206            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
4207        }
4208        fn is_valid(&self) -> bool {
4209            true
4210        }
4211        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
4212            Ok(self)
4213        }
4214
4215        #[cfg(feature = "swiftnav")]
4216        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
4217            let tow_s = (self.tow as f64) / 1000.0;
4218            let gps_time = match time::GpsTime::new(0, tow_s) {
4219                Ok(gps_time) => gps_time.tow(),
4220                Err(e) => return Some(Err(e.into())),
4221            };
4222            Some(Ok(time::MessageTime::Rover(gps_time.into())))
4223        }
4224    }
4225
4226    impl FriendlyName for MsgPosLlh {
4227        fn friendly_name() -> &'static str {
4228            "POS LLH"
4229        }
4230    }
4231
4232    impl TryFrom<Sbp> for MsgPosLlh {
4233        type Error = TryFromSbpError;
4234        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
4235            match msg {
4236                Sbp::MsgPosLlh(m) => Ok(m),
4237                _ => Err(TryFromSbpError(msg)),
4238            }
4239        }
4240    }
4241
4242    impl WireFormat for MsgPosLlh {
4243        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
4244            + <f64 as WireFormat>::MIN_LEN
4245            + <f64 as WireFormat>::MIN_LEN
4246            + <f64 as WireFormat>::MIN_LEN
4247            + <u16 as WireFormat>::MIN_LEN
4248            + <u16 as WireFormat>::MIN_LEN
4249            + <u8 as WireFormat>::MIN_LEN
4250            + <u8 as WireFormat>::MIN_LEN;
4251        fn len(&self) -> usize {
4252            WireFormat::len(&self.tow)
4253                + WireFormat::len(&self.lat)
4254                + WireFormat::len(&self.lon)
4255                + WireFormat::len(&self.height)
4256                + WireFormat::len(&self.h_accuracy)
4257                + WireFormat::len(&self.v_accuracy)
4258                + WireFormat::len(&self.n_sats)
4259                + WireFormat::len(&self.flags)
4260        }
4261        fn write<B: BufMut>(&self, buf: &mut B) {
4262            WireFormat::write(&self.tow, buf);
4263            WireFormat::write(&self.lat, buf);
4264            WireFormat::write(&self.lon, buf);
4265            WireFormat::write(&self.height, buf);
4266            WireFormat::write(&self.h_accuracy, buf);
4267            WireFormat::write(&self.v_accuracy, buf);
4268            WireFormat::write(&self.n_sats, buf);
4269            WireFormat::write(&self.flags, buf);
4270        }
4271        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
4272            MsgPosLlh {
4273                sender_id: None,
4274                tow: WireFormat::parse_unchecked(buf),
4275                lat: WireFormat::parse_unchecked(buf),
4276                lon: WireFormat::parse_unchecked(buf),
4277                height: WireFormat::parse_unchecked(buf),
4278                h_accuracy: WireFormat::parse_unchecked(buf),
4279                v_accuracy: WireFormat::parse_unchecked(buf),
4280                n_sats: WireFormat::parse_unchecked(buf),
4281                flags: WireFormat::parse_unchecked(buf),
4282            }
4283        }
4284    }
4285
4286    /// Type of reported TOW
4287    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4288    pub enum TypeOfReportedTow {
4289        /// Time of Measurement
4290        TimeOfMeasurement = 0,
4291
4292        /// Other
4293        Other = 1,
4294    }
4295
4296    impl std::fmt::Display for TypeOfReportedTow {
4297        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4298            match self {
4299                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
4300                TypeOfReportedTow::Other => f.write_str("Other"),
4301            }
4302        }
4303    }
4304
4305    impl TryFrom<u8> for TypeOfReportedTow {
4306        type Error = u8;
4307        fn try_from(i: u8) -> Result<Self, u8> {
4308            match i {
4309                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
4310                1 => Ok(TypeOfReportedTow::Other),
4311                i => Err(i),
4312            }
4313        }
4314    }
4315
4316    /// Inertial Navigation Mode
4317    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4318    pub enum InertialNavigationMode {
4319        /// None
4320        None = 0,
4321
4322        /// INS used
4323        InsUsed = 1,
4324    }
4325
4326    impl std::fmt::Display for InertialNavigationMode {
4327        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4328            match self {
4329                InertialNavigationMode::None => f.write_str("None"),
4330                InertialNavigationMode::InsUsed => f.write_str("INS used"),
4331            }
4332        }
4333    }
4334
4335    impl TryFrom<u8> for InertialNavigationMode {
4336        type Error = u8;
4337        fn try_from(i: u8) -> Result<Self, u8> {
4338            match i {
4339                0 => Ok(InertialNavigationMode::None),
4340                1 => Ok(InertialNavigationMode::InsUsed),
4341                i => Err(i),
4342            }
4343        }
4344    }
4345
4346    /// Fix mode
4347    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4348    pub enum FixMode {
4349        /// Invalid
4350        Invalid = 0,
4351
4352        /// Single Point Position (SPP)
4353        SinglePointPosition = 1,
4354
4355        /// Differential GNSS (DGNSS)
4356        DifferentialGnss = 2,
4357
4358        /// Float RTK
4359        FloatRtk = 3,
4360
4361        /// Fixed RTK
4362        FixedRtk = 4,
4363
4364        /// Dead Reckoning
4365        DeadReckoning = 5,
4366
4367        /// SBAS Position
4368        SbasPosition = 6,
4369    }
4370
4371    impl std::fmt::Display for FixMode {
4372        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4373            match self {
4374                FixMode::Invalid => f.write_str("Invalid"),
4375                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
4376                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
4377                FixMode::FloatRtk => f.write_str("Float RTK"),
4378                FixMode::FixedRtk => f.write_str("Fixed RTK"),
4379                FixMode::DeadReckoning => f.write_str("Dead Reckoning"),
4380                FixMode::SbasPosition => f.write_str("SBAS Position"),
4381            }
4382        }
4383    }
4384
4385    impl TryFrom<u8> for FixMode {
4386        type Error = u8;
4387        fn try_from(i: u8) -> Result<Self, u8> {
4388            match i {
4389                0 => Ok(FixMode::Invalid),
4390                1 => Ok(FixMode::SinglePointPosition),
4391                2 => Ok(FixMode::DifferentialGnss),
4392                3 => Ok(FixMode::FloatRtk),
4393                4 => Ok(FixMode::FixedRtk),
4394                5 => Ok(FixMode::DeadReckoning),
4395                6 => Ok(FixMode::SbasPosition),
4396                i => Err(i),
4397            }
4398        }
4399    }
4400}
4401
4402pub mod msg_pos_llh_acc {
4403    #![allow(unused_imports)]
4404
4405    use super::*;
4406    use crate::messages::lib::*;
4407
4408    /// Geodetic Position and Accuracy
4409    ///
4410    /// This position solution message reports the absolute geodetic coordinates
4411    /// and the status (single point vs pseudo-absolute RTK) of the position
4412    /// solution as well as the estimated horizontal, vertical, cross-track and
4413    /// along-track errors.  The position information and Fix Mode flags  follow
4414    /// the MSG_POS_LLH message. Since the covariance matrix is computed in the
4415    /// local-level North, East, Down frame, the estimated error terms follow that
4416    /// convention.
4417    ///
4418    /// The estimated errors are reported at a user-configurable confidence level.
4419    /// The user-configured percentile is encoded in the percentile field.
4420    ///
4421    /// The values in this message are from GNSS measurements fused with inertial
4422    /// measurements.
4423    ///
4424    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4425    #[allow(clippy::derive_partial_eq_without_eq)]
4426    #[derive(Debug, PartialEq, Clone)]
4427    pub struct MsgPosLlhAcc {
4428        /// The message sender_id
4429        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
4430        pub sender_id: Option<u16>,
4431        /// GPS Time of Week
4432        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
4433        pub tow: u32,
4434        /// Latitude
4435        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
4436        pub lat: f64,
4437        /// Longitude
4438        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
4439        pub lon: f64,
4440        /// Height above WGS84 ellipsoid
4441        #[cfg_attr(feature = "serde", serde(rename = "height"))]
4442        pub height: f64,
4443        /// Height above the geoid (i.e. height above mean sea level). See
4444        /// confidence_and_geoid for geoid model used.
4445        #[cfg_attr(feature = "serde", serde(rename = "orthometric_height"))]
4446        pub orthometric_height: f64,
4447        /// Estimated horizontal error at the user-configured confidence level; zero
4448        /// implies invalid.
4449        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
4450        pub h_accuracy: f32,
4451        /// Estimated vertical error at the user-configured confidence level; zero
4452        /// implies invalid.
4453        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
4454        pub v_accuracy: f32,
4455        /// Estimated cross-track error at the user-configured confidence level;
4456        /// zero implies invalid.
4457        #[cfg_attr(feature = "serde", serde(rename = "ct_accuracy"))]
4458        pub ct_accuracy: f32,
4459        /// Estimated along-track error at the user-configured confidence level;
4460        /// zero implies invalid.
4461        #[cfg_attr(feature = "serde", serde(rename = "at_accuracy"))]
4462        pub at_accuracy: f32,
4463        /// The estimated horizontal error ellipse at the user-configured confidence
4464        /// level.
4465        #[cfg_attr(feature = "serde", serde(rename = "h_ellipse"))]
4466        pub h_ellipse: EstimatedHorizontalErrorEllipse,
4467        /// The lower bits describe the configured confidence level for the
4468        /// estimated position error. The middle bits describe the geoid model used
4469        /// to calculate the orthometric height.
4470        #[cfg_attr(feature = "serde", serde(rename = "confidence_and_geoid"))]
4471        pub confidence_and_geoid: u8,
4472        /// Number of satellites used in solution.
4473        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
4474        pub n_sats: u8,
4475        /// Status flags
4476        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
4477        pub flags: u8,
4478    }
4479
4480    impl MsgPosLlhAcc {
4481        /// Gets the [GeoidModel][self::GeoidModel] stored in the `confidence_and_geoid` bitfield.
4482        ///
4483        /// Returns `Ok` if the bitrange contains a known `GeoidModel` variant.
4484        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4485        /// or because new variants of `GeoidModel` were added.
4486        pub fn geoid_model(&self) -> Result<GeoidModel, u8> {
4487            get_bit_range!(self.confidence_and_geoid, u8, u8, 6, 4).try_into()
4488        }
4489
4490        /// Set the bitrange corresponding to the [GeoidModel][GeoidModel] of the `confidence_and_geoid` bitfield.
4491        pub fn set_geoid_model(&mut self, geoid_model: GeoidModel) {
4492            set_bit_range!(&mut self.confidence_and_geoid, geoid_model, u8, u8, 6, 4);
4493        }
4494
4495        /// Gets the [ConfidenceLevel][self::ConfidenceLevel] stored in the `confidence_and_geoid` bitfield.
4496        ///
4497        /// Returns `Ok` if the bitrange contains a known `ConfidenceLevel` variant.
4498        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4499        /// or because new variants of `ConfidenceLevel` were added.
4500        pub fn confidence_level(&self) -> Result<ConfidenceLevel, u8> {
4501            get_bit_range!(self.confidence_and_geoid, u8, u8, 3, 0).try_into()
4502        }
4503
4504        /// Set the bitrange corresponding to the [ConfidenceLevel][ConfidenceLevel] of the `confidence_and_geoid` bitfield.
4505        pub fn set_confidence_level(&mut self, confidence_level: ConfidenceLevel) {
4506            set_bit_range!(
4507                &mut self.confidence_and_geoid,
4508                confidence_level,
4509                u8,
4510                u8,
4511                3,
4512                0
4513            );
4514        }
4515
4516        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
4517        ///
4518        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
4519        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4520        /// or because new variants of `TypeOfReportedTow` were added.
4521        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
4522            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
4523        }
4524
4525        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
4526        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
4527            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
4528        }
4529
4530        /// Gets the [InertialNavigationMode][self::InertialNavigationMode] stored in the `flags` bitfield.
4531        ///
4532        /// Returns `Ok` if the bitrange contains a known `InertialNavigationMode` variant.
4533        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4534        /// or because new variants of `InertialNavigationMode` were added.
4535        pub fn inertial_navigation_mode(&self) -> Result<InertialNavigationMode, u8> {
4536            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
4537        }
4538
4539        /// Set the bitrange corresponding to the [InertialNavigationMode][InertialNavigationMode] of the `flags` bitfield.
4540        pub fn set_inertial_navigation_mode(
4541            &mut self,
4542            inertial_navigation_mode: InertialNavigationMode,
4543        ) {
4544            set_bit_range!(&mut self.flags, inertial_navigation_mode, u8, u8, 4, 3);
4545        }
4546
4547        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
4548        ///
4549        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
4550        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4551        /// or because new variants of `FixMode` were added.
4552        pub fn fix_mode(&self) -> Result<FixMode, u8> {
4553            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
4554        }
4555
4556        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
4557        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
4558            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
4559        }
4560    }
4561
4562    impl ConcreteMessage for MsgPosLlhAcc {
4563        const MESSAGE_TYPE: u16 = 536;
4564        const MESSAGE_NAME: &'static str = "MSG_POS_LLH_ACC";
4565    }
4566
4567    impl SbpMessage for MsgPosLlhAcc {
4568        fn message_name(&self) -> &'static str {
4569            <Self as ConcreteMessage>::MESSAGE_NAME
4570        }
4571        fn message_type(&self) -> Option<u16> {
4572            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
4573        }
4574        fn sender_id(&self) -> Option<u16> {
4575            self.sender_id
4576        }
4577        fn set_sender_id(&mut self, new_id: u16) {
4578            self.sender_id = Some(new_id);
4579        }
4580        fn encoded_len(&self) -> usize {
4581            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
4582        }
4583        fn is_valid(&self) -> bool {
4584            true
4585        }
4586        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
4587            Ok(self)
4588        }
4589
4590        #[cfg(feature = "swiftnav")]
4591        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
4592            let tow_s = (self.tow as f64) / 1000.0;
4593            let gps_time = match time::GpsTime::new(0, tow_s) {
4594                Ok(gps_time) => gps_time.tow(),
4595                Err(e) => return Some(Err(e.into())),
4596            };
4597            Some(Ok(time::MessageTime::Rover(gps_time.into())))
4598        }
4599    }
4600
4601    impl FriendlyName for MsgPosLlhAcc {
4602        fn friendly_name() -> &'static str {
4603            "POS LLH ACC"
4604        }
4605    }
4606
4607    impl TryFrom<Sbp> for MsgPosLlhAcc {
4608        type Error = TryFromSbpError;
4609        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
4610            match msg {
4611                Sbp::MsgPosLlhAcc(m) => Ok(m),
4612                _ => Err(TryFromSbpError(msg)),
4613            }
4614        }
4615    }
4616
4617    impl WireFormat for MsgPosLlhAcc {
4618        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
4619            + <f64 as WireFormat>::MIN_LEN
4620            + <f64 as WireFormat>::MIN_LEN
4621            + <f64 as WireFormat>::MIN_LEN
4622            + <f64 as WireFormat>::MIN_LEN
4623            + <f32 as WireFormat>::MIN_LEN
4624            + <f32 as WireFormat>::MIN_LEN
4625            + <f32 as WireFormat>::MIN_LEN
4626            + <f32 as WireFormat>::MIN_LEN
4627            + <EstimatedHorizontalErrorEllipse as WireFormat>::MIN_LEN
4628            + <u8 as WireFormat>::MIN_LEN
4629            + <u8 as WireFormat>::MIN_LEN
4630            + <u8 as WireFormat>::MIN_LEN;
4631        fn len(&self) -> usize {
4632            WireFormat::len(&self.tow)
4633                + WireFormat::len(&self.lat)
4634                + WireFormat::len(&self.lon)
4635                + WireFormat::len(&self.height)
4636                + WireFormat::len(&self.orthometric_height)
4637                + WireFormat::len(&self.h_accuracy)
4638                + WireFormat::len(&self.v_accuracy)
4639                + WireFormat::len(&self.ct_accuracy)
4640                + WireFormat::len(&self.at_accuracy)
4641                + WireFormat::len(&self.h_ellipse)
4642                + WireFormat::len(&self.confidence_and_geoid)
4643                + WireFormat::len(&self.n_sats)
4644                + WireFormat::len(&self.flags)
4645        }
4646        fn write<B: BufMut>(&self, buf: &mut B) {
4647            WireFormat::write(&self.tow, buf);
4648            WireFormat::write(&self.lat, buf);
4649            WireFormat::write(&self.lon, buf);
4650            WireFormat::write(&self.height, buf);
4651            WireFormat::write(&self.orthometric_height, buf);
4652            WireFormat::write(&self.h_accuracy, buf);
4653            WireFormat::write(&self.v_accuracy, buf);
4654            WireFormat::write(&self.ct_accuracy, buf);
4655            WireFormat::write(&self.at_accuracy, buf);
4656            WireFormat::write(&self.h_ellipse, buf);
4657            WireFormat::write(&self.confidence_and_geoid, buf);
4658            WireFormat::write(&self.n_sats, buf);
4659            WireFormat::write(&self.flags, buf);
4660        }
4661        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
4662            MsgPosLlhAcc {
4663                sender_id: None,
4664                tow: WireFormat::parse_unchecked(buf),
4665                lat: WireFormat::parse_unchecked(buf),
4666                lon: WireFormat::parse_unchecked(buf),
4667                height: WireFormat::parse_unchecked(buf),
4668                orthometric_height: WireFormat::parse_unchecked(buf),
4669                h_accuracy: WireFormat::parse_unchecked(buf),
4670                v_accuracy: WireFormat::parse_unchecked(buf),
4671                ct_accuracy: WireFormat::parse_unchecked(buf),
4672                at_accuracy: WireFormat::parse_unchecked(buf),
4673                h_ellipse: WireFormat::parse_unchecked(buf),
4674                confidence_and_geoid: WireFormat::parse_unchecked(buf),
4675                n_sats: WireFormat::parse_unchecked(buf),
4676                flags: WireFormat::parse_unchecked(buf),
4677            }
4678        }
4679    }
4680
4681    /// Geoid model
4682    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4683    pub enum GeoidModel {
4684        /// No model
4685        NoModel = 0,
4686
4687        /// EGM96
4688        EGM96 = 1,
4689
4690        /// EGM2008
4691        EGM2008 = 2,
4692    }
4693
4694    impl std::fmt::Display for GeoidModel {
4695        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4696            match self {
4697                GeoidModel::NoModel => f.write_str("No model"),
4698                GeoidModel::EGM96 => f.write_str("EGM96"),
4699                GeoidModel::EGM2008 => f.write_str("EGM2008"),
4700            }
4701        }
4702    }
4703
4704    impl TryFrom<u8> for GeoidModel {
4705        type Error = u8;
4706        fn try_from(i: u8) -> Result<Self, u8> {
4707            match i {
4708                0 => Ok(GeoidModel::NoModel),
4709                1 => Ok(GeoidModel::EGM96),
4710                2 => Ok(GeoidModel::EGM2008),
4711                i => Err(i),
4712            }
4713        }
4714    }
4715
4716    /// Confidence level
4717    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4718    pub enum ConfidenceLevel {
4719        /// 39.35%
4720        _3935 = 1,
4721
4722        /// 68.27%
4723        _6827 = 2,
4724
4725        /// 95.45%
4726        _9545 = 3,
4727
4728        /// 99.73%
4729        _9973 = 4,
4730    }
4731
4732    impl std::fmt::Display for ConfidenceLevel {
4733        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4734            match self {
4735                ConfidenceLevel::_3935 => f.write_str("39.35%"),
4736                ConfidenceLevel::_6827 => f.write_str("68.27%"),
4737                ConfidenceLevel::_9545 => f.write_str("95.45%"),
4738                ConfidenceLevel::_9973 => f.write_str("99.73%"),
4739            }
4740        }
4741    }
4742
4743    impl TryFrom<u8> for ConfidenceLevel {
4744        type Error = u8;
4745        fn try_from(i: u8) -> Result<Self, u8> {
4746            match i {
4747                1 => Ok(ConfidenceLevel::_3935),
4748                2 => Ok(ConfidenceLevel::_6827),
4749                3 => Ok(ConfidenceLevel::_9545),
4750                4 => Ok(ConfidenceLevel::_9973),
4751                i => Err(i),
4752            }
4753        }
4754    }
4755
4756    /// Type of reported TOW
4757    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4758    pub enum TypeOfReportedTow {
4759        /// Time of Measurement
4760        TimeOfMeasurement = 0,
4761
4762        /// Other
4763        Other = 1,
4764    }
4765
4766    impl std::fmt::Display for TypeOfReportedTow {
4767        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4768            match self {
4769                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
4770                TypeOfReportedTow::Other => f.write_str("Other"),
4771            }
4772        }
4773    }
4774
4775    impl TryFrom<u8> for TypeOfReportedTow {
4776        type Error = u8;
4777        fn try_from(i: u8) -> Result<Self, u8> {
4778            match i {
4779                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
4780                1 => Ok(TypeOfReportedTow::Other),
4781                i => Err(i),
4782            }
4783        }
4784    }
4785
4786    /// Inertial Navigation Mode
4787    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4788    pub enum InertialNavigationMode {
4789        /// None
4790        None = 0,
4791
4792        /// INS used
4793        InsUsed = 1,
4794    }
4795
4796    impl std::fmt::Display for InertialNavigationMode {
4797        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4798            match self {
4799                InertialNavigationMode::None => f.write_str("None"),
4800                InertialNavigationMode::InsUsed => f.write_str("INS used"),
4801            }
4802        }
4803    }
4804
4805    impl TryFrom<u8> for InertialNavigationMode {
4806        type Error = u8;
4807        fn try_from(i: u8) -> Result<Self, u8> {
4808            match i {
4809                0 => Ok(InertialNavigationMode::None),
4810                1 => Ok(InertialNavigationMode::InsUsed),
4811                i => Err(i),
4812            }
4813        }
4814    }
4815
4816    /// Fix mode
4817    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4818    pub enum FixMode {
4819        /// Invalid
4820        Invalid = 0,
4821
4822        /// Single Point Position (SPP)
4823        SinglePointPosition = 1,
4824
4825        /// Differential GNSS (DGNSS)
4826        DifferentialGnss = 2,
4827
4828        /// Float RTK
4829        FloatRtk = 3,
4830
4831        /// Fixed RTK
4832        FixedRtk = 4,
4833
4834        /// Dead Reckoning
4835        DeadReckoning = 5,
4836
4837        /// SBAS Position
4838        SbasPosition = 6,
4839    }
4840
4841    impl std::fmt::Display for FixMode {
4842        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4843            match self {
4844                FixMode::Invalid => f.write_str("Invalid"),
4845                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
4846                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
4847                FixMode::FloatRtk => f.write_str("Float RTK"),
4848                FixMode::FixedRtk => f.write_str("Fixed RTK"),
4849                FixMode::DeadReckoning => f.write_str("Dead Reckoning"),
4850                FixMode::SbasPosition => f.write_str("SBAS Position"),
4851            }
4852        }
4853    }
4854
4855    impl TryFrom<u8> for FixMode {
4856        type Error = u8;
4857        fn try_from(i: u8) -> Result<Self, u8> {
4858            match i {
4859                0 => Ok(FixMode::Invalid),
4860                1 => Ok(FixMode::SinglePointPosition),
4861                2 => Ok(FixMode::DifferentialGnss),
4862                3 => Ok(FixMode::FloatRtk),
4863                4 => Ok(FixMode::FixedRtk),
4864                5 => Ok(FixMode::DeadReckoning),
4865                6 => Ok(FixMode::SbasPosition),
4866                i => Err(i),
4867            }
4868        }
4869    }
4870}
4871
4872pub mod msg_pos_llh_cov {
4873    #![allow(unused_imports)]
4874
4875    use super::*;
4876    use crate::messages::lib::*;
4877
4878    /// Geodetic Position with Covariances
4879    ///
4880    /// This position solution message reports the absolute geodetic coordinates
4881    /// and the status (single point vs pseudo-absolute RTK) of the position
4882    /// solution as well as the upper triangle of the 3x3 covariance matrix.  The
4883    /// position information and Fix Mode flags follow the MSG_POS_LLH message.
4884    /// Since the covariance matrix is computed in the local-level North, East,
4885    /// Down frame, the covariance terms follow that convention. Thus, covariances
4886    /// are reported against the "downward" measurement and care should be taken
4887    /// with the sign convention.
4888    ///
4889    /// The values in this message are from GNSS measurements fused with inertial
4890    /// measurements. To get values from GNSS measurements only use
4891    /// MSG_POS_LLH_COV_GNSS.
4892    ///
4893    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4894    #[allow(clippy::derive_partial_eq_without_eq)]
4895    #[derive(Debug, PartialEq, Clone)]
4896    pub struct MsgPosLlhCov {
4897        /// The message sender_id
4898        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
4899        pub sender_id: Option<u16>,
4900        /// GPS Time of Week
4901        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
4902        pub tow: u32,
4903        /// Latitude
4904        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
4905        pub lat: f64,
4906        /// Longitude
4907        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
4908        pub lon: f64,
4909        /// Height above WGS84 ellipsoid
4910        #[cfg_attr(feature = "serde", serde(rename = "height"))]
4911        pub height: f64,
4912        /// Estimated variance of northing
4913        #[cfg_attr(feature = "serde", serde(rename = "cov_n_n"))]
4914        pub cov_n_n: f32,
4915        /// Covariance of northing and easting
4916        #[cfg_attr(feature = "serde", serde(rename = "cov_n_e"))]
4917        pub cov_n_e: f32,
4918        /// Covariance of northing and downward measurement
4919        #[cfg_attr(feature = "serde", serde(rename = "cov_n_d"))]
4920        pub cov_n_d: f32,
4921        /// Estimated variance of easting
4922        #[cfg_attr(feature = "serde", serde(rename = "cov_e_e"))]
4923        pub cov_e_e: f32,
4924        /// Covariance of easting and downward measurement
4925        #[cfg_attr(feature = "serde", serde(rename = "cov_e_d"))]
4926        pub cov_e_d: f32,
4927        /// Estimated variance of downward measurement
4928        #[cfg_attr(feature = "serde", serde(rename = "cov_d_d"))]
4929        pub cov_d_d: f32,
4930        /// Number of satellites used in solution.
4931        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
4932        pub n_sats: u8,
4933        /// Status flags
4934        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
4935        pub flags: u8,
4936    }
4937
4938    impl MsgPosLlhCov {
4939        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
4940        ///
4941        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
4942        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4943        /// or because new variants of `TypeOfReportedTow` were added.
4944        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
4945            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
4946        }
4947
4948        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
4949        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
4950            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
4951        }
4952
4953        /// Gets the [InertialNavigationMode][self::InertialNavigationMode] stored in the `flags` bitfield.
4954        ///
4955        /// Returns `Ok` if the bitrange contains a known `InertialNavigationMode` variant.
4956        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4957        /// or because new variants of `InertialNavigationMode` were added.
4958        pub fn inertial_navigation_mode(&self) -> Result<InertialNavigationMode, u8> {
4959            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
4960        }
4961
4962        /// Set the bitrange corresponding to the [InertialNavigationMode][InertialNavigationMode] of the `flags` bitfield.
4963        pub fn set_inertial_navigation_mode(
4964            &mut self,
4965            inertial_navigation_mode: InertialNavigationMode,
4966        ) {
4967            set_bit_range!(&mut self.flags, inertial_navigation_mode, u8, u8, 4, 3);
4968        }
4969
4970        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
4971        ///
4972        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
4973        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
4974        /// or because new variants of `FixMode` were added.
4975        pub fn fix_mode(&self) -> Result<FixMode, u8> {
4976            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
4977        }
4978
4979        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
4980        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
4981            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
4982        }
4983    }
4984
4985    impl ConcreteMessage for MsgPosLlhCov {
4986        const MESSAGE_TYPE: u16 = 529;
4987        const MESSAGE_NAME: &'static str = "MSG_POS_LLH_COV";
4988    }
4989
4990    impl SbpMessage for MsgPosLlhCov {
4991        fn message_name(&self) -> &'static str {
4992            <Self as ConcreteMessage>::MESSAGE_NAME
4993        }
4994        fn message_type(&self) -> Option<u16> {
4995            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
4996        }
4997        fn sender_id(&self) -> Option<u16> {
4998            self.sender_id
4999        }
5000        fn set_sender_id(&mut self, new_id: u16) {
5001            self.sender_id = Some(new_id);
5002        }
5003        fn encoded_len(&self) -> usize {
5004            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
5005        }
5006        fn is_valid(&self) -> bool {
5007            true
5008        }
5009        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
5010            Ok(self)
5011        }
5012
5013        #[cfg(feature = "swiftnav")]
5014        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
5015            let tow_s = (self.tow as f64) / 1000.0;
5016            let gps_time = match time::GpsTime::new(0, tow_s) {
5017                Ok(gps_time) => gps_time.tow(),
5018                Err(e) => return Some(Err(e.into())),
5019            };
5020            Some(Ok(time::MessageTime::Rover(gps_time.into())))
5021        }
5022    }
5023
5024    impl FriendlyName for MsgPosLlhCov {
5025        fn friendly_name() -> &'static str {
5026            "POS LLH COV"
5027        }
5028    }
5029
5030    impl TryFrom<Sbp> for MsgPosLlhCov {
5031        type Error = TryFromSbpError;
5032        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
5033            match msg {
5034                Sbp::MsgPosLlhCov(m) => Ok(m),
5035                _ => Err(TryFromSbpError(msg)),
5036            }
5037        }
5038    }
5039
5040    impl WireFormat for MsgPosLlhCov {
5041        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
5042            + <f64 as WireFormat>::MIN_LEN
5043            + <f64 as WireFormat>::MIN_LEN
5044            + <f64 as WireFormat>::MIN_LEN
5045            + <f32 as WireFormat>::MIN_LEN
5046            + <f32 as WireFormat>::MIN_LEN
5047            + <f32 as WireFormat>::MIN_LEN
5048            + <f32 as WireFormat>::MIN_LEN
5049            + <f32 as WireFormat>::MIN_LEN
5050            + <f32 as WireFormat>::MIN_LEN
5051            + <u8 as WireFormat>::MIN_LEN
5052            + <u8 as WireFormat>::MIN_LEN;
5053        fn len(&self) -> usize {
5054            WireFormat::len(&self.tow)
5055                + WireFormat::len(&self.lat)
5056                + WireFormat::len(&self.lon)
5057                + WireFormat::len(&self.height)
5058                + WireFormat::len(&self.cov_n_n)
5059                + WireFormat::len(&self.cov_n_e)
5060                + WireFormat::len(&self.cov_n_d)
5061                + WireFormat::len(&self.cov_e_e)
5062                + WireFormat::len(&self.cov_e_d)
5063                + WireFormat::len(&self.cov_d_d)
5064                + WireFormat::len(&self.n_sats)
5065                + WireFormat::len(&self.flags)
5066        }
5067        fn write<B: BufMut>(&self, buf: &mut B) {
5068            WireFormat::write(&self.tow, buf);
5069            WireFormat::write(&self.lat, buf);
5070            WireFormat::write(&self.lon, buf);
5071            WireFormat::write(&self.height, buf);
5072            WireFormat::write(&self.cov_n_n, buf);
5073            WireFormat::write(&self.cov_n_e, buf);
5074            WireFormat::write(&self.cov_n_d, buf);
5075            WireFormat::write(&self.cov_e_e, buf);
5076            WireFormat::write(&self.cov_e_d, buf);
5077            WireFormat::write(&self.cov_d_d, buf);
5078            WireFormat::write(&self.n_sats, buf);
5079            WireFormat::write(&self.flags, buf);
5080        }
5081        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
5082            MsgPosLlhCov {
5083                sender_id: None,
5084                tow: WireFormat::parse_unchecked(buf),
5085                lat: WireFormat::parse_unchecked(buf),
5086                lon: WireFormat::parse_unchecked(buf),
5087                height: WireFormat::parse_unchecked(buf),
5088                cov_n_n: WireFormat::parse_unchecked(buf),
5089                cov_n_e: WireFormat::parse_unchecked(buf),
5090                cov_n_d: WireFormat::parse_unchecked(buf),
5091                cov_e_e: WireFormat::parse_unchecked(buf),
5092                cov_e_d: WireFormat::parse_unchecked(buf),
5093                cov_d_d: WireFormat::parse_unchecked(buf),
5094                n_sats: WireFormat::parse_unchecked(buf),
5095                flags: WireFormat::parse_unchecked(buf),
5096            }
5097        }
5098    }
5099
5100    /// Type of reported TOW
5101    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5102    pub enum TypeOfReportedTow {
5103        /// Time of Measurement
5104        TimeOfMeasurement = 0,
5105
5106        /// Other
5107        Other = 1,
5108    }
5109
5110    impl std::fmt::Display for TypeOfReportedTow {
5111        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5112            match self {
5113                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
5114                TypeOfReportedTow::Other => f.write_str("Other"),
5115            }
5116        }
5117    }
5118
5119    impl TryFrom<u8> for TypeOfReportedTow {
5120        type Error = u8;
5121        fn try_from(i: u8) -> Result<Self, u8> {
5122            match i {
5123                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
5124                1 => Ok(TypeOfReportedTow::Other),
5125                i => Err(i),
5126            }
5127        }
5128    }
5129
5130    /// Inertial Navigation Mode
5131    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5132    pub enum InertialNavigationMode {
5133        /// None
5134        None = 0,
5135
5136        /// INS used
5137        InsUsed = 1,
5138    }
5139
5140    impl std::fmt::Display for InertialNavigationMode {
5141        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5142            match self {
5143                InertialNavigationMode::None => f.write_str("None"),
5144                InertialNavigationMode::InsUsed => f.write_str("INS used"),
5145            }
5146        }
5147    }
5148
5149    impl TryFrom<u8> for InertialNavigationMode {
5150        type Error = u8;
5151        fn try_from(i: u8) -> Result<Self, u8> {
5152            match i {
5153                0 => Ok(InertialNavigationMode::None),
5154                1 => Ok(InertialNavigationMode::InsUsed),
5155                i => Err(i),
5156            }
5157        }
5158    }
5159
5160    /// Fix mode
5161    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5162    pub enum FixMode {
5163        /// Invalid
5164        Invalid = 0,
5165
5166        /// Single Point Position (SPP)
5167        SinglePointPosition = 1,
5168
5169        /// Differential GNSS (DGNSS)
5170        DifferentialGnss = 2,
5171
5172        /// Float RTK
5173        FloatRtk = 3,
5174
5175        /// Fixed RTK
5176        FixedRtk = 4,
5177
5178        /// Dead Reckoning
5179        DeadReckoning = 5,
5180
5181        /// SBAS Position
5182        SbasPosition = 6,
5183    }
5184
5185    impl std::fmt::Display for FixMode {
5186        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5187            match self {
5188                FixMode::Invalid => f.write_str("Invalid"),
5189                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
5190                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
5191                FixMode::FloatRtk => f.write_str("Float RTK"),
5192                FixMode::FixedRtk => f.write_str("Fixed RTK"),
5193                FixMode::DeadReckoning => f.write_str("Dead Reckoning"),
5194                FixMode::SbasPosition => f.write_str("SBAS Position"),
5195            }
5196        }
5197    }
5198
5199    impl TryFrom<u8> for FixMode {
5200        type Error = u8;
5201        fn try_from(i: u8) -> Result<Self, u8> {
5202            match i {
5203                0 => Ok(FixMode::Invalid),
5204                1 => Ok(FixMode::SinglePointPosition),
5205                2 => Ok(FixMode::DifferentialGnss),
5206                3 => Ok(FixMode::FloatRtk),
5207                4 => Ok(FixMode::FixedRtk),
5208                5 => Ok(FixMode::DeadReckoning),
5209                6 => Ok(FixMode::SbasPosition),
5210                i => Err(i),
5211            }
5212        }
5213    }
5214}
5215
5216pub mod msg_pos_llh_cov_gnss {
5217    #![allow(unused_imports)]
5218
5219    use super::*;
5220    use crate::messages::lib::*;
5221
5222    /// GNSS-only Geodetic Position with Covariances
5223    ///
5224    /// This position solution message reports the absolute geodetic coordinates
5225    /// and the status (single point vs pseudo-absolute RTK) of the position
5226    /// solution as well as the upper triangle of the 3x3 covariance matrix.  The
5227    /// position information and Fix Mode flags should follow the MSG_POS_LLH_GNSS
5228    /// message.  Since the covariance matrix is computed in the local-level
5229    /// North, East, Down frame, the covariance terms follow with that convention.
5230    /// Thus, covariances are reported against the "downward" measurement and care
5231    /// should be taken with the sign convention.
5232    ///
5233    /// The values in this message are from GNSS measurements only. To get values
5234    /// fused with inertial measurements use MSG_POS_LLH_COV.
5235    ///
5236    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5237    #[allow(clippy::derive_partial_eq_without_eq)]
5238    #[derive(Debug, PartialEq, Clone)]
5239    pub struct MsgPosLlhCovGnss {
5240        /// The message sender_id
5241        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
5242        pub sender_id: Option<u16>,
5243        /// GPS Time of Week
5244        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
5245        pub tow: u32,
5246        /// Latitude
5247        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
5248        pub lat: f64,
5249        /// Longitude
5250        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
5251        pub lon: f64,
5252        /// Height above WGS84 ellipsoid
5253        #[cfg_attr(feature = "serde", serde(rename = "height"))]
5254        pub height: f64,
5255        /// Estimated variance of northing
5256        #[cfg_attr(feature = "serde", serde(rename = "cov_n_n"))]
5257        pub cov_n_n: f32,
5258        /// Covariance of northing and easting
5259        #[cfg_attr(feature = "serde", serde(rename = "cov_n_e"))]
5260        pub cov_n_e: f32,
5261        /// Covariance of northing and downward measurement
5262        #[cfg_attr(feature = "serde", serde(rename = "cov_n_d"))]
5263        pub cov_n_d: f32,
5264        /// Estimated variance of easting
5265        #[cfg_attr(feature = "serde", serde(rename = "cov_e_e"))]
5266        pub cov_e_e: f32,
5267        /// Covariance of easting and downward measurement
5268        #[cfg_attr(feature = "serde", serde(rename = "cov_e_d"))]
5269        pub cov_e_d: f32,
5270        /// Estimated variance of downward measurement
5271        #[cfg_attr(feature = "serde", serde(rename = "cov_d_d"))]
5272        pub cov_d_d: f32,
5273        /// Number of satellites used in solution.
5274        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
5275        pub n_sats: u8,
5276        /// Status flags
5277        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
5278        pub flags: u8,
5279    }
5280
5281    impl MsgPosLlhCovGnss {
5282        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
5283        ///
5284        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
5285        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
5286        /// or because new variants of `FixMode` were added.
5287        pub fn fix_mode(&self) -> Result<FixMode, u8> {
5288            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
5289        }
5290
5291        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
5292        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
5293            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
5294        }
5295    }
5296
5297    impl ConcreteMessage for MsgPosLlhCovGnss {
5298        const MESSAGE_TYPE: u16 = 561;
5299        const MESSAGE_NAME: &'static str = "MSG_POS_LLH_COV_GNSS";
5300    }
5301
5302    impl SbpMessage for MsgPosLlhCovGnss {
5303        fn message_name(&self) -> &'static str {
5304            <Self as ConcreteMessage>::MESSAGE_NAME
5305        }
5306        fn message_type(&self) -> Option<u16> {
5307            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
5308        }
5309        fn sender_id(&self) -> Option<u16> {
5310            self.sender_id
5311        }
5312        fn set_sender_id(&mut self, new_id: u16) {
5313            self.sender_id = Some(new_id);
5314        }
5315        fn encoded_len(&self) -> usize {
5316            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
5317        }
5318        fn is_valid(&self) -> bool {
5319            true
5320        }
5321        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
5322            Ok(self)
5323        }
5324
5325        #[cfg(feature = "swiftnav")]
5326        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
5327            let tow_s = (self.tow as f64) / 1000.0;
5328            let gps_time = match time::GpsTime::new(0, tow_s) {
5329                Ok(gps_time) => gps_time.tow(),
5330                Err(e) => return Some(Err(e.into())),
5331            };
5332            Some(Ok(time::MessageTime::Rover(gps_time.into())))
5333        }
5334    }
5335
5336    impl FriendlyName for MsgPosLlhCovGnss {
5337        fn friendly_name() -> &'static str {
5338            "POS LLH COV GNSS-only"
5339        }
5340    }
5341
5342    impl TryFrom<Sbp> for MsgPosLlhCovGnss {
5343        type Error = TryFromSbpError;
5344        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
5345            match msg {
5346                Sbp::MsgPosLlhCovGnss(m) => Ok(m),
5347                _ => Err(TryFromSbpError(msg)),
5348            }
5349        }
5350    }
5351
5352    impl WireFormat for MsgPosLlhCovGnss {
5353        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
5354            + <f64 as WireFormat>::MIN_LEN
5355            + <f64 as WireFormat>::MIN_LEN
5356            + <f64 as WireFormat>::MIN_LEN
5357            + <f32 as WireFormat>::MIN_LEN
5358            + <f32 as WireFormat>::MIN_LEN
5359            + <f32 as WireFormat>::MIN_LEN
5360            + <f32 as WireFormat>::MIN_LEN
5361            + <f32 as WireFormat>::MIN_LEN
5362            + <f32 as WireFormat>::MIN_LEN
5363            + <u8 as WireFormat>::MIN_LEN
5364            + <u8 as WireFormat>::MIN_LEN;
5365        fn len(&self) -> usize {
5366            WireFormat::len(&self.tow)
5367                + WireFormat::len(&self.lat)
5368                + WireFormat::len(&self.lon)
5369                + WireFormat::len(&self.height)
5370                + WireFormat::len(&self.cov_n_n)
5371                + WireFormat::len(&self.cov_n_e)
5372                + WireFormat::len(&self.cov_n_d)
5373                + WireFormat::len(&self.cov_e_e)
5374                + WireFormat::len(&self.cov_e_d)
5375                + WireFormat::len(&self.cov_d_d)
5376                + WireFormat::len(&self.n_sats)
5377                + WireFormat::len(&self.flags)
5378        }
5379        fn write<B: BufMut>(&self, buf: &mut B) {
5380            WireFormat::write(&self.tow, buf);
5381            WireFormat::write(&self.lat, buf);
5382            WireFormat::write(&self.lon, buf);
5383            WireFormat::write(&self.height, buf);
5384            WireFormat::write(&self.cov_n_n, buf);
5385            WireFormat::write(&self.cov_n_e, buf);
5386            WireFormat::write(&self.cov_n_d, buf);
5387            WireFormat::write(&self.cov_e_e, buf);
5388            WireFormat::write(&self.cov_e_d, buf);
5389            WireFormat::write(&self.cov_d_d, buf);
5390            WireFormat::write(&self.n_sats, buf);
5391            WireFormat::write(&self.flags, buf);
5392        }
5393        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
5394            MsgPosLlhCovGnss {
5395                sender_id: None,
5396                tow: WireFormat::parse_unchecked(buf),
5397                lat: WireFormat::parse_unchecked(buf),
5398                lon: WireFormat::parse_unchecked(buf),
5399                height: WireFormat::parse_unchecked(buf),
5400                cov_n_n: WireFormat::parse_unchecked(buf),
5401                cov_n_e: WireFormat::parse_unchecked(buf),
5402                cov_n_d: WireFormat::parse_unchecked(buf),
5403                cov_e_e: WireFormat::parse_unchecked(buf),
5404                cov_e_d: WireFormat::parse_unchecked(buf),
5405                cov_d_d: WireFormat::parse_unchecked(buf),
5406                n_sats: WireFormat::parse_unchecked(buf),
5407                flags: WireFormat::parse_unchecked(buf),
5408            }
5409        }
5410    }
5411
5412    /// Fix mode
5413    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5414    pub enum FixMode {
5415        /// Invalid
5416        Invalid = 0,
5417
5418        /// Single Point Position (SPP)
5419        SinglePointPosition = 1,
5420
5421        /// Differential GNSS (DGNSS)
5422        DifferentialGnss = 2,
5423
5424        /// Float RTK
5425        FloatRtk = 3,
5426
5427        /// Fixed RTK
5428        FixedRtk = 4,
5429
5430        /// Dead Reckoning
5431        DeadReckoning = 5,
5432
5433        /// SBAS Position
5434        SbasPosition = 6,
5435    }
5436
5437    impl std::fmt::Display for FixMode {
5438        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5439            match self {
5440                FixMode::Invalid => f.write_str("Invalid"),
5441                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
5442                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
5443                FixMode::FloatRtk => f.write_str("Float RTK"),
5444                FixMode::FixedRtk => f.write_str("Fixed RTK"),
5445                FixMode::DeadReckoning => f.write_str("Dead Reckoning"),
5446                FixMode::SbasPosition => f.write_str("SBAS Position"),
5447            }
5448        }
5449    }
5450
5451    impl TryFrom<u8> for FixMode {
5452        type Error = u8;
5453        fn try_from(i: u8) -> Result<Self, u8> {
5454            match i {
5455                0 => Ok(FixMode::Invalid),
5456                1 => Ok(FixMode::SinglePointPosition),
5457                2 => Ok(FixMode::DifferentialGnss),
5458                3 => Ok(FixMode::FloatRtk),
5459                4 => Ok(FixMode::FixedRtk),
5460                5 => Ok(FixMode::DeadReckoning),
5461                6 => Ok(FixMode::SbasPosition),
5462                i => Err(i),
5463            }
5464        }
5465    }
5466}
5467
5468pub mod msg_pos_llh_dep_a {
5469    #![allow(unused_imports)]
5470
5471    use super::*;
5472    use crate::messages::lib::*;
5473
5474    /// Deprecated
5475    ///
5476    /// Deprecated.
5477    ///
5478    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5479    #[allow(clippy::derive_partial_eq_without_eq)]
5480    #[derive(Debug, PartialEq, Clone)]
5481    pub struct MsgPosLlhDepA {
5482        /// The message sender_id
5483        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
5484        pub sender_id: Option<u16>,
5485        /// GPS Time of Week
5486        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
5487        pub tow: u32,
5488        /// Latitude
5489        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
5490        pub lat: f64,
5491        /// Longitude
5492        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
5493        pub lon: f64,
5494        /// Height
5495        #[cfg_attr(feature = "serde", serde(rename = "height"))]
5496        pub height: f64,
5497        /// Horizontal position accuracy estimate (not implemented). Defaults to 0.
5498        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
5499        pub h_accuracy: u16,
5500        /// Vertical position accuracy estimate (not implemented). Defaults to 0.
5501        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
5502        pub v_accuracy: u16,
5503        /// Number of satellites used in solution.
5504        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
5505        pub n_sats: u8,
5506        /// Status flags
5507        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
5508        pub flags: u8,
5509    }
5510
5511    impl MsgPosLlhDepA {
5512        /// Gets the [RaimRepairFlag][self::RaimRepairFlag] stored in the `flags` bitfield.
5513        ///
5514        /// Returns `Ok` if the bitrange contains a known `RaimRepairFlag` variant.
5515        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
5516        /// or because new variants of `RaimRepairFlag` were added.
5517        pub fn raim_repair_flag(&self) -> Result<RaimRepairFlag, u8> {
5518            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
5519        }
5520
5521        /// Set the bitrange corresponding to the [RaimRepairFlag][RaimRepairFlag] of the `flags` bitfield.
5522        pub fn set_raim_repair_flag(&mut self, raim_repair_flag: RaimRepairFlag) {
5523            set_bit_range!(&mut self.flags, raim_repair_flag, u8, u8, 5, 5);
5524        }
5525
5526        /// Gets the [RaimAvailabilityFlag][self::RaimAvailabilityFlag] stored in the `flags` bitfield.
5527        ///
5528        /// Returns `Ok` if the bitrange contains a known `RaimAvailabilityFlag` variant.
5529        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
5530        /// or because new variants of `RaimAvailabilityFlag` were added.
5531        pub fn raim_availability_flag(&self) -> Result<RaimAvailabilityFlag, u8> {
5532            get_bit_range!(self.flags, u8, u8, 4, 4).try_into()
5533        }
5534
5535        /// Set the bitrange corresponding to the [RaimAvailabilityFlag][RaimAvailabilityFlag] of the `flags` bitfield.
5536        pub fn set_raim_availability_flag(&mut self, raim_availability_flag: RaimAvailabilityFlag) {
5537            set_bit_range!(&mut self.flags, raim_availability_flag, u8, u8, 4, 4);
5538        }
5539
5540        /// Gets the [HeightMode][self::HeightMode] stored in the `flags` bitfield.
5541        ///
5542        /// Returns `Ok` if the bitrange contains a known `HeightMode` variant.
5543        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
5544        /// or because new variants of `HeightMode` were added.
5545        pub fn height_mode(&self) -> Result<HeightMode, u8> {
5546            get_bit_range!(self.flags, u8, u8, 3, 3).try_into()
5547        }
5548
5549        /// Set the bitrange corresponding to the [HeightMode][HeightMode] of the `flags` bitfield.
5550        pub fn set_height_mode(&mut self, height_mode: HeightMode) {
5551            set_bit_range!(&mut self.flags, height_mode, u8, u8, 3, 3);
5552        }
5553
5554        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
5555        ///
5556        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
5557        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
5558        /// or because new variants of `FixMode` were added.
5559        pub fn fix_mode(&self) -> Result<FixMode, u8> {
5560            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
5561        }
5562
5563        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
5564        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
5565            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
5566        }
5567    }
5568
5569    impl ConcreteMessage for MsgPosLlhDepA {
5570        const MESSAGE_TYPE: u16 = 513;
5571        const MESSAGE_NAME: &'static str = "MSG_POS_LLH_DEP_A";
5572    }
5573
5574    impl SbpMessage for MsgPosLlhDepA {
5575        fn message_name(&self) -> &'static str {
5576            <Self as ConcreteMessage>::MESSAGE_NAME
5577        }
5578        fn message_type(&self) -> Option<u16> {
5579            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
5580        }
5581        fn sender_id(&self) -> Option<u16> {
5582            self.sender_id
5583        }
5584        fn set_sender_id(&mut self, new_id: u16) {
5585            self.sender_id = Some(new_id);
5586        }
5587        fn encoded_len(&self) -> usize {
5588            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
5589        }
5590        fn is_valid(&self) -> bool {
5591            true
5592        }
5593        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
5594            Ok(self)
5595        }
5596
5597        #[cfg(feature = "swiftnav")]
5598        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
5599            let tow_s = (self.tow as f64) / 1000.0;
5600            let gps_time = match time::GpsTime::new(0, tow_s) {
5601                Ok(gps_time) => gps_time.tow(),
5602                Err(e) => return Some(Err(e.into())),
5603            };
5604            Some(Ok(time::MessageTime::Rover(gps_time.into())))
5605        }
5606    }
5607
5608    impl FriendlyName for MsgPosLlhDepA {
5609        fn friendly_name() -> &'static str {
5610            "POS LLH DEP A"
5611        }
5612    }
5613
5614    impl TryFrom<Sbp> for MsgPosLlhDepA {
5615        type Error = TryFromSbpError;
5616        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
5617            match msg {
5618                Sbp::MsgPosLlhDepA(m) => Ok(m),
5619                _ => Err(TryFromSbpError(msg)),
5620            }
5621        }
5622    }
5623
5624    impl WireFormat for MsgPosLlhDepA {
5625        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
5626            + <f64 as WireFormat>::MIN_LEN
5627            + <f64 as WireFormat>::MIN_LEN
5628            + <f64 as WireFormat>::MIN_LEN
5629            + <u16 as WireFormat>::MIN_LEN
5630            + <u16 as WireFormat>::MIN_LEN
5631            + <u8 as WireFormat>::MIN_LEN
5632            + <u8 as WireFormat>::MIN_LEN;
5633        fn len(&self) -> usize {
5634            WireFormat::len(&self.tow)
5635                + WireFormat::len(&self.lat)
5636                + WireFormat::len(&self.lon)
5637                + WireFormat::len(&self.height)
5638                + WireFormat::len(&self.h_accuracy)
5639                + WireFormat::len(&self.v_accuracy)
5640                + WireFormat::len(&self.n_sats)
5641                + WireFormat::len(&self.flags)
5642        }
5643        fn write<B: BufMut>(&self, buf: &mut B) {
5644            WireFormat::write(&self.tow, buf);
5645            WireFormat::write(&self.lat, buf);
5646            WireFormat::write(&self.lon, buf);
5647            WireFormat::write(&self.height, buf);
5648            WireFormat::write(&self.h_accuracy, buf);
5649            WireFormat::write(&self.v_accuracy, buf);
5650            WireFormat::write(&self.n_sats, buf);
5651            WireFormat::write(&self.flags, buf);
5652        }
5653        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
5654            MsgPosLlhDepA {
5655                sender_id: None,
5656                tow: WireFormat::parse_unchecked(buf),
5657                lat: WireFormat::parse_unchecked(buf),
5658                lon: WireFormat::parse_unchecked(buf),
5659                height: WireFormat::parse_unchecked(buf),
5660                h_accuracy: WireFormat::parse_unchecked(buf),
5661                v_accuracy: WireFormat::parse_unchecked(buf),
5662                n_sats: WireFormat::parse_unchecked(buf),
5663                flags: WireFormat::parse_unchecked(buf),
5664            }
5665        }
5666    }
5667
5668    /// RAIM repair flag
5669    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5670    pub enum RaimRepairFlag {
5671        /// No repair
5672        NoRepair = 0,
5673
5674        /// Solution came from RAIM repair
5675        SolutionCameFromRaimRepair = 1,
5676    }
5677
5678    impl std::fmt::Display for RaimRepairFlag {
5679        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5680            match self {
5681                RaimRepairFlag::NoRepair => f.write_str("No repair"),
5682                RaimRepairFlag::SolutionCameFromRaimRepair => {
5683                    f.write_str("Solution came from RAIM repair")
5684                }
5685            }
5686        }
5687    }
5688
5689    impl TryFrom<u8> for RaimRepairFlag {
5690        type Error = u8;
5691        fn try_from(i: u8) -> Result<Self, u8> {
5692            match i {
5693                0 => Ok(RaimRepairFlag::NoRepair),
5694                1 => Ok(RaimRepairFlag::SolutionCameFromRaimRepair),
5695                i => Err(i),
5696            }
5697        }
5698    }
5699
5700    /// RAIM availability flag
5701    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5702    pub enum RaimAvailabilityFlag {
5703        /// RAIM check was explicitly disabled or unavailable
5704        RaimCheckWasExplicitlyDisabledOrUnavailable = 0,
5705
5706        /// RAIM check was available
5707        RaimCheckWasAvailable = 1,
5708    }
5709
5710    impl std::fmt::Display for RaimAvailabilityFlag {
5711        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5712            match self {
5713                RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable => {
5714                    f.write_str("RAIM check was explicitly disabled or unavailable")
5715                }
5716                RaimAvailabilityFlag::RaimCheckWasAvailable => {
5717                    f.write_str("RAIM check was available")
5718                }
5719            }
5720        }
5721    }
5722
5723    impl TryFrom<u8> for RaimAvailabilityFlag {
5724        type Error = u8;
5725        fn try_from(i: u8) -> Result<Self, u8> {
5726            match i {
5727                0 => Ok(RaimAvailabilityFlag::RaimCheckWasExplicitlyDisabledOrUnavailable),
5728                1 => Ok(RaimAvailabilityFlag::RaimCheckWasAvailable),
5729                i => Err(i),
5730            }
5731        }
5732    }
5733
5734    /// Height Mode
5735    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5736    pub enum HeightMode {
5737        /// Height above WGS84 ellipsoid
5738        HeightAboveWgs84Ellipsoid = 0,
5739
5740        /// Height above mean sea level
5741        HeightAboveMeanSeaLevel = 1,
5742    }
5743
5744    impl std::fmt::Display for HeightMode {
5745        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5746            match self {
5747                HeightMode::HeightAboveWgs84Ellipsoid => {
5748                    f.write_str("Height above WGS84 ellipsoid")
5749                }
5750                HeightMode::HeightAboveMeanSeaLevel => f.write_str("Height above mean sea level"),
5751            }
5752        }
5753    }
5754
5755    impl TryFrom<u8> for HeightMode {
5756        type Error = u8;
5757        fn try_from(i: u8) -> Result<Self, u8> {
5758            match i {
5759                0 => Ok(HeightMode::HeightAboveWgs84Ellipsoid),
5760                1 => Ok(HeightMode::HeightAboveMeanSeaLevel),
5761                i => Err(i),
5762            }
5763        }
5764    }
5765
5766    /// Fix mode
5767    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5768    pub enum FixMode {
5769        /// Single Point Positioning (SPP)
5770        SinglePointPositioning = 0,
5771
5772        /// Fixed RTK
5773        FixedRtk = 1,
5774
5775        /// Float RTK
5776        FloatRtk = 2,
5777    }
5778
5779    impl std::fmt::Display for FixMode {
5780        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5781            match self {
5782                FixMode::SinglePointPositioning => f.write_str("Single Point Positioning (SPP)"),
5783                FixMode::FixedRtk => f.write_str("Fixed RTK"),
5784                FixMode::FloatRtk => f.write_str("Float RTK"),
5785            }
5786        }
5787    }
5788
5789    impl TryFrom<u8> for FixMode {
5790        type Error = u8;
5791        fn try_from(i: u8) -> Result<Self, u8> {
5792            match i {
5793                0 => Ok(FixMode::SinglePointPositioning),
5794                1 => Ok(FixMode::FixedRtk),
5795                2 => Ok(FixMode::FloatRtk),
5796                i => Err(i),
5797            }
5798        }
5799    }
5800}
5801
5802pub mod msg_pos_llh_gnss {
5803    #![allow(unused_imports)]
5804
5805    use super::*;
5806    use crate::messages::lib::*;
5807
5808    /// GNSS-only Geodetic Position
5809    ///
5810    /// This position solution message reports the absolute geodetic coordinates
5811    /// and the status (single point vs pseudo-absolute RTK) of the position
5812    /// solution. If the rover receiver knows the surveyed position of the base
5813    /// station and has an RTK solution, this reports a pseudo-absolute position
5814    /// solution using the base station position and the rover's RTK baseline
5815    /// vector. The full GPS time is given by the preceding MSG_GPS_TIME_GNSS with
5816    /// the matching time-of-week (tow).
5817    ///
5818    /// The values in this message are from GNSS measurements only. To get values
5819    /// fused with inertial measurements use MSG_POS_LLH.
5820    ///
5821    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5822    #[allow(clippy::derive_partial_eq_without_eq)]
5823    #[derive(Debug, PartialEq, Clone)]
5824    pub struct MsgPosLlhGnss {
5825        /// The message sender_id
5826        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
5827        pub sender_id: Option<u16>,
5828        /// GPS Time of Week
5829        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
5830        pub tow: u32,
5831        /// Latitude
5832        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
5833        pub lat: f64,
5834        /// Longitude
5835        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
5836        pub lon: f64,
5837        /// Height above WGS84 ellipsoid
5838        #[cfg_attr(feature = "serde", serde(rename = "height"))]
5839        pub height: f64,
5840        /// Horizontal position estimated standard deviation
5841        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
5842        pub h_accuracy: u16,
5843        /// Vertical position estimated standard deviation
5844        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
5845        pub v_accuracy: u16,
5846        /// Number of satellites used in solution.
5847        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
5848        pub n_sats: u8,
5849        /// Status flags
5850        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
5851        pub flags: u8,
5852    }
5853
5854    impl MsgPosLlhGnss {
5855        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
5856        ///
5857        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
5858        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
5859        /// or because new variants of `FixMode` were added.
5860        pub fn fix_mode(&self) -> Result<FixMode, u8> {
5861            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
5862        }
5863
5864        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
5865        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
5866            set_bit_range!(&mut self.flags, fix_mode, u8, u8, 2, 0);
5867        }
5868    }
5869
5870    impl ConcreteMessage for MsgPosLlhGnss {
5871        const MESSAGE_TYPE: u16 = 554;
5872        const MESSAGE_NAME: &'static str = "MSG_POS_LLH_GNSS";
5873    }
5874
5875    impl SbpMessage for MsgPosLlhGnss {
5876        fn message_name(&self) -> &'static str {
5877            <Self as ConcreteMessage>::MESSAGE_NAME
5878        }
5879        fn message_type(&self) -> Option<u16> {
5880            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
5881        }
5882        fn sender_id(&self) -> Option<u16> {
5883            self.sender_id
5884        }
5885        fn set_sender_id(&mut self, new_id: u16) {
5886            self.sender_id = Some(new_id);
5887        }
5888        fn encoded_len(&self) -> usize {
5889            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
5890        }
5891        fn is_valid(&self) -> bool {
5892            true
5893        }
5894        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
5895            Ok(self)
5896        }
5897
5898        #[cfg(feature = "swiftnav")]
5899        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
5900            let tow_s = (self.tow as f64) / 1000.0;
5901            let gps_time = match time::GpsTime::new(0, tow_s) {
5902                Ok(gps_time) => gps_time.tow(),
5903                Err(e) => return Some(Err(e.into())),
5904            };
5905            Some(Ok(time::MessageTime::Rover(gps_time.into())))
5906        }
5907    }
5908
5909    impl FriendlyName for MsgPosLlhGnss {
5910        fn friendly_name() -> &'static str {
5911            "POS LLH GNSS-only"
5912        }
5913    }
5914
5915    impl TryFrom<Sbp> for MsgPosLlhGnss {
5916        type Error = TryFromSbpError;
5917        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
5918            match msg {
5919                Sbp::MsgPosLlhGnss(m) => Ok(m),
5920                _ => Err(TryFromSbpError(msg)),
5921            }
5922        }
5923    }
5924
5925    impl WireFormat for MsgPosLlhGnss {
5926        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
5927            + <f64 as WireFormat>::MIN_LEN
5928            + <f64 as WireFormat>::MIN_LEN
5929            + <f64 as WireFormat>::MIN_LEN
5930            + <u16 as WireFormat>::MIN_LEN
5931            + <u16 as WireFormat>::MIN_LEN
5932            + <u8 as WireFormat>::MIN_LEN
5933            + <u8 as WireFormat>::MIN_LEN;
5934        fn len(&self) -> usize {
5935            WireFormat::len(&self.tow)
5936                + WireFormat::len(&self.lat)
5937                + WireFormat::len(&self.lon)
5938                + WireFormat::len(&self.height)
5939                + WireFormat::len(&self.h_accuracy)
5940                + WireFormat::len(&self.v_accuracy)
5941                + WireFormat::len(&self.n_sats)
5942                + WireFormat::len(&self.flags)
5943        }
5944        fn write<B: BufMut>(&self, buf: &mut B) {
5945            WireFormat::write(&self.tow, buf);
5946            WireFormat::write(&self.lat, buf);
5947            WireFormat::write(&self.lon, buf);
5948            WireFormat::write(&self.height, buf);
5949            WireFormat::write(&self.h_accuracy, buf);
5950            WireFormat::write(&self.v_accuracy, buf);
5951            WireFormat::write(&self.n_sats, buf);
5952            WireFormat::write(&self.flags, buf);
5953        }
5954        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
5955            MsgPosLlhGnss {
5956                sender_id: None,
5957                tow: WireFormat::parse_unchecked(buf),
5958                lat: WireFormat::parse_unchecked(buf),
5959                lon: WireFormat::parse_unchecked(buf),
5960                height: WireFormat::parse_unchecked(buf),
5961                h_accuracy: WireFormat::parse_unchecked(buf),
5962                v_accuracy: WireFormat::parse_unchecked(buf),
5963                n_sats: WireFormat::parse_unchecked(buf),
5964                flags: WireFormat::parse_unchecked(buf),
5965            }
5966        }
5967    }
5968
5969    /// Fix mode
5970    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5971    pub enum FixMode {
5972        /// Invalid
5973        Invalid = 0,
5974
5975        /// Single Point Position (SPP)
5976        SinglePointPosition = 1,
5977
5978        /// Differential GNSS (DGNSS)
5979        DifferentialGnss = 2,
5980
5981        /// Float RTK
5982        FloatRtk = 3,
5983
5984        /// Fixed RTK
5985        FixedRtk = 4,
5986
5987        /// SBAS Position
5988        SbasPosition = 6,
5989    }
5990
5991    impl std::fmt::Display for FixMode {
5992        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5993            match self {
5994                FixMode::Invalid => f.write_str("Invalid"),
5995                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
5996                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
5997                FixMode::FloatRtk => f.write_str("Float RTK"),
5998                FixMode::FixedRtk => f.write_str("Fixed RTK"),
5999                FixMode::SbasPosition => f.write_str("SBAS Position"),
6000            }
6001        }
6002    }
6003
6004    impl TryFrom<u8> for FixMode {
6005        type Error = u8;
6006        fn try_from(i: u8) -> Result<Self, u8> {
6007            match i {
6008                0 => Ok(FixMode::Invalid),
6009                1 => Ok(FixMode::SinglePointPosition),
6010                2 => Ok(FixMode::DifferentialGnss),
6011                3 => Ok(FixMode::FloatRtk),
6012                4 => Ok(FixMode::FixedRtk),
6013                6 => Ok(FixMode::SbasPosition),
6014                i => Err(i),
6015            }
6016        }
6017    }
6018}
6019
6020pub mod msg_protection_level {
6021    #![allow(unused_imports)]
6022
6023    use super::*;
6024    use crate::messages::lib::*;
6025
6026    /// Computed state and Protection Levels
6027    ///
6028    /// This message reports the protection levels associated to the given state
6029    /// estimate. The full GPS time is given by the preceding MSG_GPS_TIME with
6030    /// the matching time-of-week (tow).
6031    ///
6032    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6033    #[allow(clippy::derive_partial_eq_without_eq)]
6034    #[derive(Debug, PartialEq, Clone)]
6035    pub struct MsgProtectionLevel {
6036        /// The message sender_id
6037        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
6038        pub sender_id: Option<u16>,
6039        /// GPS Time of Week
6040        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
6041        pub tow: u32,
6042        /// GPS week number
6043        #[cfg_attr(feature = "serde", serde(rename = "wn"))]
6044        pub wn: i16,
6045        /// Horizontal protection level
6046        #[cfg_attr(feature = "serde", serde(rename = "hpl"))]
6047        pub hpl: u16,
6048        /// Vertical protection level
6049        #[cfg_attr(feature = "serde", serde(rename = "vpl"))]
6050        pub vpl: u16,
6051        /// Along-track position error protection level
6052        #[cfg_attr(feature = "serde", serde(rename = "atpl"))]
6053        pub atpl: u16,
6054        /// Cross-track position error protection level
6055        #[cfg_attr(feature = "serde", serde(rename = "ctpl"))]
6056        pub ctpl: u16,
6057        /// Protection level for the error vector between estimated and true
6058        /// along/cross track velocity vector
6059        #[cfg_attr(feature = "serde", serde(rename = "hvpl"))]
6060        pub hvpl: u16,
6061        /// Protection level for the velocity in vehicle upright direction
6062        /// (different from vertical direction if on a slope)
6063        #[cfg_attr(feature = "serde", serde(rename = "vvpl"))]
6064        pub vvpl: u16,
6065        /// Heading orientation protection level
6066        #[cfg_attr(feature = "serde", serde(rename = "hopl"))]
6067        pub hopl: u16,
6068        /// Pitch orientation protection level
6069        #[cfg_attr(feature = "serde", serde(rename = "popl"))]
6070        pub popl: u16,
6071        /// Roll orientation protection level
6072        #[cfg_attr(feature = "serde", serde(rename = "ropl"))]
6073        pub ropl: u16,
6074        /// Latitude
6075        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
6076        pub lat: f64,
6077        /// Longitude
6078        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
6079        pub lon: f64,
6080        /// Height
6081        #[cfg_attr(feature = "serde", serde(rename = "height"))]
6082        pub height: f64,
6083        /// Velocity in vehicle x direction
6084        #[cfg_attr(feature = "serde", serde(rename = "v_x"))]
6085        pub v_x: i32,
6086        /// Velocity in vehicle y direction
6087        #[cfg_attr(feature = "serde", serde(rename = "v_y"))]
6088        pub v_y: i32,
6089        /// Velocity in vehicle z direction
6090        #[cfg_attr(feature = "serde", serde(rename = "v_z"))]
6091        pub v_z: i32,
6092        /// Roll angle
6093        #[cfg_attr(feature = "serde", serde(rename = "roll"))]
6094        pub roll: i32,
6095        /// Pitch angle
6096        #[cfg_attr(feature = "serde", serde(rename = "pitch"))]
6097        pub pitch: i32,
6098        /// Heading angle
6099        #[cfg_attr(feature = "serde", serde(rename = "heading"))]
6100        pub heading: i32,
6101        /// Status flags
6102        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
6103        pub flags: u32,
6104    }
6105
6106    impl MsgProtectionLevel {
6107        /// Gets the `target_integrity_risk_tir_level` stored in `flags`.
6108        pub fn target_integrity_risk_tir_level(&self) -> u8 {
6109            get_bit_range!(self.flags, u32, u8, 2, 0)
6110        }
6111
6112        /// Sets the `target_integrity_risk_tir_level` bitrange of `flags`.
6113        pub fn set_target_integrity_risk_tir_level(&mut self, target_integrity_risk_tir_level: u8) {
6114            set_bit_range!(
6115                &mut self.flags,
6116                target_integrity_risk_tir_level,
6117                u32,
6118                u8,
6119                2,
6120                0
6121            );
6122        }
6123
6124        /// Gets the [FixMode][self::FixMode] stored in the `flags` bitfield.
6125        ///
6126        /// Returns `Ok` if the bitrange contains a known `FixMode` variant.
6127        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
6128        /// or because new variants of `FixMode` were added.
6129        pub fn fix_mode(&self) -> Result<FixMode, u8> {
6130            get_bit_range!(self.flags, u32, u8, 17, 15).try_into()
6131        }
6132
6133        /// Set the bitrange corresponding to the [FixMode][FixMode] of the `flags` bitfield.
6134        pub fn set_fix_mode(&mut self, fix_mode: FixMode) {
6135            set_bit_range!(&mut self.flags, fix_mode, u32, u8, 17, 15);
6136        }
6137
6138        /// Gets the [InertialNavigationMode][self::InertialNavigationMode] stored in the `flags` bitfield.
6139        ///
6140        /// Returns `Ok` if the bitrange contains a known `InertialNavigationMode` variant.
6141        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
6142        /// or because new variants of `InertialNavigationMode` were added.
6143        pub fn inertial_navigation_mode(&self) -> Result<InertialNavigationMode, u8> {
6144            get_bit_range!(self.flags, u32, u8, 19, 18).try_into()
6145        }
6146
6147        /// Set the bitrange corresponding to the [InertialNavigationMode][InertialNavigationMode] of the `flags` bitfield.
6148        pub fn set_inertial_navigation_mode(
6149            &mut self,
6150            inertial_navigation_mode: InertialNavigationMode,
6151        ) {
6152            set_bit_range!(&mut self.flags, inertial_navigation_mode, u32, u8, 19, 18);
6153        }
6154
6155        /// Gets the [TimeStatus][self::TimeStatus] stored in the `flags` bitfield.
6156        ///
6157        /// Returns `Ok` if the bitrange contains a known `TimeStatus` variant.
6158        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
6159        /// or because new variants of `TimeStatus` were added.
6160        pub fn time_status(&self) -> Result<TimeStatus, u8> {
6161            get_bit_range!(self.flags, u32, u8, 20, 20).try_into()
6162        }
6163
6164        /// Set the bitrange corresponding to the [TimeStatus][TimeStatus] of the `flags` bitfield.
6165        pub fn set_time_status(&mut self, time_status: TimeStatus) {
6166            set_bit_range!(&mut self.flags, time_status, u32, u8, 20, 20);
6167        }
6168
6169        /// Gets the `velocity_valid` flag.
6170        #[allow(clippy::identity_op)]
6171        pub fn velocity_valid(&self) -> bool {
6172            ((self.flags >> 21) & 1) == 1
6173        }
6174
6175        /// Sets the `velocity_valid` flag.
6176        pub fn set_velocity_valid(&mut self, velocity_valid: bool) {
6177            self.flags ^= (!(velocity_valid as u32)) & (1 << 21)
6178        }
6179
6180        /// Gets the `attitude_valid` flag.
6181        #[allow(clippy::identity_op)]
6182        pub fn attitude_valid(&self) -> bool {
6183            ((self.flags >> 22) & 1) == 1
6184        }
6185
6186        /// Sets the `attitude_valid` flag.
6187        pub fn set_attitude_valid(&mut self, attitude_valid: bool) {
6188            self.flags ^= (!(attitude_valid as u32)) & (1 << 22)
6189        }
6190
6191        /// Gets the `safe_state_hpl` flag.
6192        #[allow(clippy::identity_op)]
6193        pub fn safe_state_hpl(&self) -> bool {
6194            ((self.flags >> 23) & 1) == 1
6195        }
6196
6197        /// Sets the `safe_state_hpl` flag.
6198        pub fn set_safe_state_hpl(&mut self, safe_state_hpl: bool) {
6199            self.flags ^= (!(safe_state_hpl as u32)) & (1 << 23)
6200        }
6201
6202        /// Gets the `safe_state_vpl` flag.
6203        #[allow(clippy::identity_op)]
6204        pub fn safe_state_vpl(&self) -> bool {
6205            ((self.flags >> 24) & 1) == 1
6206        }
6207
6208        /// Sets the `safe_state_vpl` flag.
6209        pub fn set_safe_state_vpl(&mut self, safe_state_vpl: bool) {
6210            self.flags ^= (!(safe_state_vpl as u32)) & (1 << 24)
6211        }
6212
6213        /// Gets the `safe_state_atpl` flag.
6214        #[allow(clippy::identity_op)]
6215        pub fn safe_state_atpl(&self) -> bool {
6216            ((self.flags >> 25) & 1) == 1
6217        }
6218
6219        /// Sets the `safe_state_atpl` flag.
6220        pub fn set_safe_state_atpl(&mut self, safe_state_atpl: bool) {
6221            self.flags ^= (!(safe_state_atpl as u32)) & (1 << 25)
6222        }
6223
6224        /// Gets the `safe_state_ctpl` flag.
6225        #[allow(clippy::identity_op)]
6226        pub fn safe_state_ctpl(&self) -> bool {
6227            ((self.flags >> 26) & 1) == 1
6228        }
6229
6230        /// Sets the `safe_state_ctpl` flag.
6231        pub fn set_safe_state_ctpl(&mut self, safe_state_ctpl: bool) {
6232            self.flags ^= (!(safe_state_ctpl as u32)) & (1 << 26)
6233        }
6234
6235        /// Gets the `safe_state_hvpl` flag.
6236        #[allow(clippy::identity_op)]
6237        pub fn safe_state_hvpl(&self) -> bool {
6238            ((self.flags >> 27) & 1) == 1
6239        }
6240
6241        /// Sets the `safe_state_hvpl` flag.
6242        pub fn set_safe_state_hvpl(&mut self, safe_state_hvpl: bool) {
6243            self.flags ^= (!(safe_state_hvpl as u32)) & (1 << 27)
6244        }
6245
6246        /// Gets the `safe_state_vvpl` flag.
6247        #[allow(clippy::identity_op)]
6248        pub fn safe_state_vvpl(&self) -> bool {
6249            ((self.flags >> 28) & 1) == 1
6250        }
6251
6252        /// Sets the `safe_state_vvpl` flag.
6253        pub fn set_safe_state_vvpl(&mut self, safe_state_vvpl: bool) {
6254            self.flags ^= (!(safe_state_vvpl as u32)) & (1 << 28)
6255        }
6256
6257        /// Gets the `safe_state_hopl` flag.
6258        #[allow(clippy::identity_op)]
6259        pub fn safe_state_hopl(&self) -> bool {
6260            ((self.flags >> 29) & 1) == 1
6261        }
6262
6263        /// Sets the `safe_state_hopl` flag.
6264        pub fn set_safe_state_hopl(&mut self, safe_state_hopl: bool) {
6265            self.flags ^= (!(safe_state_hopl as u32)) & (1 << 29)
6266        }
6267
6268        /// Gets the `safe_state_popl` flag.
6269        #[allow(clippy::identity_op)]
6270        pub fn safe_state_popl(&self) -> bool {
6271            ((self.flags >> 30) & 1) == 1
6272        }
6273
6274        /// Sets the `safe_state_popl` flag.
6275        pub fn set_safe_state_popl(&mut self, safe_state_popl: bool) {
6276            self.flags ^= (!(safe_state_popl as u32)) & (1 << 30)
6277        }
6278
6279        /// Gets the `safe_state_ropl` flag.
6280        #[allow(clippy::identity_op)]
6281        pub fn safe_state_ropl(&self) -> bool {
6282            ((self.flags >> 31) & 1) == 1
6283        }
6284
6285        /// Sets the `safe_state_ropl` flag.
6286        pub fn set_safe_state_ropl(&mut self, safe_state_ropl: bool) {
6287            self.flags ^= (!(safe_state_ropl as u32)) & (1 << 31)
6288        }
6289    }
6290
6291    impl ConcreteMessage for MsgProtectionLevel {
6292        const MESSAGE_TYPE: u16 = 535;
6293        const MESSAGE_NAME: &'static str = "MSG_PROTECTION_LEVEL";
6294    }
6295
6296    impl SbpMessage for MsgProtectionLevel {
6297        fn message_name(&self) -> &'static str {
6298            <Self as ConcreteMessage>::MESSAGE_NAME
6299        }
6300        fn message_type(&self) -> Option<u16> {
6301            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
6302        }
6303        fn sender_id(&self) -> Option<u16> {
6304            self.sender_id
6305        }
6306        fn set_sender_id(&mut self, new_id: u16) {
6307            self.sender_id = Some(new_id);
6308        }
6309        fn encoded_len(&self) -> usize {
6310            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
6311        }
6312        fn is_valid(&self) -> bool {
6313            true
6314        }
6315        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
6316            Ok(self)
6317        }
6318
6319        #[cfg(feature = "swiftnav")]
6320        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
6321            let tow_s = (self.tow as f64) / 1000.0;
6322            #[allow(clippy::useless_conversion)]
6323            let wn: i16 = match self.wn.try_into() {
6324                Ok(wn) => wn,
6325                Err(e) => return Some(Err(e.into())),
6326            };
6327            let gps_time = match time::GpsTime::new(wn, tow_s) {
6328                Ok(gps_time) => gps_time,
6329                Err(e) => return Some(Err(e.into())),
6330            };
6331            Some(Ok(time::MessageTime::Rover(gps_time.into())))
6332        }
6333    }
6334
6335    impl FriendlyName for MsgProtectionLevel {
6336        fn friendly_name() -> &'static str {
6337            "PROTECTION LEVEL"
6338        }
6339    }
6340
6341    impl TryFrom<Sbp> for MsgProtectionLevel {
6342        type Error = TryFromSbpError;
6343        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
6344            match msg {
6345                Sbp::MsgProtectionLevel(m) => Ok(m),
6346                _ => Err(TryFromSbpError(msg)),
6347            }
6348        }
6349    }
6350
6351    impl WireFormat for MsgProtectionLevel {
6352        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
6353            + <i16 as WireFormat>::MIN_LEN
6354            + <u16 as WireFormat>::MIN_LEN
6355            + <u16 as WireFormat>::MIN_LEN
6356            + <u16 as WireFormat>::MIN_LEN
6357            + <u16 as WireFormat>::MIN_LEN
6358            + <u16 as WireFormat>::MIN_LEN
6359            + <u16 as WireFormat>::MIN_LEN
6360            + <u16 as WireFormat>::MIN_LEN
6361            + <u16 as WireFormat>::MIN_LEN
6362            + <u16 as WireFormat>::MIN_LEN
6363            + <f64 as WireFormat>::MIN_LEN
6364            + <f64 as WireFormat>::MIN_LEN
6365            + <f64 as WireFormat>::MIN_LEN
6366            + <i32 as WireFormat>::MIN_LEN
6367            + <i32 as WireFormat>::MIN_LEN
6368            + <i32 as WireFormat>::MIN_LEN
6369            + <i32 as WireFormat>::MIN_LEN
6370            + <i32 as WireFormat>::MIN_LEN
6371            + <i32 as WireFormat>::MIN_LEN
6372            + <u32 as WireFormat>::MIN_LEN;
6373        fn len(&self) -> usize {
6374            WireFormat::len(&self.tow)
6375                + WireFormat::len(&self.wn)
6376                + WireFormat::len(&self.hpl)
6377                + WireFormat::len(&self.vpl)
6378                + WireFormat::len(&self.atpl)
6379                + WireFormat::len(&self.ctpl)
6380                + WireFormat::len(&self.hvpl)
6381                + WireFormat::len(&self.vvpl)
6382                + WireFormat::len(&self.hopl)
6383                + WireFormat::len(&self.popl)
6384                + WireFormat::len(&self.ropl)
6385                + WireFormat::len(&self.lat)
6386                + WireFormat::len(&self.lon)
6387                + WireFormat::len(&self.height)
6388                + WireFormat::len(&self.v_x)
6389                + WireFormat::len(&self.v_y)
6390                + WireFormat::len(&self.v_z)
6391                + WireFormat::len(&self.roll)
6392                + WireFormat::len(&self.pitch)
6393                + WireFormat::len(&self.heading)
6394                + WireFormat::len(&self.flags)
6395        }
6396        fn write<B: BufMut>(&self, buf: &mut B) {
6397            WireFormat::write(&self.tow, buf);
6398            WireFormat::write(&self.wn, buf);
6399            WireFormat::write(&self.hpl, buf);
6400            WireFormat::write(&self.vpl, buf);
6401            WireFormat::write(&self.atpl, buf);
6402            WireFormat::write(&self.ctpl, buf);
6403            WireFormat::write(&self.hvpl, buf);
6404            WireFormat::write(&self.vvpl, buf);
6405            WireFormat::write(&self.hopl, buf);
6406            WireFormat::write(&self.popl, buf);
6407            WireFormat::write(&self.ropl, buf);
6408            WireFormat::write(&self.lat, buf);
6409            WireFormat::write(&self.lon, buf);
6410            WireFormat::write(&self.height, buf);
6411            WireFormat::write(&self.v_x, buf);
6412            WireFormat::write(&self.v_y, buf);
6413            WireFormat::write(&self.v_z, buf);
6414            WireFormat::write(&self.roll, buf);
6415            WireFormat::write(&self.pitch, buf);
6416            WireFormat::write(&self.heading, buf);
6417            WireFormat::write(&self.flags, buf);
6418        }
6419        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
6420            MsgProtectionLevel {
6421                sender_id: None,
6422                tow: WireFormat::parse_unchecked(buf),
6423                wn: WireFormat::parse_unchecked(buf),
6424                hpl: WireFormat::parse_unchecked(buf),
6425                vpl: WireFormat::parse_unchecked(buf),
6426                atpl: WireFormat::parse_unchecked(buf),
6427                ctpl: WireFormat::parse_unchecked(buf),
6428                hvpl: WireFormat::parse_unchecked(buf),
6429                vvpl: WireFormat::parse_unchecked(buf),
6430                hopl: WireFormat::parse_unchecked(buf),
6431                popl: WireFormat::parse_unchecked(buf),
6432                ropl: WireFormat::parse_unchecked(buf),
6433                lat: WireFormat::parse_unchecked(buf),
6434                lon: WireFormat::parse_unchecked(buf),
6435                height: WireFormat::parse_unchecked(buf),
6436                v_x: WireFormat::parse_unchecked(buf),
6437                v_y: WireFormat::parse_unchecked(buf),
6438                v_z: WireFormat::parse_unchecked(buf),
6439                roll: WireFormat::parse_unchecked(buf),
6440                pitch: WireFormat::parse_unchecked(buf),
6441                heading: WireFormat::parse_unchecked(buf),
6442                flags: WireFormat::parse_unchecked(buf),
6443            }
6444        }
6445    }
6446
6447    /// Fix mode
6448    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6449    pub enum FixMode {
6450        /// Invalid
6451        Invalid = 0,
6452
6453        /// Single Point Position (SPP)
6454        SinglePointPosition = 1,
6455
6456        /// Differential GNSS (DGNSS)
6457        DifferentialGnss = 2,
6458
6459        /// Float RTK
6460        FloatRtk = 3,
6461
6462        /// Fixed RTK
6463        FixedRtk = 4,
6464
6465        /// Dead Reckoning
6466        DeadReckoning = 5,
6467
6468        /// SBAS Position
6469        SbasPosition = 6,
6470    }
6471
6472    impl std::fmt::Display for FixMode {
6473        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6474            match self {
6475                FixMode::Invalid => f.write_str("Invalid"),
6476                FixMode::SinglePointPosition => f.write_str("Single Point Position (SPP)"),
6477                FixMode::DifferentialGnss => f.write_str("Differential GNSS (DGNSS)"),
6478                FixMode::FloatRtk => f.write_str("Float RTK"),
6479                FixMode::FixedRtk => f.write_str("Fixed RTK"),
6480                FixMode::DeadReckoning => f.write_str("Dead Reckoning"),
6481                FixMode::SbasPosition => f.write_str("SBAS Position"),
6482            }
6483        }
6484    }
6485
6486    impl TryFrom<u8> for FixMode {
6487        type Error = u8;
6488        fn try_from(i: u8) -> Result<Self, u8> {
6489            match i {
6490                0 => Ok(FixMode::Invalid),
6491                1 => Ok(FixMode::SinglePointPosition),
6492                2 => Ok(FixMode::DifferentialGnss),
6493                3 => Ok(FixMode::FloatRtk),
6494                4 => Ok(FixMode::FixedRtk),
6495                5 => Ok(FixMode::DeadReckoning),
6496                6 => Ok(FixMode::SbasPosition),
6497                i => Err(i),
6498            }
6499        }
6500    }
6501
6502    /// Inertial Navigation Mode
6503    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6504    pub enum InertialNavigationMode {
6505        /// None
6506        None = 0,
6507
6508        /// INS used
6509        InsUsed = 1,
6510    }
6511
6512    impl std::fmt::Display for InertialNavigationMode {
6513        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6514            match self {
6515                InertialNavigationMode::None => f.write_str("None"),
6516                InertialNavigationMode::InsUsed => f.write_str("INS used"),
6517            }
6518        }
6519    }
6520
6521    impl TryFrom<u8> for InertialNavigationMode {
6522        type Error = u8;
6523        fn try_from(i: u8) -> Result<Self, u8> {
6524            match i {
6525                0 => Ok(InertialNavigationMode::None),
6526                1 => Ok(InertialNavigationMode::InsUsed),
6527                i => Err(i),
6528            }
6529        }
6530    }
6531
6532    /// Time status
6533    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6534    pub enum TimeStatus {
6535        /// GNSS time of validity
6536        GnssTimeOfValidity = 0,
6537
6538        /// Other
6539        Other = 1,
6540    }
6541
6542    impl std::fmt::Display for TimeStatus {
6543        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6544            match self {
6545                TimeStatus::GnssTimeOfValidity => f.write_str("GNSS time of validity"),
6546                TimeStatus::Other => f.write_str("Other"),
6547            }
6548        }
6549    }
6550
6551    impl TryFrom<u8> for TimeStatus {
6552        type Error = u8;
6553        fn try_from(i: u8) -> Result<Self, u8> {
6554            match i {
6555                0 => Ok(TimeStatus::GnssTimeOfValidity),
6556                1 => Ok(TimeStatus::Other),
6557                i => Err(i),
6558            }
6559        }
6560    }
6561}
6562
6563pub mod msg_protection_level_dep_a {
6564    #![allow(unused_imports)]
6565
6566    use super::*;
6567    use crate::messages::lib::*;
6568
6569    /// Deprecated
6570    ///
6571    /// Deprecated.
6572    ///
6573    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6574    #[allow(clippy::derive_partial_eq_without_eq)]
6575    #[derive(Debug, PartialEq, Clone)]
6576    pub struct MsgProtectionLevelDepA {
6577        /// The message sender_id
6578        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
6579        pub sender_id: Option<u16>,
6580        /// GPS Time of Week
6581        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
6582        pub tow: u32,
6583        /// Vertical protection level
6584        #[cfg_attr(feature = "serde", serde(rename = "vpl"))]
6585        pub vpl: u16,
6586        /// Horizontal protection level
6587        #[cfg_attr(feature = "serde", serde(rename = "hpl"))]
6588        pub hpl: u16,
6589        /// Latitude
6590        #[cfg_attr(feature = "serde", serde(rename = "lat"))]
6591        pub lat: f64,
6592        /// Longitude
6593        #[cfg_attr(feature = "serde", serde(rename = "lon"))]
6594        pub lon: f64,
6595        /// Height
6596        #[cfg_attr(feature = "serde", serde(rename = "height"))]
6597        pub height: f64,
6598        /// Status flags
6599        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
6600        pub flags: u8,
6601    }
6602
6603    impl MsgProtectionLevelDepA {
6604        /// Gets the [TargetIntegrityRiskTirLevel][self::TargetIntegrityRiskTirLevel] stored in the `flags` bitfield.
6605        ///
6606        /// Returns `Ok` if the bitrange contains a known `TargetIntegrityRiskTirLevel` variant.
6607        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
6608        /// or because new variants of `TargetIntegrityRiskTirLevel` were added.
6609        pub fn target_integrity_risk_tir_level(&self) -> Result<TargetIntegrityRiskTirLevel, u8> {
6610            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
6611        }
6612
6613        /// Set the bitrange corresponding to the [TargetIntegrityRiskTirLevel][TargetIntegrityRiskTirLevel] of the `flags` bitfield.
6614        pub fn set_target_integrity_risk_tir_level(
6615            &mut self,
6616            target_integrity_risk_tir_level: TargetIntegrityRiskTirLevel,
6617        ) {
6618            set_bit_range!(
6619                &mut self.flags,
6620                target_integrity_risk_tir_level,
6621                u8,
6622                u8,
6623                2,
6624                0
6625            );
6626        }
6627    }
6628
6629    impl ConcreteMessage for MsgProtectionLevelDepA {
6630        const MESSAGE_TYPE: u16 = 534;
6631        const MESSAGE_NAME: &'static str = "MSG_PROTECTION_LEVEL_DEP_A";
6632    }
6633
6634    impl SbpMessage for MsgProtectionLevelDepA {
6635        fn message_name(&self) -> &'static str {
6636            <Self as ConcreteMessage>::MESSAGE_NAME
6637        }
6638        fn message_type(&self) -> Option<u16> {
6639            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
6640        }
6641        fn sender_id(&self) -> Option<u16> {
6642            self.sender_id
6643        }
6644        fn set_sender_id(&mut self, new_id: u16) {
6645            self.sender_id = Some(new_id);
6646        }
6647        fn encoded_len(&self) -> usize {
6648            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
6649        }
6650        fn is_valid(&self) -> bool {
6651            true
6652        }
6653        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
6654            Ok(self)
6655        }
6656
6657        #[cfg(feature = "swiftnav")]
6658        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
6659            let tow_s = (self.tow as f64) / 1000.0;
6660            let gps_time = match time::GpsTime::new(0, tow_s) {
6661                Ok(gps_time) => gps_time.tow(),
6662                Err(e) => return Some(Err(e.into())),
6663            };
6664            Some(Ok(time::MessageTime::Rover(gps_time.into())))
6665        }
6666    }
6667
6668    impl FriendlyName for MsgProtectionLevelDepA {
6669        fn friendly_name() -> &'static str {
6670            "PROTECTION LEVEL DEP A"
6671        }
6672    }
6673
6674    impl TryFrom<Sbp> for MsgProtectionLevelDepA {
6675        type Error = TryFromSbpError;
6676        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
6677            match msg {
6678                Sbp::MsgProtectionLevelDepA(m) => Ok(m),
6679                _ => Err(TryFromSbpError(msg)),
6680            }
6681        }
6682    }
6683
6684    impl WireFormat for MsgProtectionLevelDepA {
6685        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
6686            + <u16 as WireFormat>::MIN_LEN
6687            + <u16 as WireFormat>::MIN_LEN
6688            + <f64 as WireFormat>::MIN_LEN
6689            + <f64 as WireFormat>::MIN_LEN
6690            + <f64 as WireFormat>::MIN_LEN
6691            + <u8 as WireFormat>::MIN_LEN;
6692        fn len(&self) -> usize {
6693            WireFormat::len(&self.tow)
6694                + WireFormat::len(&self.vpl)
6695                + WireFormat::len(&self.hpl)
6696                + WireFormat::len(&self.lat)
6697                + WireFormat::len(&self.lon)
6698                + WireFormat::len(&self.height)
6699                + WireFormat::len(&self.flags)
6700        }
6701        fn write<B: BufMut>(&self, buf: &mut B) {
6702            WireFormat::write(&self.tow, buf);
6703            WireFormat::write(&self.vpl, buf);
6704            WireFormat::write(&self.hpl, buf);
6705            WireFormat::write(&self.lat, buf);
6706            WireFormat::write(&self.lon, buf);
6707            WireFormat::write(&self.height, buf);
6708            WireFormat::write(&self.flags, buf);
6709        }
6710        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
6711            MsgProtectionLevelDepA {
6712                sender_id: None,
6713                tow: WireFormat::parse_unchecked(buf),
6714                vpl: WireFormat::parse_unchecked(buf),
6715                hpl: WireFormat::parse_unchecked(buf),
6716                lat: WireFormat::parse_unchecked(buf),
6717                lon: WireFormat::parse_unchecked(buf),
6718                height: WireFormat::parse_unchecked(buf),
6719                flags: WireFormat::parse_unchecked(buf),
6720            }
6721        }
6722    }
6723
6724    /// Target Integrity Risk (TIR) Level
6725    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6726    pub enum TargetIntegrityRiskTirLevel {
6727        /// Safe state, protection level shall not be used for safety-critical
6728        /// application
6729        SafeStateProtectionLevelShallNotBeUsedForSafetyCriticalApplication = 0,
6730
6731        /// TIR Level 1
6732        TirLevel1 = 1,
6733
6734        /// TIR Level 2
6735        TirLevel2 = 2,
6736
6737        /// TIR Level 3
6738        TirLevel3 = 3,
6739    }
6740
6741    impl std::fmt::Display for TargetIntegrityRiskTirLevel {
6742        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6743            match self {
6744            TargetIntegrityRiskTirLevel::SafeStateProtectionLevelShallNotBeUsedForSafetyCriticalApplication => f.write_str("Safe state, protection level shall not be used for safety-critical application"),
6745            TargetIntegrityRiskTirLevel::TirLevel1 => f.write_str("TIR Level 1"),
6746            TargetIntegrityRiskTirLevel::TirLevel2 => f.write_str("TIR Level 2"),
6747            TargetIntegrityRiskTirLevel::TirLevel3 => f.write_str("TIR Level 3"),
6748        }
6749        }
6750    }
6751
6752    impl TryFrom<u8> for TargetIntegrityRiskTirLevel {
6753        type Error = u8;
6754        fn try_from(i: u8) -> Result<Self, u8> {
6755            match i {
6756            0 => Ok( TargetIntegrityRiskTirLevel :: SafeStateProtectionLevelShallNotBeUsedForSafetyCriticalApplication ),
6757            1 => Ok( TargetIntegrityRiskTirLevel :: TirLevel1 ),
6758            2 => Ok( TargetIntegrityRiskTirLevel :: TirLevel2 ),
6759            3 => Ok( TargetIntegrityRiskTirLevel :: TirLevel3 ),
6760            i => Err(i),
6761        }
6762        }
6763    }
6764}
6765
6766pub mod msg_reference_frame_param {
6767    #![allow(unused_imports)]
6768
6769    use super::*;
6770    use crate::messages::lib::*;
6771    /// Reference Frame Transformation Parameters
6772    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6773    #[allow(clippy::derive_partial_eq_without_eq)]
6774    #[derive(Debug, PartialEq, Clone)]
6775    pub struct MsgReferenceFrameParam {
6776        /// The message sender_id
6777        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
6778        pub sender_id: Option<u16>,
6779        /// SSR IOD parameter.
6780        #[cfg_attr(feature = "serde", serde(rename = "ssr_iod"))]
6781        pub ssr_iod: u8,
6782        /// Name of source coordinate-system.
6783        #[cfg_attr(feature = "serde", serde(rename = "sn"))]
6784        pub sn: SbpString<[u8; 32], NullTerminated>,
6785        /// Name of target coordinate-system.
6786        #[cfg_attr(feature = "serde", serde(rename = "tn"))]
6787        pub tn: SbpString<[u8; 32], NullTerminated>,
6788        /// System Identification Number.
6789        #[cfg_attr(feature = "serde", serde(rename = "sin"))]
6790        pub sin: u8,
6791        /// Utilized Transformation Message.
6792        #[cfg_attr(feature = "serde", serde(rename = "utn"))]
6793        pub utn: u16,
6794        /// Reference Epoch t0 for transformation parameter set given as Modified
6795        /// Julian Day (MJD) Number minus 44244 days.
6796        #[cfg_attr(feature = "serde", serde(rename = "re_t0"))]
6797        pub re_t0: u16,
6798        /// Translation in X for Reference Epoch t0.
6799        #[cfg_attr(feature = "serde", serde(rename = "delta_X0"))]
6800        pub delta_x0: i32,
6801        /// Translation in Y for Reference Epoch t0.
6802        #[cfg_attr(feature = "serde", serde(rename = "delta_Y0"))]
6803        pub delta_y0: i32,
6804        /// Translation in Z for Reference Epoch t0.
6805        #[cfg_attr(feature = "serde", serde(rename = "delta_Z0"))]
6806        pub delta_z0: i32,
6807        /// Rotation around the X-axis for Reference Epoch t0.
6808        #[cfg_attr(feature = "serde", serde(rename = "theta_01"))]
6809        pub theta_01: i32,
6810        /// Rotation around the Y-axis for Reference Epoch t0.
6811        #[cfg_attr(feature = "serde", serde(rename = "theta_02"))]
6812        pub theta_02: i32,
6813        /// Rotation around the Z-axis for Reference Epoch t0.
6814        #[cfg_attr(feature = "serde", serde(rename = "theta_03"))]
6815        pub theta_03: i32,
6816        /// Scale correction for Reference Epoch t0.
6817        #[cfg_attr(feature = "serde", serde(rename = "scale"))]
6818        pub scale: i32,
6819        /// Rate of change of translation in X.
6820        #[cfg_attr(feature = "serde", serde(rename = "dot_delta_X0"))]
6821        pub dot_delta_x0: i32,
6822        /// Rate of change of translation in Y.
6823        #[cfg_attr(feature = "serde", serde(rename = "dot_delta_Y0"))]
6824        pub dot_delta_y0: i32,
6825        /// Rate of change of translation in Z.
6826        #[cfg_attr(feature = "serde", serde(rename = "dot_delta_Z0"))]
6827        pub dot_delta_z0: i32,
6828        /// Rate of change of rotation around the X-axis.
6829        #[cfg_attr(feature = "serde", serde(rename = "dot_theta_01"))]
6830        pub dot_theta_01: i32,
6831        /// Rate of change of rotation around the Y-axis.
6832        #[cfg_attr(feature = "serde", serde(rename = "dot_theta_02"))]
6833        pub dot_theta_02: i32,
6834        /// Rate of change of rotation around the Z-axis.
6835        #[cfg_attr(feature = "serde", serde(rename = "dot_theta_03"))]
6836        pub dot_theta_03: i32,
6837        /// Rate of change of scale correction.
6838        #[cfg_attr(feature = "serde", serde(rename = "dot_scale"))]
6839        pub dot_scale: i16,
6840    }
6841
6842    impl ConcreteMessage for MsgReferenceFrameParam {
6843        const MESSAGE_TYPE: u16 = 580;
6844        const MESSAGE_NAME: &'static str = "MSG_REFERENCE_FRAME_PARAM";
6845    }
6846
6847    impl SbpMessage for MsgReferenceFrameParam {
6848        fn message_name(&self) -> &'static str {
6849            <Self as ConcreteMessage>::MESSAGE_NAME
6850        }
6851        fn message_type(&self) -> Option<u16> {
6852            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
6853        }
6854        fn sender_id(&self) -> Option<u16> {
6855            self.sender_id
6856        }
6857        fn set_sender_id(&mut self, new_id: u16) {
6858            self.sender_id = Some(new_id);
6859        }
6860        fn encoded_len(&self) -> usize {
6861            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
6862        }
6863        fn is_valid(&self) -> bool {
6864            true
6865        }
6866        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
6867            Ok(self)
6868        }
6869    }
6870
6871    impl FriendlyName for MsgReferenceFrameParam {
6872        fn friendly_name() -> &'static str {
6873            "REFERENCE FRAME PARAM"
6874        }
6875    }
6876
6877    impl TryFrom<Sbp> for MsgReferenceFrameParam {
6878        type Error = TryFromSbpError;
6879        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
6880            match msg {
6881                Sbp::MsgReferenceFrameParam(m) => Ok(m),
6882                _ => Err(TryFromSbpError(msg)),
6883            }
6884        }
6885    }
6886
6887    impl WireFormat for MsgReferenceFrameParam {
6888        const MIN_LEN: usize = <u8 as WireFormat>::MIN_LEN
6889            + <SbpString<[u8; 32], NullTerminated> as WireFormat>::MIN_LEN
6890            + <SbpString<[u8; 32], NullTerminated> as WireFormat>::MIN_LEN
6891            + <u8 as WireFormat>::MIN_LEN
6892            + <u16 as WireFormat>::MIN_LEN
6893            + <u16 as WireFormat>::MIN_LEN
6894            + <i32 as WireFormat>::MIN_LEN
6895            + <i32 as WireFormat>::MIN_LEN
6896            + <i32 as WireFormat>::MIN_LEN
6897            + <i32 as WireFormat>::MIN_LEN
6898            + <i32 as WireFormat>::MIN_LEN
6899            + <i32 as WireFormat>::MIN_LEN
6900            + <i32 as WireFormat>::MIN_LEN
6901            + <i32 as WireFormat>::MIN_LEN
6902            + <i32 as WireFormat>::MIN_LEN
6903            + <i32 as WireFormat>::MIN_LEN
6904            + <i32 as WireFormat>::MIN_LEN
6905            + <i32 as WireFormat>::MIN_LEN
6906            + <i32 as WireFormat>::MIN_LEN
6907            + <i16 as WireFormat>::MIN_LEN;
6908        fn len(&self) -> usize {
6909            WireFormat::len(&self.ssr_iod)
6910                + WireFormat::len(&self.sn)
6911                + WireFormat::len(&self.tn)
6912                + WireFormat::len(&self.sin)
6913                + WireFormat::len(&self.utn)
6914                + WireFormat::len(&self.re_t0)
6915                + WireFormat::len(&self.delta_x0)
6916                + WireFormat::len(&self.delta_y0)
6917                + WireFormat::len(&self.delta_z0)
6918                + WireFormat::len(&self.theta_01)
6919                + WireFormat::len(&self.theta_02)
6920                + WireFormat::len(&self.theta_03)
6921                + WireFormat::len(&self.scale)
6922                + WireFormat::len(&self.dot_delta_x0)
6923                + WireFormat::len(&self.dot_delta_y0)
6924                + WireFormat::len(&self.dot_delta_z0)
6925                + WireFormat::len(&self.dot_theta_01)
6926                + WireFormat::len(&self.dot_theta_02)
6927                + WireFormat::len(&self.dot_theta_03)
6928                + WireFormat::len(&self.dot_scale)
6929        }
6930        fn write<B: BufMut>(&self, buf: &mut B) {
6931            WireFormat::write(&self.ssr_iod, buf);
6932            WireFormat::write(&self.sn, buf);
6933            WireFormat::write(&self.tn, buf);
6934            WireFormat::write(&self.sin, buf);
6935            WireFormat::write(&self.utn, buf);
6936            WireFormat::write(&self.re_t0, buf);
6937            WireFormat::write(&self.delta_x0, buf);
6938            WireFormat::write(&self.delta_y0, buf);
6939            WireFormat::write(&self.delta_z0, buf);
6940            WireFormat::write(&self.theta_01, buf);
6941            WireFormat::write(&self.theta_02, buf);
6942            WireFormat::write(&self.theta_03, buf);
6943            WireFormat::write(&self.scale, buf);
6944            WireFormat::write(&self.dot_delta_x0, buf);
6945            WireFormat::write(&self.dot_delta_y0, buf);
6946            WireFormat::write(&self.dot_delta_z0, buf);
6947            WireFormat::write(&self.dot_theta_01, buf);
6948            WireFormat::write(&self.dot_theta_02, buf);
6949            WireFormat::write(&self.dot_theta_03, buf);
6950            WireFormat::write(&self.dot_scale, buf);
6951        }
6952        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
6953            MsgReferenceFrameParam {
6954                sender_id: None,
6955                ssr_iod: WireFormat::parse_unchecked(buf),
6956                sn: WireFormat::parse_unchecked(buf),
6957                tn: WireFormat::parse_unchecked(buf),
6958                sin: WireFormat::parse_unchecked(buf),
6959                utn: WireFormat::parse_unchecked(buf),
6960                re_t0: WireFormat::parse_unchecked(buf),
6961                delta_x0: WireFormat::parse_unchecked(buf),
6962                delta_y0: WireFormat::parse_unchecked(buf),
6963                delta_z0: WireFormat::parse_unchecked(buf),
6964                theta_01: WireFormat::parse_unchecked(buf),
6965                theta_02: WireFormat::parse_unchecked(buf),
6966                theta_03: WireFormat::parse_unchecked(buf),
6967                scale: WireFormat::parse_unchecked(buf),
6968                dot_delta_x0: WireFormat::parse_unchecked(buf),
6969                dot_delta_y0: WireFormat::parse_unchecked(buf),
6970                dot_delta_z0: WireFormat::parse_unchecked(buf),
6971                dot_theta_01: WireFormat::parse_unchecked(buf),
6972                dot_theta_02: WireFormat::parse_unchecked(buf),
6973                dot_theta_03: WireFormat::parse_unchecked(buf),
6974                dot_scale: WireFormat::parse_unchecked(buf),
6975            }
6976        }
6977    }
6978}
6979
6980pub mod msg_utc_leap_second {
6981    #![allow(unused_imports)]
6982
6983    use super::*;
6984    use crate::messages::lib::*;
6985
6986    /// Leap second SBP message.
6987    ///
6988    /// UTC-GPST leap seconds before and after the most recent (past, or future,
6989    /// for announced insertions) UTC leap second insertion.
6990    ///
6991    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6992    #[allow(clippy::derive_partial_eq_without_eq)]
6993    #[derive(Debug, PartialEq, Clone)]
6994    pub struct MsgUtcLeapSecond {
6995        /// The message sender_id
6996        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
6997        pub sender_id: Option<u16>,
6998        /// Reserved.
6999        #[cfg_attr(feature = "serde", serde(rename = "reserved_0"))]
7000        pub reserved_0: i16,
7001        /// Reserved.
7002        #[cfg_attr(feature = "serde", serde(rename = "reserved_1"))]
7003        pub reserved_1: i16,
7004        /// Reserved.
7005        #[cfg_attr(feature = "serde", serde(rename = "reserved_2"))]
7006        pub reserved_2: i8,
7007        /// Leap second count before insertion.
7008        #[cfg_attr(feature = "serde", serde(rename = "count_before"))]
7009        pub count_before: i8,
7010        /// Reserved.
7011        #[cfg_attr(feature = "serde", serde(rename = "reserved_3"))]
7012        pub reserved_3: u16,
7013        /// Reserved.
7014        #[cfg_attr(feature = "serde", serde(rename = "reserved_4"))]
7015        pub reserved_4: u16,
7016        /// Leap second reference GPS week number.
7017        #[cfg_attr(feature = "serde", serde(rename = "ref_wn"))]
7018        pub ref_wn: u16,
7019        /// Leap second reference day number.
7020        #[cfg_attr(feature = "serde", serde(rename = "ref_dn"))]
7021        pub ref_dn: u8,
7022        /// Leap second count after insertion.
7023        #[cfg_attr(feature = "serde", serde(rename = "count_after"))]
7024        pub count_after: i8,
7025    }
7026
7027    impl ConcreteMessage for MsgUtcLeapSecond {
7028        const MESSAGE_TYPE: u16 = 570;
7029        const MESSAGE_NAME: &'static str = "MSG_UTC_LEAP_SECOND";
7030    }
7031
7032    impl SbpMessage for MsgUtcLeapSecond {
7033        fn message_name(&self) -> &'static str {
7034            <Self as ConcreteMessage>::MESSAGE_NAME
7035        }
7036        fn message_type(&self) -> Option<u16> {
7037            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
7038        }
7039        fn sender_id(&self) -> Option<u16> {
7040            self.sender_id
7041        }
7042        fn set_sender_id(&mut self, new_id: u16) {
7043            self.sender_id = Some(new_id);
7044        }
7045        fn encoded_len(&self) -> usize {
7046            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
7047        }
7048        fn is_valid(&self) -> bool {
7049            true
7050        }
7051        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
7052            Ok(self)
7053        }
7054    }
7055
7056    impl FriendlyName for MsgUtcLeapSecond {
7057        fn friendly_name() -> &'static str {
7058            "UTC LEAP SECOND"
7059        }
7060    }
7061
7062    impl TryFrom<Sbp> for MsgUtcLeapSecond {
7063        type Error = TryFromSbpError;
7064        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
7065            match msg {
7066                Sbp::MsgUtcLeapSecond(m) => Ok(m),
7067                _ => Err(TryFromSbpError(msg)),
7068            }
7069        }
7070    }
7071
7072    impl WireFormat for MsgUtcLeapSecond {
7073        const MIN_LEN: usize = <i16 as WireFormat>::MIN_LEN
7074            + <i16 as WireFormat>::MIN_LEN
7075            + <i8 as WireFormat>::MIN_LEN
7076            + <i8 as WireFormat>::MIN_LEN
7077            + <u16 as WireFormat>::MIN_LEN
7078            + <u16 as WireFormat>::MIN_LEN
7079            + <u16 as WireFormat>::MIN_LEN
7080            + <u8 as WireFormat>::MIN_LEN
7081            + <i8 as WireFormat>::MIN_LEN;
7082        fn len(&self) -> usize {
7083            WireFormat::len(&self.reserved_0)
7084                + WireFormat::len(&self.reserved_1)
7085                + WireFormat::len(&self.reserved_2)
7086                + WireFormat::len(&self.count_before)
7087                + WireFormat::len(&self.reserved_3)
7088                + WireFormat::len(&self.reserved_4)
7089                + WireFormat::len(&self.ref_wn)
7090                + WireFormat::len(&self.ref_dn)
7091                + WireFormat::len(&self.count_after)
7092        }
7093        fn write<B: BufMut>(&self, buf: &mut B) {
7094            WireFormat::write(&self.reserved_0, buf);
7095            WireFormat::write(&self.reserved_1, buf);
7096            WireFormat::write(&self.reserved_2, buf);
7097            WireFormat::write(&self.count_before, buf);
7098            WireFormat::write(&self.reserved_3, buf);
7099            WireFormat::write(&self.reserved_4, buf);
7100            WireFormat::write(&self.ref_wn, buf);
7101            WireFormat::write(&self.ref_dn, buf);
7102            WireFormat::write(&self.count_after, buf);
7103        }
7104        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
7105            MsgUtcLeapSecond {
7106                sender_id: None,
7107                reserved_0: WireFormat::parse_unchecked(buf),
7108                reserved_1: WireFormat::parse_unchecked(buf),
7109                reserved_2: WireFormat::parse_unchecked(buf),
7110                count_before: WireFormat::parse_unchecked(buf),
7111                reserved_3: WireFormat::parse_unchecked(buf),
7112                reserved_4: WireFormat::parse_unchecked(buf),
7113                ref_wn: WireFormat::parse_unchecked(buf),
7114                ref_dn: WireFormat::parse_unchecked(buf),
7115                count_after: WireFormat::parse_unchecked(buf),
7116            }
7117        }
7118    }
7119}
7120
7121pub mod msg_utc_time {
7122    #![allow(unused_imports)]
7123
7124    use super::*;
7125    use crate::messages::lib::*;
7126
7127    /// UTC Time
7128    ///
7129    /// This message reports the Universal Coordinated Time (UTC).  Note the flags
7130    /// which indicate the source of the UTC offset value and source of the time
7131    /// fix.
7132    ///
7133    /// The values in this message are from GNSS measurements fused with inertial
7134    /// measurements. To get values from GNSS measurements only use
7135    /// MSG_UTC_TIME_GNSS.
7136    ///
7137    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7138    #[allow(clippy::derive_partial_eq_without_eq)]
7139    #[derive(Debug, PartialEq, Clone)]
7140    pub struct MsgUtcTime {
7141        /// The message sender_id
7142        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
7143        pub sender_id: Option<u16>,
7144        /// Indicates source and time validity
7145        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
7146        pub flags: u8,
7147        /// GPS time of week rounded to the nearest millisecond
7148        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
7149        pub tow: u32,
7150        /// Year
7151        #[cfg_attr(feature = "serde", serde(rename = "year"))]
7152        pub year: u16,
7153        /// Month (range 1 .. 12)
7154        #[cfg_attr(feature = "serde", serde(rename = "month"))]
7155        pub month: u8,
7156        /// days in the month (range 1-31)
7157        #[cfg_attr(feature = "serde", serde(rename = "day"))]
7158        pub day: u8,
7159        /// hours of day (range 0-23)
7160        #[cfg_attr(feature = "serde", serde(rename = "hours"))]
7161        pub hours: u8,
7162        /// minutes of hour (range 0-59)
7163        #[cfg_attr(feature = "serde", serde(rename = "minutes"))]
7164        pub minutes: u8,
7165        /// seconds of minute (range 0-60) rounded down
7166        #[cfg_attr(feature = "serde", serde(rename = "seconds"))]
7167        pub seconds: u8,
7168        /// nanoseconds of second (range 0-999999999)
7169        #[cfg_attr(feature = "serde", serde(rename = "ns"))]
7170        pub ns: u32,
7171    }
7172
7173    impl MsgUtcTime {
7174        /// Gets the [UtcOffsetSource][self::UtcOffsetSource] stored in the `flags` bitfield.
7175        ///
7176        /// Returns `Ok` if the bitrange contains a known `UtcOffsetSource` variant.
7177        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7178        /// or because new variants of `UtcOffsetSource` were added.
7179        pub fn utc_offset_source(&self) -> Result<UtcOffsetSource, u8> {
7180            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
7181        }
7182
7183        /// Set the bitrange corresponding to the [UtcOffsetSource][UtcOffsetSource] of the `flags` bitfield.
7184        pub fn set_utc_offset_source(&mut self, utc_offset_source: UtcOffsetSource) {
7185            set_bit_range!(&mut self.flags, utc_offset_source, u8, u8, 4, 3);
7186        }
7187
7188        /// Gets the [TimeSource][self::TimeSource] stored in the `flags` bitfield.
7189        ///
7190        /// Returns `Ok` if the bitrange contains a known `TimeSource` variant.
7191        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7192        /// or because new variants of `TimeSource` were added.
7193        pub fn time_source(&self) -> Result<TimeSource, u8> {
7194            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
7195        }
7196
7197        /// Set the bitrange corresponding to the [TimeSource][TimeSource] of the `flags` bitfield.
7198        pub fn set_time_source(&mut self, time_source: TimeSource) {
7199            set_bit_range!(&mut self.flags, time_source, u8, u8, 2, 0);
7200        }
7201    }
7202
7203    impl ConcreteMessage for MsgUtcTime {
7204        const MESSAGE_TYPE: u16 = 259;
7205        const MESSAGE_NAME: &'static str = "MSG_UTC_TIME";
7206    }
7207
7208    impl SbpMessage for MsgUtcTime {
7209        fn message_name(&self) -> &'static str {
7210            <Self as ConcreteMessage>::MESSAGE_NAME
7211        }
7212        fn message_type(&self) -> Option<u16> {
7213            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
7214        }
7215        fn sender_id(&self) -> Option<u16> {
7216            self.sender_id
7217        }
7218        fn set_sender_id(&mut self, new_id: u16) {
7219            self.sender_id = Some(new_id);
7220        }
7221        fn encoded_len(&self) -> usize {
7222            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
7223        }
7224        fn is_valid(&self) -> bool {
7225            true
7226        }
7227        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
7228            Ok(self)
7229        }
7230
7231        #[cfg(feature = "swiftnav")]
7232        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
7233            if self.time_source().ok()? == TimeSource::None {
7234                return None;
7235            }
7236            let tow_s = (self.tow as f64) / 1000.0;
7237            let gps_time = match time::GpsTime::new(0, tow_s) {
7238                Ok(gps_time) => gps_time.tow(),
7239                Err(e) => return Some(Err(e.into())),
7240            };
7241            Some(Ok(time::MessageTime::Rover(gps_time.into())))
7242        }
7243    }
7244
7245    impl FriendlyName for MsgUtcTime {
7246        fn friendly_name() -> &'static str {
7247            "UTC TIME"
7248        }
7249    }
7250
7251    impl TryFrom<Sbp> for MsgUtcTime {
7252        type Error = TryFromSbpError;
7253        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
7254            match msg {
7255                Sbp::MsgUtcTime(m) => Ok(m),
7256                _ => Err(TryFromSbpError(msg)),
7257            }
7258        }
7259    }
7260
7261    impl WireFormat for MsgUtcTime {
7262        const MIN_LEN: usize = <u8 as WireFormat>::MIN_LEN
7263            + <u32 as WireFormat>::MIN_LEN
7264            + <u16 as WireFormat>::MIN_LEN
7265            + <u8 as WireFormat>::MIN_LEN
7266            + <u8 as WireFormat>::MIN_LEN
7267            + <u8 as WireFormat>::MIN_LEN
7268            + <u8 as WireFormat>::MIN_LEN
7269            + <u8 as WireFormat>::MIN_LEN
7270            + <u32 as WireFormat>::MIN_LEN;
7271        fn len(&self) -> usize {
7272            WireFormat::len(&self.flags)
7273                + WireFormat::len(&self.tow)
7274                + WireFormat::len(&self.year)
7275                + WireFormat::len(&self.month)
7276                + WireFormat::len(&self.day)
7277                + WireFormat::len(&self.hours)
7278                + WireFormat::len(&self.minutes)
7279                + WireFormat::len(&self.seconds)
7280                + WireFormat::len(&self.ns)
7281        }
7282        fn write<B: BufMut>(&self, buf: &mut B) {
7283            WireFormat::write(&self.flags, buf);
7284            WireFormat::write(&self.tow, buf);
7285            WireFormat::write(&self.year, buf);
7286            WireFormat::write(&self.month, buf);
7287            WireFormat::write(&self.day, buf);
7288            WireFormat::write(&self.hours, buf);
7289            WireFormat::write(&self.minutes, buf);
7290            WireFormat::write(&self.seconds, buf);
7291            WireFormat::write(&self.ns, buf);
7292        }
7293        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
7294            MsgUtcTime {
7295                sender_id: None,
7296                flags: WireFormat::parse_unchecked(buf),
7297                tow: WireFormat::parse_unchecked(buf),
7298                year: WireFormat::parse_unchecked(buf),
7299                month: WireFormat::parse_unchecked(buf),
7300                day: WireFormat::parse_unchecked(buf),
7301                hours: WireFormat::parse_unchecked(buf),
7302                minutes: WireFormat::parse_unchecked(buf),
7303                seconds: WireFormat::parse_unchecked(buf),
7304                ns: WireFormat::parse_unchecked(buf),
7305            }
7306        }
7307    }
7308
7309    /// UTC offset source
7310    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7311    pub enum UtcOffsetSource {
7312        /// Factory Default
7313        FactoryDefault = 0,
7314
7315        /// Non Volatile Memory
7316        NonVolatileMemory = 1,
7317
7318        /// Decoded this Session
7319        DecodedThisSession = 2,
7320    }
7321
7322    impl std::fmt::Display for UtcOffsetSource {
7323        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7324            match self {
7325                UtcOffsetSource::FactoryDefault => f.write_str("Factory Default"),
7326                UtcOffsetSource::NonVolatileMemory => f.write_str("Non Volatile Memory"),
7327                UtcOffsetSource::DecodedThisSession => f.write_str("Decoded this Session"),
7328            }
7329        }
7330    }
7331
7332    impl TryFrom<u8> for UtcOffsetSource {
7333        type Error = u8;
7334        fn try_from(i: u8) -> Result<Self, u8> {
7335            match i {
7336                0 => Ok(UtcOffsetSource::FactoryDefault),
7337                1 => Ok(UtcOffsetSource::NonVolatileMemory),
7338                2 => Ok(UtcOffsetSource::DecodedThisSession),
7339                i => Err(i),
7340            }
7341        }
7342    }
7343
7344    /// Time source
7345    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7346    pub enum TimeSource {
7347        /// None (invalid)
7348        None = 0,
7349
7350        /// GNSS Solution
7351        GnssSolution = 1,
7352
7353        /// Propagated
7354        Propagated = 2,
7355    }
7356
7357    impl std::fmt::Display for TimeSource {
7358        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7359            match self {
7360                TimeSource::None => f.write_str("None (invalid)"),
7361                TimeSource::GnssSolution => f.write_str("GNSS Solution"),
7362                TimeSource::Propagated => f.write_str("Propagated"),
7363            }
7364        }
7365    }
7366
7367    impl TryFrom<u8> for TimeSource {
7368        type Error = u8;
7369        fn try_from(i: u8) -> Result<Self, u8> {
7370            match i {
7371                0 => Ok(TimeSource::None),
7372                1 => Ok(TimeSource::GnssSolution),
7373                2 => Ok(TimeSource::Propagated),
7374                i => Err(i),
7375            }
7376        }
7377    }
7378}
7379
7380pub mod msg_utc_time_gnss {
7381    #![allow(unused_imports)]
7382
7383    use super::*;
7384    use crate::messages::lib::*;
7385
7386    /// GNSS-only UTC Time
7387    ///
7388    /// This message reports the Universal Coordinated Time (UTC).  Note the flags
7389    /// which indicate the source of the UTC offset value and source of the time
7390    /// fix.
7391    ///
7392    /// The values in this message are from GNSS measurements only. To get values
7393    /// fused with inertial measurements use MSG_UTC_TIME.
7394    ///
7395    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7396    #[allow(clippy::derive_partial_eq_without_eq)]
7397    #[derive(Debug, PartialEq, Clone)]
7398    pub struct MsgUtcTimeGnss {
7399        /// The message sender_id
7400        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
7401        pub sender_id: Option<u16>,
7402        /// Indicates source and time validity
7403        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
7404        pub flags: u8,
7405        /// GPS time of week rounded to the nearest millisecond
7406        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
7407        pub tow: u32,
7408        /// Year
7409        #[cfg_attr(feature = "serde", serde(rename = "year"))]
7410        pub year: u16,
7411        /// Month (range 1 .. 12)
7412        #[cfg_attr(feature = "serde", serde(rename = "month"))]
7413        pub month: u8,
7414        /// days in the month (range 1-31)
7415        #[cfg_attr(feature = "serde", serde(rename = "day"))]
7416        pub day: u8,
7417        /// hours of day (range 0-23)
7418        #[cfg_attr(feature = "serde", serde(rename = "hours"))]
7419        pub hours: u8,
7420        /// minutes of hour (range 0-59)
7421        #[cfg_attr(feature = "serde", serde(rename = "minutes"))]
7422        pub minutes: u8,
7423        /// seconds of minute (range 0-60) rounded down
7424        #[cfg_attr(feature = "serde", serde(rename = "seconds"))]
7425        pub seconds: u8,
7426        /// nanoseconds of second (range 0-999999999)
7427        #[cfg_attr(feature = "serde", serde(rename = "ns"))]
7428        pub ns: u32,
7429    }
7430
7431    impl MsgUtcTimeGnss {
7432        /// Gets the [UtcOffsetSource][self::UtcOffsetSource] stored in the `flags` bitfield.
7433        ///
7434        /// Returns `Ok` if the bitrange contains a known `UtcOffsetSource` variant.
7435        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7436        /// or because new variants of `UtcOffsetSource` were added.
7437        pub fn utc_offset_source(&self) -> Result<UtcOffsetSource, u8> {
7438            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
7439        }
7440
7441        /// Set the bitrange corresponding to the [UtcOffsetSource][UtcOffsetSource] of the `flags` bitfield.
7442        pub fn set_utc_offset_source(&mut self, utc_offset_source: UtcOffsetSource) {
7443            set_bit_range!(&mut self.flags, utc_offset_source, u8, u8, 4, 3);
7444        }
7445
7446        /// Gets the [TimeSource][self::TimeSource] stored in the `flags` bitfield.
7447        ///
7448        /// Returns `Ok` if the bitrange contains a known `TimeSource` variant.
7449        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7450        /// or because new variants of `TimeSource` were added.
7451        pub fn time_source(&self) -> Result<TimeSource, u8> {
7452            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
7453        }
7454
7455        /// Set the bitrange corresponding to the [TimeSource][TimeSource] of the `flags` bitfield.
7456        pub fn set_time_source(&mut self, time_source: TimeSource) {
7457            set_bit_range!(&mut self.flags, time_source, u8, u8, 2, 0);
7458        }
7459    }
7460
7461    impl ConcreteMessage for MsgUtcTimeGnss {
7462        const MESSAGE_TYPE: u16 = 261;
7463        const MESSAGE_NAME: &'static str = "MSG_UTC_TIME_GNSS";
7464    }
7465
7466    impl SbpMessage for MsgUtcTimeGnss {
7467        fn message_name(&self) -> &'static str {
7468            <Self as ConcreteMessage>::MESSAGE_NAME
7469        }
7470        fn message_type(&self) -> Option<u16> {
7471            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
7472        }
7473        fn sender_id(&self) -> Option<u16> {
7474            self.sender_id
7475        }
7476        fn set_sender_id(&mut self, new_id: u16) {
7477            self.sender_id = Some(new_id);
7478        }
7479        fn encoded_len(&self) -> usize {
7480            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
7481        }
7482        fn is_valid(&self) -> bool {
7483            true
7484        }
7485        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
7486            Ok(self)
7487        }
7488
7489        #[cfg(feature = "swiftnav")]
7490        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
7491            if self.time_source().ok()? == TimeSource::None {
7492                return None;
7493            }
7494            let tow_s = (self.tow as f64) / 1000.0;
7495            let gps_time = match time::GpsTime::new(0, tow_s) {
7496                Ok(gps_time) => gps_time.tow(),
7497                Err(e) => return Some(Err(e.into())),
7498            };
7499            Some(Ok(time::MessageTime::Rover(gps_time.into())))
7500        }
7501    }
7502
7503    impl FriendlyName for MsgUtcTimeGnss {
7504        fn friendly_name() -> &'static str {
7505            "UTC TIME GNSS-only"
7506        }
7507    }
7508
7509    impl TryFrom<Sbp> for MsgUtcTimeGnss {
7510        type Error = TryFromSbpError;
7511        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
7512            match msg {
7513                Sbp::MsgUtcTimeGnss(m) => Ok(m),
7514                _ => Err(TryFromSbpError(msg)),
7515            }
7516        }
7517    }
7518
7519    impl WireFormat for MsgUtcTimeGnss {
7520        const MIN_LEN: usize = <u8 as WireFormat>::MIN_LEN
7521            + <u32 as WireFormat>::MIN_LEN
7522            + <u16 as WireFormat>::MIN_LEN
7523            + <u8 as WireFormat>::MIN_LEN
7524            + <u8 as WireFormat>::MIN_LEN
7525            + <u8 as WireFormat>::MIN_LEN
7526            + <u8 as WireFormat>::MIN_LEN
7527            + <u8 as WireFormat>::MIN_LEN
7528            + <u32 as WireFormat>::MIN_LEN;
7529        fn len(&self) -> usize {
7530            WireFormat::len(&self.flags)
7531                + WireFormat::len(&self.tow)
7532                + WireFormat::len(&self.year)
7533                + WireFormat::len(&self.month)
7534                + WireFormat::len(&self.day)
7535                + WireFormat::len(&self.hours)
7536                + WireFormat::len(&self.minutes)
7537                + WireFormat::len(&self.seconds)
7538                + WireFormat::len(&self.ns)
7539        }
7540        fn write<B: BufMut>(&self, buf: &mut B) {
7541            WireFormat::write(&self.flags, buf);
7542            WireFormat::write(&self.tow, buf);
7543            WireFormat::write(&self.year, buf);
7544            WireFormat::write(&self.month, buf);
7545            WireFormat::write(&self.day, buf);
7546            WireFormat::write(&self.hours, buf);
7547            WireFormat::write(&self.minutes, buf);
7548            WireFormat::write(&self.seconds, buf);
7549            WireFormat::write(&self.ns, buf);
7550        }
7551        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
7552            MsgUtcTimeGnss {
7553                sender_id: None,
7554                flags: WireFormat::parse_unchecked(buf),
7555                tow: WireFormat::parse_unchecked(buf),
7556                year: WireFormat::parse_unchecked(buf),
7557                month: WireFormat::parse_unchecked(buf),
7558                day: WireFormat::parse_unchecked(buf),
7559                hours: WireFormat::parse_unchecked(buf),
7560                minutes: WireFormat::parse_unchecked(buf),
7561                seconds: WireFormat::parse_unchecked(buf),
7562                ns: WireFormat::parse_unchecked(buf),
7563            }
7564        }
7565    }
7566
7567    /// UTC offset source
7568    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7569    pub enum UtcOffsetSource {
7570        /// Factory Default
7571        FactoryDefault = 0,
7572
7573        /// Non Volatile Memory
7574        NonVolatileMemory = 1,
7575
7576        /// Decoded this Session
7577        DecodedThisSession = 2,
7578    }
7579
7580    impl std::fmt::Display for UtcOffsetSource {
7581        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7582            match self {
7583                UtcOffsetSource::FactoryDefault => f.write_str("Factory Default"),
7584                UtcOffsetSource::NonVolatileMemory => f.write_str("Non Volatile Memory"),
7585                UtcOffsetSource::DecodedThisSession => f.write_str("Decoded this Session"),
7586            }
7587        }
7588    }
7589
7590    impl TryFrom<u8> for UtcOffsetSource {
7591        type Error = u8;
7592        fn try_from(i: u8) -> Result<Self, u8> {
7593            match i {
7594                0 => Ok(UtcOffsetSource::FactoryDefault),
7595                1 => Ok(UtcOffsetSource::NonVolatileMemory),
7596                2 => Ok(UtcOffsetSource::DecodedThisSession),
7597                i => Err(i),
7598            }
7599        }
7600    }
7601
7602    /// Time source
7603    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7604    pub enum TimeSource {
7605        /// None (invalid)
7606        None = 0,
7607
7608        /// GNSS Solution
7609        GnssSolution = 1,
7610
7611        /// Propagated
7612        Propagated = 2,
7613    }
7614
7615    impl std::fmt::Display for TimeSource {
7616        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7617            match self {
7618                TimeSource::None => f.write_str("None (invalid)"),
7619                TimeSource::GnssSolution => f.write_str("GNSS Solution"),
7620                TimeSource::Propagated => f.write_str("Propagated"),
7621            }
7622        }
7623    }
7624
7625    impl TryFrom<u8> for TimeSource {
7626        type Error = u8;
7627        fn try_from(i: u8) -> Result<Self, u8> {
7628            match i {
7629                0 => Ok(TimeSource::None),
7630                1 => Ok(TimeSource::GnssSolution),
7631                2 => Ok(TimeSource::Propagated),
7632                i => Err(i),
7633            }
7634        }
7635    }
7636}
7637
7638pub mod msg_vel_body {
7639    #![allow(unused_imports)]
7640
7641    use super::*;
7642    use crate::messages::lib::*;
7643
7644    /// Velocity in User Frame
7645    ///
7646    /// This message reports the velocity in the Vehicle Body Frame. By
7647    /// convention, the x-axis should point out the nose of the vehicle and
7648    /// represent the forward direction, while as the y-axis should point out the
7649    /// right hand side of the vehicle. Since this is a right handed system, z
7650    /// should point out the bottom of the vehicle. The orientation and origin of
7651    /// the Vehicle Body Frame are specified via the device settings. The full GPS
7652    /// time is given by the preceding MSG_GPS_TIME with the matching time-of-week
7653    /// (tow). This message is only produced by inertial versions of Swift
7654    /// products and is not available from Piksi Multi or Duro.
7655    ///
7656    /// The values in this message are from GNSS measurements fused with inertial
7657    /// measurements.
7658    ///
7659    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7660    #[allow(clippy::derive_partial_eq_without_eq)]
7661    #[derive(Debug, PartialEq, Clone)]
7662    pub struct MsgVelBody {
7663        /// The message sender_id
7664        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
7665        pub sender_id: Option<u16>,
7666        /// GPS Time of Week
7667        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
7668        pub tow: u32,
7669        /// Velocity in x direction
7670        #[cfg_attr(feature = "serde", serde(rename = "x"))]
7671        pub x: i32,
7672        /// Velocity in y direction
7673        #[cfg_attr(feature = "serde", serde(rename = "y"))]
7674        pub y: i32,
7675        /// Velocity in z direction
7676        #[cfg_attr(feature = "serde", serde(rename = "z"))]
7677        pub z: i32,
7678        /// Estimated variance of x
7679        #[cfg_attr(feature = "serde", serde(rename = "cov_x_x"))]
7680        pub cov_x_x: f32,
7681        /// Covariance of x and y
7682        #[cfg_attr(feature = "serde", serde(rename = "cov_x_y"))]
7683        pub cov_x_y: f32,
7684        /// Covariance of x and z
7685        #[cfg_attr(feature = "serde", serde(rename = "cov_x_z"))]
7686        pub cov_x_z: f32,
7687        /// Estimated variance of y
7688        #[cfg_attr(feature = "serde", serde(rename = "cov_y_y"))]
7689        pub cov_y_y: f32,
7690        /// Covariance of y and z
7691        #[cfg_attr(feature = "serde", serde(rename = "cov_y_z"))]
7692        pub cov_y_z: f32,
7693        /// Estimated variance of z
7694        #[cfg_attr(feature = "serde", serde(rename = "cov_z_z"))]
7695        pub cov_z_z: f32,
7696        /// Number of satellites used in solution
7697        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
7698        pub n_sats: u8,
7699        /// Status flags
7700        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
7701        pub flags: u8,
7702    }
7703
7704    impl MsgVelBody {
7705        /// Gets the [InsNavigationMode][self::InsNavigationMode] stored in the `flags` bitfield.
7706        ///
7707        /// Returns `Ok` if the bitrange contains a known `InsNavigationMode` variant.
7708        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7709        /// or because new variants of `InsNavigationMode` were added.
7710        pub fn ins_navigation_mode(&self) -> Result<InsNavigationMode, u8> {
7711            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
7712        }
7713
7714        /// Set the bitrange corresponding to the [InsNavigationMode][InsNavigationMode] of the `flags` bitfield.
7715        pub fn set_ins_navigation_mode(&mut self, ins_navigation_mode: InsNavigationMode) {
7716            set_bit_range!(&mut self.flags, ins_navigation_mode, u8, u8, 4, 3);
7717        }
7718
7719        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
7720        ///
7721        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
7722        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7723        /// or because new variants of `VelocityMode` were added.
7724        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
7725            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
7726        }
7727
7728        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
7729        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
7730            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
7731        }
7732    }
7733
7734    impl ConcreteMessage for MsgVelBody {
7735        const MESSAGE_TYPE: u16 = 531;
7736        const MESSAGE_NAME: &'static str = "MSG_VEL_BODY";
7737    }
7738
7739    impl SbpMessage for MsgVelBody {
7740        fn message_name(&self) -> &'static str {
7741            <Self as ConcreteMessage>::MESSAGE_NAME
7742        }
7743        fn message_type(&self) -> Option<u16> {
7744            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
7745        }
7746        fn sender_id(&self) -> Option<u16> {
7747            self.sender_id
7748        }
7749        fn set_sender_id(&mut self, new_id: u16) {
7750            self.sender_id = Some(new_id);
7751        }
7752        fn encoded_len(&self) -> usize {
7753            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
7754        }
7755        fn is_valid(&self) -> bool {
7756            true
7757        }
7758        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
7759            Ok(self)
7760        }
7761
7762        #[cfg(feature = "swiftnav")]
7763        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
7764            let tow_s = (self.tow as f64) / 1000.0;
7765            let gps_time = match time::GpsTime::new(0, tow_s) {
7766                Ok(gps_time) => gps_time.tow(),
7767                Err(e) => return Some(Err(e.into())),
7768            };
7769            Some(Ok(time::MessageTime::Rover(gps_time.into())))
7770        }
7771    }
7772
7773    impl FriendlyName for MsgVelBody {
7774        fn friendly_name() -> &'static str {
7775            "VEL BODY"
7776        }
7777    }
7778
7779    impl TryFrom<Sbp> for MsgVelBody {
7780        type Error = TryFromSbpError;
7781        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
7782            match msg {
7783                Sbp::MsgVelBody(m) => Ok(m),
7784                _ => Err(TryFromSbpError(msg)),
7785            }
7786        }
7787    }
7788
7789    impl WireFormat for MsgVelBody {
7790        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
7791            + <i32 as WireFormat>::MIN_LEN
7792            + <i32 as WireFormat>::MIN_LEN
7793            + <i32 as WireFormat>::MIN_LEN
7794            + <f32 as WireFormat>::MIN_LEN
7795            + <f32 as WireFormat>::MIN_LEN
7796            + <f32 as WireFormat>::MIN_LEN
7797            + <f32 as WireFormat>::MIN_LEN
7798            + <f32 as WireFormat>::MIN_LEN
7799            + <f32 as WireFormat>::MIN_LEN
7800            + <u8 as WireFormat>::MIN_LEN
7801            + <u8 as WireFormat>::MIN_LEN;
7802        fn len(&self) -> usize {
7803            WireFormat::len(&self.tow)
7804                + WireFormat::len(&self.x)
7805                + WireFormat::len(&self.y)
7806                + WireFormat::len(&self.z)
7807                + WireFormat::len(&self.cov_x_x)
7808                + WireFormat::len(&self.cov_x_y)
7809                + WireFormat::len(&self.cov_x_z)
7810                + WireFormat::len(&self.cov_y_y)
7811                + WireFormat::len(&self.cov_y_z)
7812                + WireFormat::len(&self.cov_z_z)
7813                + WireFormat::len(&self.n_sats)
7814                + WireFormat::len(&self.flags)
7815        }
7816        fn write<B: BufMut>(&self, buf: &mut B) {
7817            WireFormat::write(&self.tow, buf);
7818            WireFormat::write(&self.x, buf);
7819            WireFormat::write(&self.y, buf);
7820            WireFormat::write(&self.z, buf);
7821            WireFormat::write(&self.cov_x_x, buf);
7822            WireFormat::write(&self.cov_x_y, buf);
7823            WireFormat::write(&self.cov_x_z, buf);
7824            WireFormat::write(&self.cov_y_y, buf);
7825            WireFormat::write(&self.cov_y_z, buf);
7826            WireFormat::write(&self.cov_z_z, buf);
7827            WireFormat::write(&self.n_sats, buf);
7828            WireFormat::write(&self.flags, buf);
7829        }
7830        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
7831            MsgVelBody {
7832                sender_id: None,
7833                tow: WireFormat::parse_unchecked(buf),
7834                x: WireFormat::parse_unchecked(buf),
7835                y: WireFormat::parse_unchecked(buf),
7836                z: WireFormat::parse_unchecked(buf),
7837                cov_x_x: WireFormat::parse_unchecked(buf),
7838                cov_x_y: WireFormat::parse_unchecked(buf),
7839                cov_x_z: WireFormat::parse_unchecked(buf),
7840                cov_y_y: WireFormat::parse_unchecked(buf),
7841                cov_y_z: WireFormat::parse_unchecked(buf),
7842                cov_z_z: WireFormat::parse_unchecked(buf),
7843                n_sats: WireFormat::parse_unchecked(buf),
7844                flags: WireFormat::parse_unchecked(buf),
7845            }
7846        }
7847    }
7848
7849    /// INS Navigation Mode
7850    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7851    pub enum InsNavigationMode {
7852        /// None
7853        None = 0,
7854
7855        /// INS used
7856        InsUsed = 1,
7857    }
7858
7859    impl std::fmt::Display for InsNavigationMode {
7860        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7861            match self {
7862                InsNavigationMode::None => f.write_str("None"),
7863                InsNavigationMode::InsUsed => f.write_str("INS used"),
7864            }
7865        }
7866    }
7867
7868    impl TryFrom<u8> for InsNavigationMode {
7869        type Error = u8;
7870        fn try_from(i: u8) -> Result<Self, u8> {
7871            match i {
7872                0 => Ok(InsNavigationMode::None),
7873                1 => Ok(InsNavigationMode::InsUsed),
7874                i => Err(i),
7875            }
7876        }
7877    }
7878
7879    /// Velocity mode
7880    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7881    pub enum VelocityMode {
7882        /// Invalid
7883        Invalid = 0,
7884
7885        /// Measured Doppler derived
7886        MeasuredDopplerDerived = 1,
7887
7888        /// Computed Doppler derived
7889        ComputedDopplerDerived = 2,
7890
7891        /// Dead Reckoning
7892        DeadReckoning = 3,
7893    }
7894
7895    impl std::fmt::Display for VelocityMode {
7896        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7897            match self {
7898                VelocityMode::Invalid => f.write_str("Invalid"),
7899                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
7900                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
7901                VelocityMode::DeadReckoning => f.write_str("Dead Reckoning"),
7902            }
7903        }
7904    }
7905
7906    impl TryFrom<u8> for VelocityMode {
7907        type Error = u8;
7908        fn try_from(i: u8) -> Result<Self, u8> {
7909            match i {
7910                0 => Ok(VelocityMode::Invalid),
7911                1 => Ok(VelocityMode::MeasuredDopplerDerived),
7912                2 => Ok(VelocityMode::ComputedDopplerDerived),
7913                3 => Ok(VelocityMode::DeadReckoning),
7914                i => Err(i),
7915            }
7916        }
7917    }
7918}
7919
7920pub mod msg_vel_cog {
7921    #![allow(unused_imports)]
7922
7923    use super::*;
7924    use crate::messages::lib::*;
7925
7926    /// Velocity expressed as course over ground
7927    ///
7928    /// This message reports the receiver course over ground (COG) and speed over
7929    /// ground (SOG) based on the horizontal (N-E) components of the NED velocity
7930    /// vector. It also includes the vertical velocity coordinate. A flag is
7931    /// provided to indicate whether the COG value has been frozen. When the flag
7932    /// is set to true, the COG field is set to its last valid value until the
7933    /// system exceeds a minimum velocity threshold. No other fields are affected
7934    /// by this flag. The NED coordinate system is defined as the local WGS84
7935    /// tangent plane centered at the current position. The full GPS time is given
7936    /// by the preceding MSG_GPS_TIME with the matching time-of-week (tow). Note:
7937    /// course over ground represents the receiver's direction of travel, but not
7938    /// necessarily the device heading.
7939    ///
7940    /// The values in this message are from GNSS measurements fused with inertial
7941    /// measurements.
7942    ///
7943    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7944    #[allow(clippy::derive_partial_eq_without_eq)]
7945    #[derive(Debug, PartialEq, Clone)]
7946    pub struct MsgVelCog {
7947        /// The message sender_id
7948        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
7949        pub sender_id: Option<u16>,
7950        /// GPS Time of Week
7951        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
7952        pub tow: u32,
7953        /// Course over ground relative to north direction
7954        #[cfg_attr(feature = "serde", serde(rename = "cog"))]
7955        pub cog: u32,
7956        /// Speed over ground (based on horizontal velocity)
7957        #[cfg_attr(feature = "serde", serde(rename = "sog"))]
7958        pub sog: u32,
7959        /// Vertical velocity component (positive up)
7960        #[cfg_attr(feature = "serde", serde(rename = "v_up"))]
7961        pub v_up: i32,
7962        /// Course over ground estimated standard deviation
7963        #[cfg_attr(feature = "serde", serde(rename = "cog_accuracy"))]
7964        pub cog_accuracy: u32,
7965        /// Speed over ground estimated standard deviation
7966        #[cfg_attr(feature = "serde", serde(rename = "sog_accuracy"))]
7967        pub sog_accuracy: u32,
7968        /// Vertical velocity estimated standard deviation
7969        #[cfg_attr(feature = "serde", serde(rename = "v_up_accuracy"))]
7970        pub v_up_accuracy: u32,
7971        /// Status flags
7972        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
7973        pub flags: u16,
7974    }
7975
7976    impl MsgVelCog {
7977        /// Gets the [CogFrozen][self::CogFrozen] stored in the `flags` bitfield.
7978        ///
7979        /// Returns `Ok` if the bitrange contains a known `CogFrozen` variant.
7980        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7981        /// or because new variants of `CogFrozen` were added.
7982        pub fn cog_frozen(&self) -> Result<CogFrozen, u8> {
7983            get_bit_range!(self.flags, u16, u8, 9, 9).try_into()
7984        }
7985
7986        /// Set the bitrange corresponding to the [CogFrozen][CogFrozen] of the `flags` bitfield.
7987        pub fn set_cog_frozen(&mut self, cog_frozen: CogFrozen) {
7988            set_bit_range!(&mut self.flags, cog_frozen, u16, u8, 9, 9);
7989        }
7990
7991        /// Gets the [VerticalVelocityValidity][self::VerticalVelocityValidity] stored in the `flags` bitfield.
7992        ///
7993        /// Returns `Ok` if the bitrange contains a known `VerticalVelocityValidity` variant.
7994        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
7995        /// or because new variants of `VerticalVelocityValidity` were added.
7996        pub fn vertical_velocity_validity(&self) -> Result<VerticalVelocityValidity, u8> {
7997            get_bit_range!(self.flags, u16, u8, 8, 8).try_into()
7998        }
7999
8000        /// Set the bitrange corresponding to the [VerticalVelocityValidity][VerticalVelocityValidity] of the `flags` bitfield.
8001        pub fn set_vertical_velocity_validity(
8002            &mut self,
8003            vertical_velocity_validity: VerticalVelocityValidity,
8004        ) {
8005            set_bit_range!(&mut self.flags, vertical_velocity_validity, u16, u8, 8, 8);
8006        }
8007
8008        /// Gets the [SogValidity][self::SogValidity] stored in the `flags` bitfield.
8009        ///
8010        /// Returns `Ok` if the bitrange contains a known `SogValidity` variant.
8011        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8012        /// or because new variants of `SogValidity` were added.
8013        pub fn sog_validity(&self) -> Result<SogValidity, u8> {
8014            get_bit_range!(self.flags, u16, u8, 7, 7).try_into()
8015        }
8016
8017        /// Set the bitrange corresponding to the [SogValidity][SogValidity] of the `flags` bitfield.
8018        pub fn set_sog_validity(&mut self, sog_validity: SogValidity) {
8019            set_bit_range!(&mut self.flags, sog_validity, u16, u8, 7, 7);
8020        }
8021
8022        /// Gets the [CogValidity][self::CogValidity] stored in the `flags` bitfield.
8023        ///
8024        /// Returns `Ok` if the bitrange contains a known `CogValidity` variant.
8025        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8026        /// or because new variants of `CogValidity` were added.
8027        pub fn cog_validity(&self) -> Result<CogValidity, u8> {
8028            get_bit_range!(self.flags, u16, u8, 6, 6).try_into()
8029        }
8030
8031        /// Set the bitrange corresponding to the [CogValidity][CogValidity] of the `flags` bitfield.
8032        pub fn set_cog_validity(&mut self, cog_validity: CogValidity) {
8033            set_bit_range!(&mut self.flags, cog_validity, u16, u8, 6, 6);
8034        }
8035
8036        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
8037        ///
8038        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
8039        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8040        /// or because new variants of `TypeOfReportedTow` were added.
8041        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
8042            get_bit_range!(self.flags, u16, u8, 5, 5).try_into()
8043        }
8044
8045        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
8046        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
8047            set_bit_range!(&mut self.flags, type_of_reported_tow, u16, u8, 5, 5);
8048        }
8049
8050        /// Gets the [InsNavigationMode][self::InsNavigationMode] stored in the `flags` bitfield.
8051        ///
8052        /// Returns `Ok` if the bitrange contains a known `InsNavigationMode` variant.
8053        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8054        /// or because new variants of `InsNavigationMode` were added.
8055        pub fn ins_navigation_mode(&self) -> Result<InsNavigationMode, u8> {
8056            get_bit_range!(self.flags, u16, u8, 4, 3).try_into()
8057        }
8058
8059        /// Set the bitrange corresponding to the [InsNavigationMode][InsNavigationMode] of the `flags` bitfield.
8060        pub fn set_ins_navigation_mode(&mut self, ins_navigation_mode: InsNavigationMode) {
8061            set_bit_range!(&mut self.flags, ins_navigation_mode, u16, u8, 4, 3);
8062        }
8063
8064        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
8065        ///
8066        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
8067        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8068        /// or because new variants of `VelocityMode` were added.
8069        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
8070            get_bit_range!(self.flags, u16, u8, 2, 0).try_into()
8071        }
8072
8073        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
8074        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
8075            set_bit_range!(&mut self.flags, velocity_mode, u16, u8, 2, 0);
8076        }
8077    }
8078
8079    impl ConcreteMessage for MsgVelCog {
8080        const MESSAGE_TYPE: u16 = 540;
8081        const MESSAGE_NAME: &'static str = "MSG_VEL_COG";
8082    }
8083
8084    impl SbpMessage for MsgVelCog {
8085        fn message_name(&self) -> &'static str {
8086            <Self as ConcreteMessage>::MESSAGE_NAME
8087        }
8088        fn message_type(&self) -> Option<u16> {
8089            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
8090        }
8091        fn sender_id(&self) -> Option<u16> {
8092            self.sender_id
8093        }
8094        fn set_sender_id(&mut self, new_id: u16) {
8095            self.sender_id = Some(new_id);
8096        }
8097        fn encoded_len(&self) -> usize {
8098            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
8099        }
8100        fn is_valid(&self) -> bool {
8101            true
8102        }
8103        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
8104            Ok(self)
8105        }
8106
8107        #[cfg(feature = "swiftnav")]
8108        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
8109            let tow_s = (self.tow as f64) / 1000.0;
8110            let gps_time = match time::GpsTime::new(0, tow_s) {
8111                Ok(gps_time) => gps_time.tow(),
8112                Err(e) => return Some(Err(e.into())),
8113            };
8114            Some(Ok(time::MessageTime::Rover(gps_time.into())))
8115        }
8116    }
8117
8118    impl FriendlyName for MsgVelCog {
8119        fn friendly_name() -> &'static str {
8120            "VEL COG"
8121        }
8122    }
8123
8124    impl TryFrom<Sbp> for MsgVelCog {
8125        type Error = TryFromSbpError;
8126        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
8127            match msg {
8128                Sbp::MsgVelCog(m) => Ok(m),
8129                _ => Err(TryFromSbpError(msg)),
8130            }
8131        }
8132    }
8133
8134    impl WireFormat for MsgVelCog {
8135        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
8136            + <u32 as WireFormat>::MIN_LEN
8137            + <u32 as WireFormat>::MIN_LEN
8138            + <i32 as WireFormat>::MIN_LEN
8139            + <u32 as WireFormat>::MIN_LEN
8140            + <u32 as WireFormat>::MIN_LEN
8141            + <u32 as WireFormat>::MIN_LEN
8142            + <u16 as WireFormat>::MIN_LEN;
8143        fn len(&self) -> usize {
8144            WireFormat::len(&self.tow)
8145                + WireFormat::len(&self.cog)
8146                + WireFormat::len(&self.sog)
8147                + WireFormat::len(&self.v_up)
8148                + WireFormat::len(&self.cog_accuracy)
8149                + WireFormat::len(&self.sog_accuracy)
8150                + WireFormat::len(&self.v_up_accuracy)
8151                + WireFormat::len(&self.flags)
8152        }
8153        fn write<B: BufMut>(&self, buf: &mut B) {
8154            WireFormat::write(&self.tow, buf);
8155            WireFormat::write(&self.cog, buf);
8156            WireFormat::write(&self.sog, buf);
8157            WireFormat::write(&self.v_up, buf);
8158            WireFormat::write(&self.cog_accuracy, buf);
8159            WireFormat::write(&self.sog_accuracy, buf);
8160            WireFormat::write(&self.v_up_accuracy, buf);
8161            WireFormat::write(&self.flags, buf);
8162        }
8163        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
8164            MsgVelCog {
8165                sender_id: None,
8166                tow: WireFormat::parse_unchecked(buf),
8167                cog: WireFormat::parse_unchecked(buf),
8168                sog: WireFormat::parse_unchecked(buf),
8169                v_up: WireFormat::parse_unchecked(buf),
8170                cog_accuracy: WireFormat::parse_unchecked(buf),
8171                sog_accuracy: WireFormat::parse_unchecked(buf),
8172                v_up_accuracy: WireFormat::parse_unchecked(buf),
8173                flags: WireFormat::parse_unchecked(buf),
8174            }
8175        }
8176    }
8177
8178    /// COG frozen
8179    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8180    pub enum CogFrozen {
8181        /// Not frozen
8182        NotFrozen = 0,
8183
8184        /// Frozen
8185        Frozen = 1,
8186    }
8187
8188    impl std::fmt::Display for CogFrozen {
8189        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8190            match self {
8191                CogFrozen::NotFrozen => f.write_str("Not frozen"),
8192                CogFrozen::Frozen => f.write_str("Frozen"),
8193            }
8194        }
8195    }
8196
8197    impl TryFrom<u8> for CogFrozen {
8198        type Error = u8;
8199        fn try_from(i: u8) -> Result<Self, u8> {
8200            match i {
8201                0 => Ok(CogFrozen::NotFrozen),
8202                1 => Ok(CogFrozen::Frozen),
8203                i => Err(i),
8204            }
8205        }
8206    }
8207
8208    /// Vertical velocity validity
8209    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8210    pub enum VerticalVelocityValidity {
8211        /// Invalid
8212        Invalid = 0,
8213
8214        /// Vertical velocity valid
8215        VerticalVelocityValid = 1,
8216    }
8217
8218    impl std::fmt::Display for VerticalVelocityValidity {
8219        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8220            match self {
8221                VerticalVelocityValidity::Invalid => f.write_str("Invalid"),
8222                VerticalVelocityValidity::VerticalVelocityValid => {
8223                    f.write_str("Vertical velocity valid")
8224                }
8225            }
8226        }
8227    }
8228
8229    impl TryFrom<u8> for VerticalVelocityValidity {
8230        type Error = u8;
8231        fn try_from(i: u8) -> Result<Self, u8> {
8232            match i {
8233                0 => Ok(VerticalVelocityValidity::Invalid),
8234                1 => Ok(VerticalVelocityValidity::VerticalVelocityValid),
8235                i => Err(i),
8236            }
8237        }
8238    }
8239
8240    /// SOG validity
8241    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8242    pub enum SogValidity {
8243        /// Invalid
8244        Invalid = 0,
8245
8246        /// SOG valid
8247        SogValid = 1,
8248    }
8249
8250    impl std::fmt::Display for SogValidity {
8251        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8252            match self {
8253                SogValidity::Invalid => f.write_str("Invalid"),
8254                SogValidity::SogValid => f.write_str("SOG valid"),
8255            }
8256        }
8257    }
8258
8259    impl TryFrom<u8> for SogValidity {
8260        type Error = u8;
8261        fn try_from(i: u8) -> Result<Self, u8> {
8262            match i {
8263                0 => Ok(SogValidity::Invalid),
8264                1 => Ok(SogValidity::SogValid),
8265                i => Err(i),
8266            }
8267        }
8268    }
8269
8270    /// COG validity
8271    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8272    pub enum CogValidity {
8273        /// Invalid
8274        Invalid = 0,
8275
8276        /// COG valid
8277        CogValid = 1,
8278    }
8279
8280    impl std::fmt::Display for CogValidity {
8281        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8282            match self {
8283                CogValidity::Invalid => f.write_str("Invalid"),
8284                CogValidity::CogValid => f.write_str("COG valid"),
8285            }
8286        }
8287    }
8288
8289    impl TryFrom<u8> for CogValidity {
8290        type Error = u8;
8291        fn try_from(i: u8) -> Result<Self, u8> {
8292            match i {
8293                0 => Ok(CogValidity::Invalid),
8294                1 => Ok(CogValidity::CogValid),
8295                i => Err(i),
8296            }
8297        }
8298    }
8299
8300    /// Type of reported TOW
8301    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8302    pub enum TypeOfReportedTow {
8303        /// Time of Measurement
8304        TimeOfMeasurement = 0,
8305
8306        /// Other
8307        Other = 1,
8308    }
8309
8310    impl std::fmt::Display for TypeOfReportedTow {
8311        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8312            match self {
8313                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
8314                TypeOfReportedTow::Other => f.write_str("Other"),
8315            }
8316        }
8317    }
8318
8319    impl TryFrom<u8> for TypeOfReportedTow {
8320        type Error = u8;
8321        fn try_from(i: u8) -> Result<Self, u8> {
8322            match i {
8323                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
8324                1 => Ok(TypeOfReportedTow::Other),
8325                i => Err(i),
8326            }
8327        }
8328    }
8329
8330    /// INS Navigation Mode
8331    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8332    pub enum InsNavigationMode {
8333        /// None
8334        None = 0,
8335
8336        /// INS used
8337        InsUsed = 1,
8338    }
8339
8340    impl std::fmt::Display for InsNavigationMode {
8341        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8342            match self {
8343                InsNavigationMode::None => f.write_str("None"),
8344                InsNavigationMode::InsUsed => f.write_str("INS used"),
8345            }
8346        }
8347    }
8348
8349    impl TryFrom<u8> for InsNavigationMode {
8350        type Error = u8;
8351        fn try_from(i: u8) -> Result<Self, u8> {
8352            match i {
8353                0 => Ok(InsNavigationMode::None),
8354                1 => Ok(InsNavigationMode::InsUsed),
8355                i => Err(i),
8356            }
8357        }
8358    }
8359
8360    /// Velocity mode
8361    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8362    pub enum VelocityMode {
8363        /// Invalid
8364        Invalid = 0,
8365
8366        /// Measured Doppler derived
8367        MeasuredDopplerDerived = 1,
8368
8369        /// Computed Doppler derived
8370        ComputedDopplerDerived = 2,
8371
8372        /// Dead Reckoning
8373        DeadReckoning = 3,
8374    }
8375
8376    impl std::fmt::Display for VelocityMode {
8377        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8378            match self {
8379                VelocityMode::Invalid => f.write_str("Invalid"),
8380                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
8381                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
8382                VelocityMode::DeadReckoning => f.write_str("Dead Reckoning"),
8383            }
8384        }
8385    }
8386
8387    impl TryFrom<u8> for VelocityMode {
8388        type Error = u8;
8389        fn try_from(i: u8) -> Result<Self, u8> {
8390            match i {
8391                0 => Ok(VelocityMode::Invalid),
8392                1 => Ok(VelocityMode::MeasuredDopplerDerived),
8393                2 => Ok(VelocityMode::ComputedDopplerDerived),
8394                3 => Ok(VelocityMode::DeadReckoning),
8395                i => Err(i),
8396            }
8397        }
8398    }
8399}
8400
8401pub mod msg_vel_ecef {
8402    #![allow(unused_imports)]
8403
8404    use super::*;
8405    use crate::messages::lib::*;
8406
8407    /// Velocity in ECEF
8408    ///
8409    /// This message reports the velocity in Earth Centered Earth Fixed (ECEF)
8410    /// coordinates. The full GPS time is given by the preceding MSG_GPS_TIME with
8411    /// the matching time-of-week (tow).
8412    ///
8413    /// The values in this message are from GNSS measurements fused with inertial
8414    /// measurements. To get values from GNSS measurements only use
8415    /// MSG_VEL_ECEF_GNSS.
8416    ///
8417    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8418    #[allow(clippy::derive_partial_eq_without_eq)]
8419    #[derive(Debug, PartialEq, Clone)]
8420    pub struct MsgVelEcef {
8421        /// The message sender_id
8422        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
8423        pub sender_id: Option<u16>,
8424        /// GPS Time of Week
8425        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
8426        pub tow: u32,
8427        /// Velocity ECEF X coordinate
8428        #[cfg_attr(feature = "serde", serde(rename = "x"))]
8429        pub x: i32,
8430        /// Velocity ECEF Y coordinate
8431        #[cfg_attr(feature = "serde", serde(rename = "y"))]
8432        pub y: i32,
8433        /// Velocity ECEF Z coordinate
8434        #[cfg_attr(feature = "serde", serde(rename = "z"))]
8435        pub z: i32,
8436        /// Velocity estimated standard deviation
8437        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
8438        pub accuracy: u16,
8439        /// Number of satellites used in solution
8440        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
8441        pub n_sats: u8,
8442        /// Status flags
8443        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
8444        pub flags: u8,
8445    }
8446
8447    impl MsgVelEcef {
8448        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
8449        ///
8450        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
8451        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8452        /// or because new variants of `TypeOfReportedTow` were added.
8453        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
8454            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
8455        }
8456
8457        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
8458        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
8459            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
8460        }
8461
8462        /// Gets the [InsNavigationMode][self::InsNavigationMode] stored in the `flags` bitfield.
8463        ///
8464        /// Returns `Ok` if the bitrange contains a known `InsNavigationMode` variant.
8465        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8466        /// or because new variants of `InsNavigationMode` were added.
8467        pub fn ins_navigation_mode(&self) -> Result<InsNavigationMode, u8> {
8468            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
8469        }
8470
8471        /// Set the bitrange corresponding to the [InsNavigationMode][InsNavigationMode] of the `flags` bitfield.
8472        pub fn set_ins_navigation_mode(&mut self, ins_navigation_mode: InsNavigationMode) {
8473            set_bit_range!(&mut self.flags, ins_navigation_mode, u8, u8, 4, 3);
8474        }
8475
8476        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
8477        ///
8478        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
8479        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8480        /// or because new variants of `VelocityMode` were added.
8481        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
8482            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
8483        }
8484
8485        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
8486        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
8487            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
8488        }
8489    }
8490
8491    impl ConcreteMessage for MsgVelEcef {
8492        const MESSAGE_TYPE: u16 = 525;
8493        const MESSAGE_NAME: &'static str = "MSG_VEL_ECEF";
8494    }
8495
8496    impl SbpMessage for MsgVelEcef {
8497        fn message_name(&self) -> &'static str {
8498            <Self as ConcreteMessage>::MESSAGE_NAME
8499        }
8500        fn message_type(&self) -> Option<u16> {
8501            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
8502        }
8503        fn sender_id(&self) -> Option<u16> {
8504            self.sender_id
8505        }
8506        fn set_sender_id(&mut self, new_id: u16) {
8507            self.sender_id = Some(new_id);
8508        }
8509        fn encoded_len(&self) -> usize {
8510            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
8511        }
8512        fn is_valid(&self) -> bool {
8513            true
8514        }
8515        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
8516            Ok(self)
8517        }
8518
8519        #[cfg(feature = "swiftnav")]
8520        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
8521            let tow_s = (self.tow as f64) / 1000.0;
8522            let gps_time = match time::GpsTime::new(0, tow_s) {
8523                Ok(gps_time) => gps_time.tow(),
8524                Err(e) => return Some(Err(e.into())),
8525            };
8526            Some(Ok(time::MessageTime::Rover(gps_time.into())))
8527        }
8528    }
8529
8530    impl FriendlyName for MsgVelEcef {
8531        fn friendly_name() -> &'static str {
8532            "VEL ECEF"
8533        }
8534    }
8535
8536    impl TryFrom<Sbp> for MsgVelEcef {
8537        type Error = TryFromSbpError;
8538        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
8539            match msg {
8540                Sbp::MsgVelEcef(m) => Ok(m),
8541                _ => Err(TryFromSbpError(msg)),
8542            }
8543        }
8544    }
8545
8546    impl WireFormat for MsgVelEcef {
8547        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
8548            + <i32 as WireFormat>::MIN_LEN
8549            + <i32 as WireFormat>::MIN_LEN
8550            + <i32 as WireFormat>::MIN_LEN
8551            + <u16 as WireFormat>::MIN_LEN
8552            + <u8 as WireFormat>::MIN_LEN
8553            + <u8 as WireFormat>::MIN_LEN;
8554        fn len(&self) -> usize {
8555            WireFormat::len(&self.tow)
8556                + WireFormat::len(&self.x)
8557                + WireFormat::len(&self.y)
8558                + WireFormat::len(&self.z)
8559                + WireFormat::len(&self.accuracy)
8560                + WireFormat::len(&self.n_sats)
8561                + WireFormat::len(&self.flags)
8562        }
8563        fn write<B: BufMut>(&self, buf: &mut B) {
8564            WireFormat::write(&self.tow, buf);
8565            WireFormat::write(&self.x, buf);
8566            WireFormat::write(&self.y, buf);
8567            WireFormat::write(&self.z, buf);
8568            WireFormat::write(&self.accuracy, buf);
8569            WireFormat::write(&self.n_sats, buf);
8570            WireFormat::write(&self.flags, buf);
8571        }
8572        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
8573            MsgVelEcef {
8574                sender_id: None,
8575                tow: WireFormat::parse_unchecked(buf),
8576                x: WireFormat::parse_unchecked(buf),
8577                y: WireFormat::parse_unchecked(buf),
8578                z: WireFormat::parse_unchecked(buf),
8579                accuracy: WireFormat::parse_unchecked(buf),
8580                n_sats: WireFormat::parse_unchecked(buf),
8581                flags: WireFormat::parse_unchecked(buf),
8582            }
8583        }
8584    }
8585
8586    /// Type of reported TOW
8587    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8588    pub enum TypeOfReportedTow {
8589        /// Time of Measurement
8590        TimeOfMeasurement = 0,
8591
8592        /// Other
8593        Other = 1,
8594    }
8595
8596    impl std::fmt::Display for TypeOfReportedTow {
8597        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8598            match self {
8599                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
8600                TypeOfReportedTow::Other => f.write_str("Other"),
8601            }
8602        }
8603    }
8604
8605    impl TryFrom<u8> for TypeOfReportedTow {
8606        type Error = u8;
8607        fn try_from(i: u8) -> Result<Self, u8> {
8608            match i {
8609                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
8610                1 => Ok(TypeOfReportedTow::Other),
8611                i => Err(i),
8612            }
8613        }
8614    }
8615
8616    /// INS Navigation Mode
8617    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8618    pub enum InsNavigationMode {
8619        /// None
8620        None = 0,
8621
8622        /// INS used
8623        InsUsed = 1,
8624    }
8625
8626    impl std::fmt::Display for InsNavigationMode {
8627        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8628            match self {
8629                InsNavigationMode::None => f.write_str("None"),
8630                InsNavigationMode::InsUsed => f.write_str("INS used"),
8631            }
8632        }
8633    }
8634
8635    impl TryFrom<u8> for InsNavigationMode {
8636        type Error = u8;
8637        fn try_from(i: u8) -> Result<Self, u8> {
8638            match i {
8639                0 => Ok(InsNavigationMode::None),
8640                1 => Ok(InsNavigationMode::InsUsed),
8641                i => Err(i),
8642            }
8643        }
8644    }
8645
8646    /// Velocity mode
8647    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8648    pub enum VelocityMode {
8649        /// Invalid
8650        Invalid = 0,
8651
8652        /// Measured Doppler derived
8653        MeasuredDopplerDerived = 1,
8654
8655        /// Computed Doppler derived
8656        ComputedDopplerDerived = 2,
8657
8658        /// Dead Reckoning
8659        DeadReckoning = 3,
8660    }
8661
8662    impl std::fmt::Display for VelocityMode {
8663        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8664            match self {
8665                VelocityMode::Invalid => f.write_str("Invalid"),
8666                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
8667                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
8668                VelocityMode::DeadReckoning => f.write_str("Dead Reckoning"),
8669            }
8670        }
8671    }
8672
8673    impl TryFrom<u8> for VelocityMode {
8674        type Error = u8;
8675        fn try_from(i: u8) -> Result<Self, u8> {
8676            match i {
8677                0 => Ok(VelocityMode::Invalid),
8678                1 => Ok(VelocityMode::MeasuredDopplerDerived),
8679                2 => Ok(VelocityMode::ComputedDopplerDerived),
8680                3 => Ok(VelocityMode::DeadReckoning),
8681                i => Err(i),
8682            }
8683        }
8684    }
8685}
8686
8687pub mod msg_vel_ecef_cov {
8688    #![allow(unused_imports)]
8689
8690    use super::*;
8691    use crate::messages::lib::*;
8692
8693    /// Velocity in ECEF with Covariances
8694    ///
8695    /// This message reports the velocity in Earth Centered Earth Fixed (ECEF)
8696    /// coordinates. The full GPS time is given by the preceding MSG_GPS_TIME with
8697    /// the matching time-of-week (tow).
8698    ///
8699    /// The values in this message are from GNSS measurements fused with inertial
8700    /// measurements. To get values from GNSS measurements only use
8701    /// MSG_VEL_ECEF_COV_GNSS.
8702    ///
8703    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8704    #[allow(clippy::derive_partial_eq_without_eq)]
8705    #[derive(Debug, PartialEq, Clone)]
8706    pub struct MsgVelEcefCov {
8707        /// The message sender_id
8708        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
8709        pub sender_id: Option<u16>,
8710        /// GPS Time of Week
8711        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
8712        pub tow: u32,
8713        /// Velocity ECEF X coordinate
8714        #[cfg_attr(feature = "serde", serde(rename = "x"))]
8715        pub x: i32,
8716        /// Velocity ECEF Y coordinate
8717        #[cfg_attr(feature = "serde", serde(rename = "y"))]
8718        pub y: i32,
8719        /// Velocity ECEF Z coordinate
8720        #[cfg_attr(feature = "serde", serde(rename = "z"))]
8721        pub z: i32,
8722        /// Estimated variance of x
8723        #[cfg_attr(feature = "serde", serde(rename = "cov_x_x"))]
8724        pub cov_x_x: f32,
8725        /// Estimated covariance of x and y
8726        #[cfg_attr(feature = "serde", serde(rename = "cov_x_y"))]
8727        pub cov_x_y: f32,
8728        /// Estimated covariance of x and z
8729        #[cfg_attr(feature = "serde", serde(rename = "cov_x_z"))]
8730        pub cov_x_z: f32,
8731        /// Estimated variance of y
8732        #[cfg_attr(feature = "serde", serde(rename = "cov_y_y"))]
8733        pub cov_y_y: f32,
8734        /// Estimated covariance of y and z
8735        #[cfg_attr(feature = "serde", serde(rename = "cov_y_z"))]
8736        pub cov_y_z: f32,
8737        /// Estimated variance of z
8738        #[cfg_attr(feature = "serde", serde(rename = "cov_z_z"))]
8739        pub cov_z_z: f32,
8740        /// Number of satellites used in solution
8741        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
8742        pub n_sats: u8,
8743        /// Status flags
8744        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
8745        pub flags: u8,
8746    }
8747
8748    impl MsgVelEcefCov {
8749        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
8750        ///
8751        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
8752        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8753        /// or because new variants of `TypeOfReportedTow` were added.
8754        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
8755            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
8756        }
8757
8758        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
8759        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
8760            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
8761        }
8762
8763        /// Gets the [InsNavigationMode][self::InsNavigationMode] stored in the `flags` bitfield.
8764        ///
8765        /// Returns `Ok` if the bitrange contains a known `InsNavigationMode` variant.
8766        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8767        /// or because new variants of `InsNavigationMode` were added.
8768        pub fn ins_navigation_mode(&self) -> Result<InsNavigationMode, u8> {
8769            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
8770        }
8771
8772        /// Set the bitrange corresponding to the [InsNavigationMode][InsNavigationMode] of the `flags` bitfield.
8773        pub fn set_ins_navigation_mode(&mut self, ins_navigation_mode: InsNavigationMode) {
8774            set_bit_range!(&mut self.flags, ins_navigation_mode, u8, u8, 4, 3);
8775        }
8776
8777        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
8778        ///
8779        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
8780        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
8781        /// or because new variants of `VelocityMode` were added.
8782        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
8783            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
8784        }
8785
8786        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
8787        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
8788            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
8789        }
8790    }
8791
8792    impl ConcreteMessage for MsgVelEcefCov {
8793        const MESSAGE_TYPE: u16 = 533;
8794        const MESSAGE_NAME: &'static str = "MSG_VEL_ECEF_COV";
8795    }
8796
8797    impl SbpMessage for MsgVelEcefCov {
8798        fn message_name(&self) -> &'static str {
8799            <Self as ConcreteMessage>::MESSAGE_NAME
8800        }
8801        fn message_type(&self) -> Option<u16> {
8802            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
8803        }
8804        fn sender_id(&self) -> Option<u16> {
8805            self.sender_id
8806        }
8807        fn set_sender_id(&mut self, new_id: u16) {
8808            self.sender_id = Some(new_id);
8809        }
8810        fn encoded_len(&self) -> usize {
8811            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
8812        }
8813        fn is_valid(&self) -> bool {
8814            true
8815        }
8816        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
8817            Ok(self)
8818        }
8819
8820        #[cfg(feature = "swiftnav")]
8821        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
8822            let tow_s = (self.tow as f64) / 1000.0;
8823            let gps_time = match time::GpsTime::new(0, tow_s) {
8824                Ok(gps_time) => gps_time.tow(),
8825                Err(e) => return Some(Err(e.into())),
8826            };
8827            Some(Ok(time::MessageTime::Rover(gps_time.into())))
8828        }
8829    }
8830
8831    impl FriendlyName for MsgVelEcefCov {
8832        fn friendly_name() -> &'static str {
8833            "VEL ECEF COV"
8834        }
8835    }
8836
8837    impl TryFrom<Sbp> for MsgVelEcefCov {
8838        type Error = TryFromSbpError;
8839        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
8840            match msg {
8841                Sbp::MsgVelEcefCov(m) => Ok(m),
8842                _ => Err(TryFromSbpError(msg)),
8843            }
8844        }
8845    }
8846
8847    impl WireFormat for MsgVelEcefCov {
8848        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
8849            + <i32 as WireFormat>::MIN_LEN
8850            + <i32 as WireFormat>::MIN_LEN
8851            + <i32 as WireFormat>::MIN_LEN
8852            + <f32 as WireFormat>::MIN_LEN
8853            + <f32 as WireFormat>::MIN_LEN
8854            + <f32 as WireFormat>::MIN_LEN
8855            + <f32 as WireFormat>::MIN_LEN
8856            + <f32 as WireFormat>::MIN_LEN
8857            + <f32 as WireFormat>::MIN_LEN
8858            + <u8 as WireFormat>::MIN_LEN
8859            + <u8 as WireFormat>::MIN_LEN;
8860        fn len(&self) -> usize {
8861            WireFormat::len(&self.tow)
8862                + WireFormat::len(&self.x)
8863                + WireFormat::len(&self.y)
8864                + WireFormat::len(&self.z)
8865                + WireFormat::len(&self.cov_x_x)
8866                + WireFormat::len(&self.cov_x_y)
8867                + WireFormat::len(&self.cov_x_z)
8868                + WireFormat::len(&self.cov_y_y)
8869                + WireFormat::len(&self.cov_y_z)
8870                + WireFormat::len(&self.cov_z_z)
8871                + WireFormat::len(&self.n_sats)
8872                + WireFormat::len(&self.flags)
8873        }
8874        fn write<B: BufMut>(&self, buf: &mut B) {
8875            WireFormat::write(&self.tow, buf);
8876            WireFormat::write(&self.x, buf);
8877            WireFormat::write(&self.y, buf);
8878            WireFormat::write(&self.z, buf);
8879            WireFormat::write(&self.cov_x_x, buf);
8880            WireFormat::write(&self.cov_x_y, buf);
8881            WireFormat::write(&self.cov_x_z, buf);
8882            WireFormat::write(&self.cov_y_y, buf);
8883            WireFormat::write(&self.cov_y_z, buf);
8884            WireFormat::write(&self.cov_z_z, buf);
8885            WireFormat::write(&self.n_sats, buf);
8886            WireFormat::write(&self.flags, buf);
8887        }
8888        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
8889            MsgVelEcefCov {
8890                sender_id: None,
8891                tow: WireFormat::parse_unchecked(buf),
8892                x: WireFormat::parse_unchecked(buf),
8893                y: WireFormat::parse_unchecked(buf),
8894                z: WireFormat::parse_unchecked(buf),
8895                cov_x_x: WireFormat::parse_unchecked(buf),
8896                cov_x_y: WireFormat::parse_unchecked(buf),
8897                cov_x_z: WireFormat::parse_unchecked(buf),
8898                cov_y_y: WireFormat::parse_unchecked(buf),
8899                cov_y_z: WireFormat::parse_unchecked(buf),
8900                cov_z_z: WireFormat::parse_unchecked(buf),
8901                n_sats: WireFormat::parse_unchecked(buf),
8902                flags: WireFormat::parse_unchecked(buf),
8903            }
8904        }
8905    }
8906
8907    /// Type of reported TOW
8908    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8909    pub enum TypeOfReportedTow {
8910        /// Time of Measurement
8911        TimeOfMeasurement = 0,
8912
8913        /// Other
8914        Other = 1,
8915    }
8916
8917    impl std::fmt::Display for TypeOfReportedTow {
8918        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8919            match self {
8920                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
8921                TypeOfReportedTow::Other => f.write_str("Other"),
8922            }
8923        }
8924    }
8925
8926    impl TryFrom<u8> for TypeOfReportedTow {
8927        type Error = u8;
8928        fn try_from(i: u8) -> Result<Self, u8> {
8929            match i {
8930                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
8931                1 => Ok(TypeOfReportedTow::Other),
8932                i => Err(i),
8933            }
8934        }
8935    }
8936
8937    /// INS Navigation Mode
8938    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8939    pub enum InsNavigationMode {
8940        /// None
8941        None = 0,
8942
8943        /// INS used
8944        InsUsed = 1,
8945    }
8946
8947    impl std::fmt::Display for InsNavigationMode {
8948        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8949            match self {
8950                InsNavigationMode::None => f.write_str("None"),
8951                InsNavigationMode::InsUsed => f.write_str("INS used"),
8952            }
8953        }
8954    }
8955
8956    impl TryFrom<u8> for InsNavigationMode {
8957        type Error = u8;
8958        fn try_from(i: u8) -> Result<Self, u8> {
8959            match i {
8960                0 => Ok(InsNavigationMode::None),
8961                1 => Ok(InsNavigationMode::InsUsed),
8962                i => Err(i),
8963            }
8964        }
8965    }
8966
8967    /// Velocity mode
8968    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8969    pub enum VelocityMode {
8970        /// Invalid
8971        Invalid = 0,
8972
8973        /// Measured Doppler derived
8974        MeasuredDopplerDerived = 1,
8975
8976        /// Computed Doppler derived
8977        ComputedDopplerDerived = 2,
8978
8979        /// Dead Reckoning
8980        DeadReckoning = 3,
8981    }
8982
8983    impl std::fmt::Display for VelocityMode {
8984        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8985            match self {
8986                VelocityMode::Invalid => f.write_str("Invalid"),
8987                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
8988                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
8989                VelocityMode::DeadReckoning => f.write_str("Dead Reckoning"),
8990            }
8991        }
8992    }
8993
8994    impl TryFrom<u8> for VelocityMode {
8995        type Error = u8;
8996        fn try_from(i: u8) -> Result<Self, u8> {
8997            match i {
8998                0 => Ok(VelocityMode::Invalid),
8999                1 => Ok(VelocityMode::MeasuredDopplerDerived),
9000                2 => Ok(VelocityMode::ComputedDopplerDerived),
9001                3 => Ok(VelocityMode::DeadReckoning),
9002                i => Err(i),
9003            }
9004        }
9005    }
9006}
9007
9008pub mod msg_vel_ecef_cov_gnss {
9009    #![allow(unused_imports)]
9010
9011    use super::*;
9012    use crate::messages::lib::*;
9013
9014    /// GNSS-only Velocity in ECEF with Covariances
9015    ///
9016    /// This message reports the velocity in Earth Centered Earth Fixed (ECEF)
9017    /// coordinates. The full GPS time is given by the preceding MSG_GPS_TIME_GNSS
9018    /// with the matching time-of-week (tow).
9019    ///
9020    /// The values in this message are from GNSS measurements only. To get values
9021    /// fused with inertial measurements use MSG_VEL_ECEF_COV.
9022    ///
9023    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9024    #[allow(clippy::derive_partial_eq_without_eq)]
9025    #[derive(Debug, PartialEq, Clone)]
9026    pub struct MsgVelEcefCovGnss {
9027        /// The message sender_id
9028        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
9029        pub sender_id: Option<u16>,
9030        /// GPS Time of Week
9031        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
9032        pub tow: u32,
9033        /// Velocity ECEF X coordinate
9034        #[cfg_attr(feature = "serde", serde(rename = "x"))]
9035        pub x: i32,
9036        /// Velocity ECEF Y coordinate
9037        #[cfg_attr(feature = "serde", serde(rename = "y"))]
9038        pub y: i32,
9039        /// Velocity ECEF Z coordinate
9040        #[cfg_attr(feature = "serde", serde(rename = "z"))]
9041        pub z: i32,
9042        /// Estimated variance of x
9043        #[cfg_attr(feature = "serde", serde(rename = "cov_x_x"))]
9044        pub cov_x_x: f32,
9045        /// Estimated covariance of x and y
9046        #[cfg_attr(feature = "serde", serde(rename = "cov_x_y"))]
9047        pub cov_x_y: f32,
9048        /// Estimated covariance of x and z
9049        #[cfg_attr(feature = "serde", serde(rename = "cov_x_z"))]
9050        pub cov_x_z: f32,
9051        /// Estimated variance of y
9052        #[cfg_attr(feature = "serde", serde(rename = "cov_y_y"))]
9053        pub cov_y_y: f32,
9054        /// Estimated covariance of y and z
9055        #[cfg_attr(feature = "serde", serde(rename = "cov_y_z"))]
9056        pub cov_y_z: f32,
9057        /// Estimated variance of z
9058        #[cfg_attr(feature = "serde", serde(rename = "cov_z_z"))]
9059        pub cov_z_z: f32,
9060        /// Number of satellites used in solution
9061        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
9062        pub n_sats: u8,
9063        /// Status flags
9064        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
9065        pub flags: u8,
9066    }
9067
9068    impl MsgVelEcefCovGnss {
9069        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
9070        ///
9071        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
9072        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9073        /// or because new variants of `VelocityMode` were added.
9074        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
9075            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
9076        }
9077
9078        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
9079        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
9080            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
9081        }
9082    }
9083
9084    impl ConcreteMessage for MsgVelEcefCovGnss {
9085        const MESSAGE_TYPE: u16 = 565;
9086        const MESSAGE_NAME: &'static str = "MSG_VEL_ECEF_COV_GNSS";
9087    }
9088
9089    impl SbpMessage for MsgVelEcefCovGnss {
9090        fn message_name(&self) -> &'static str {
9091            <Self as ConcreteMessage>::MESSAGE_NAME
9092        }
9093        fn message_type(&self) -> Option<u16> {
9094            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
9095        }
9096        fn sender_id(&self) -> Option<u16> {
9097            self.sender_id
9098        }
9099        fn set_sender_id(&mut self, new_id: u16) {
9100            self.sender_id = Some(new_id);
9101        }
9102        fn encoded_len(&self) -> usize {
9103            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
9104        }
9105        fn is_valid(&self) -> bool {
9106            true
9107        }
9108        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
9109            Ok(self)
9110        }
9111
9112        #[cfg(feature = "swiftnav")]
9113        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
9114            let tow_s = (self.tow as f64) / 1000.0;
9115            let gps_time = match time::GpsTime::new(0, tow_s) {
9116                Ok(gps_time) => gps_time.tow(),
9117                Err(e) => return Some(Err(e.into())),
9118            };
9119            Some(Ok(time::MessageTime::Rover(gps_time.into())))
9120        }
9121    }
9122
9123    impl FriendlyName for MsgVelEcefCovGnss {
9124        fn friendly_name() -> &'static str {
9125            "VEL ECEF COV GNSS-only"
9126        }
9127    }
9128
9129    impl TryFrom<Sbp> for MsgVelEcefCovGnss {
9130        type Error = TryFromSbpError;
9131        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
9132            match msg {
9133                Sbp::MsgVelEcefCovGnss(m) => Ok(m),
9134                _ => Err(TryFromSbpError(msg)),
9135            }
9136        }
9137    }
9138
9139    impl WireFormat for MsgVelEcefCovGnss {
9140        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
9141            + <i32 as WireFormat>::MIN_LEN
9142            + <i32 as WireFormat>::MIN_LEN
9143            + <i32 as WireFormat>::MIN_LEN
9144            + <f32 as WireFormat>::MIN_LEN
9145            + <f32 as WireFormat>::MIN_LEN
9146            + <f32 as WireFormat>::MIN_LEN
9147            + <f32 as WireFormat>::MIN_LEN
9148            + <f32 as WireFormat>::MIN_LEN
9149            + <f32 as WireFormat>::MIN_LEN
9150            + <u8 as WireFormat>::MIN_LEN
9151            + <u8 as WireFormat>::MIN_LEN;
9152        fn len(&self) -> usize {
9153            WireFormat::len(&self.tow)
9154                + WireFormat::len(&self.x)
9155                + WireFormat::len(&self.y)
9156                + WireFormat::len(&self.z)
9157                + WireFormat::len(&self.cov_x_x)
9158                + WireFormat::len(&self.cov_x_y)
9159                + WireFormat::len(&self.cov_x_z)
9160                + WireFormat::len(&self.cov_y_y)
9161                + WireFormat::len(&self.cov_y_z)
9162                + WireFormat::len(&self.cov_z_z)
9163                + WireFormat::len(&self.n_sats)
9164                + WireFormat::len(&self.flags)
9165        }
9166        fn write<B: BufMut>(&self, buf: &mut B) {
9167            WireFormat::write(&self.tow, buf);
9168            WireFormat::write(&self.x, buf);
9169            WireFormat::write(&self.y, buf);
9170            WireFormat::write(&self.z, buf);
9171            WireFormat::write(&self.cov_x_x, buf);
9172            WireFormat::write(&self.cov_x_y, buf);
9173            WireFormat::write(&self.cov_x_z, buf);
9174            WireFormat::write(&self.cov_y_y, buf);
9175            WireFormat::write(&self.cov_y_z, buf);
9176            WireFormat::write(&self.cov_z_z, buf);
9177            WireFormat::write(&self.n_sats, buf);
9178            WireFormat::write(&self.flags, buf);
9179        }
9180        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
9181            MsgVelEcefCovGnss {
9182                sender_id: None,
9183                tow: WireFormat::parse_unchecked(buf),
9184                x: WireFormat::parse_unchecked(buf),
9185                y: WireFormat::parse_unchecked(buf),
9186                z: WireFormat::parse_unchecked(buf),
9187                cov_x_x: WireFormat::parse_unchecked(buf),
9188                cov_x_y: WireFormat::parse_unchecked(buf),
9189                cov_x_z: WireFormat::parse_unchecked(buf),
9190                cov_y_y: WireFormat::parse_unchecked(buf),
9191                cov_y_z: WireFormat::parse_unchecked(buf),
9192                cov_z_z: WireFormat::parse_unchecked(buf),
9193                n_sats: WireFormat::parse_unchecked(buf),
9194                flags: WireFormat::parse_unchecked(buf),
9195            }
9196        }
9197    }
9198
9199    /// Velocity mode
9200    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9201    pub enum VelocityMode {
9202        /// Invalid
9203        Invalid = 0,
9204
9205        /// Measured Doppler derived
9206        MeasuredDopplerDerived = 1,
9207
9208        /// Computed Doppler derived
9209        ComputedDopplerDerived = 2,
9210    }
9211
9212    impl std::fmt::Display for VelocityMode {
9213        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9214            match self {
9215                VelocityMode::Invalid => f.write_str("Invalid"),
9216                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
9217                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
9218            }
9219        }
9220    }
9221
9222    impl TryFrom<u8> for VelocityMode {
9223        type Error = u8;
9224        fn try_from(i: u8) -> Result<Self, u8> {
9225            match i {
9226                0 => Ok(VelocityMode::Invalid),
9227                1 => Ok(VelocityMode::MeasuredDopplerDerived),
9228                2 => Ok(VelocityMode::ComputedDopplerDerived),
9229                i => Err(i),
9230            }
9231        }
9232    }
9233}
9234
9235pub mod msg_vel_ecef_dep_a {
9236    #![allow(unused_imports)]
9237
9238    use super::*;
9239    use crate::messages::lib::*;
9240
9241    /// Deprecated
9242    ///
9243    /// Deprecated.
9244    ///
9245    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9246    #[allow(clippy::derive_partial_eq_without_eq)]
9247    #[derive(Debug, PartialEq, Clone)]
9248    pub struct MsgVelEcefDepA {
9249        /// The message sender_id
9250        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
9251        pub sender_id: Option<u16>,
9252        /// GPS Time of Week
9253        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
9254        pub tow: u32,
9255        /// Velocity ECEF X coordinate
9256        #[cfg_attr(feature = "serde", serde(rename = "x"))]
9257        pub x: i32,
9258        /// Velocity ECEF Y coordinate
9259        #[cfg_attr(feature = "serde", serde(rename = "y"))]
9260        pub y: i32,
9261        /// Velocity ECEF Z coordinate
9262        #[cfg_attr(feature = "serde", serde(rename = "z"))]
9263        pub z: i32,
9264        /// Velocity accuracy estimate (not implemented). Defaults to 0.
9265        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
9266        pub accuracy: u16,
9267        /// Number of satellites used in solution
9268        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
9269        pub n_sats: u8,
9270        /// Status flags (reserved)
9271        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
9272        pub flags: u8,
9273    }
9274
9275    impl ConcreteMessage for MsgVelEcefDepA {
9276        const MESSAGE_TYPE: u16 = 516;
9277        const MESSAGE_NAME: &'static str = "MSG_VEL_ECEF_DEP_A";
9278    }
9279
9280    impl SbpMessage for MsgVelEcefDepA {
9281        fn message_name(&self) -> &'static str {
9282            <Self as ConcreteMessage>::MESSAGE_NAME
9283        }
9284        fn message_type(&self) -> Option<u16> {
9285            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
9286        }
9287        fn sender_id(&self) -> Option<u16> {
9288            self.sender_id
9289        }
9290        fn set_sender_id(&mut self, new_id: u16) {
9291            self.sender_id = Some(new_id);
9292        }
9293        fn encoded_len(&self) -> usize {
9294            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
9295        }
9296        fn is_valid(&self) -> bool {
9297            true
9298        }
9299        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
9300            Ok(self)
9301        }
9302
9303        #[cfg(feature = "swiftnav")]
9304        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
9305            let tow_s = (self.tow as f64) / 1000.0;
9306            let gps_time = match time::GpsTime::new(0, tow_s) {
9307                Ok(gps_time) => gps_time.tow(),
9308                Err(e) => return Some(Err(e.into())),
9309            };
9310            Some(Ok(time::MessageTime::Rover(gps_time.into())))
9311        }
9312    }
9313
9314    impl FriendlyName for MsgVelEcefDepA {
9315        fn friendly_name() -> &'static str {
9316            "VEL ECEF DEP A"
9317        }
9318    }
9319
9320    impl TryFrom<Sbp> for MsgVelEcefDepA {
9321        type Error = TryFromSbpError;
9322        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
9323            match msg {
9324                Sbp::MsgVelEcefDepA(m) => Ok(m),
9325                _ => Err(TryFromSbpError(msg)),
9326            }
9327        }
9328    }
9329
9330    impl WireFormat for MsgVelEcefDepA {
9331        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
9332            + <i32 as WireFormat>::MIN_LEN
9333            + <i32 as WireFormat>::MIN_LEN
9334            + <i32 as WireFormat>::MIN_LEN
9335            + <u16 as WireFormat>::MIN_LEN
9336            + <u8 as WireFormat>::MIN_LEN
9337            + <u8 as WireFormat>::MIN_LEN;
9338        fn len(&self) -> usize {
9339            WireFormat::len(&self.tow)
9340                + WireFormat::len(&self.x)
9341                + WireFormat::len(&self.y)
9342                + WireFormat::len(&self.z)
9343                + WireFormat::len(&self.accuracy)
9344                + WireFormat::len(&self.n_sats)
9345                + WireFormat::len(&self.flags)
9346        }
9347        fn write<B: BufMut>(&self, buf: &mut B) {
9348            WireFormat::write(&self.tow, buf);
9349            WireFormat::write(&self.x, buf);
9350            WireFormat::write(&self.y, buf);
9351            WireFormat::write(&self.z, buf);
9352            WireFormat::write(&self.accuracy, buf);
9353            WireFormat::write(&self.n_sats, buf);
9354            WireFormat::write(&self.flags, buf);
9355        }
9356        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
9357            MsgVelEcefDepA {
9358                sender_id: None,
9359                tow: WireFormat::parse_unchecked(buf),
9360                x: WireFormat::parse_unchecked(buf),
9361                y: WireFormat::parse_unchecked(buf),
9362                z: WireFormat::parse_unchecked(buf),
9363                accuracy: WireFormat::parse_unchecked(buf),
9364                n_sats: WireFormat::parse_unchecked(buf),
9365                flags: WireFormat::parse_unchecked(buf),
9366            }
9367        }
9368    }
9369}
9370
9371pub mod msg_vel_ecef_gnss {
9372    #![allow(unused_imports)]
9373
9374    use super::*;
9375    use crate::messages::lib::*;
9376
9377    /// GNSS-only Velocity in ECEF
9378    ///
9379    /// This message reports the velocity in Earth Centered Earth Fixed (ECEF)
9380    /// coordinates. The full GPS time is given by the preceding MSG_GPS_TIME_GNSS
9381    /// with the matching time-of-week (tow).
9382    ///
9383    /// The values in this message are from GNSS measurements only. To get values
9384    /// fused with inertial measurements use MSG_VEL_ECEF.
9385    ///
9386    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9387    #[allow(clippy::derive_partial_eq_without_eq)]
9388    #[derive(Debug, PartialEq, Clone)]
9389    pub struct MsgVelEcefGnss {
9390        /// The message sender_id
9391        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
9392        pub sender_id: Option<u16>,
9393        /// GPS Time of Week
9394        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
9395        pub tow: u32,
9396        /// Velocity ECEF X coordinate
9397        #[cfg_attr(feature = "serde", serde(rename = "x"))]
9398        pub x: i32,
9399        /// Velocity ECEF Y coordinate
9400        #[cfg_attr(feature = "serde", serde(rename = "y"))]
9401        pub y: i32,
9402        /// Velocity ECEF Z coordinate
9403        #[cfg_attr(feature = "serde", serde(rename = "z"))]
9404        pub z: i32,
9405        /// Velocity estimated standard deviation
9406        #[cfg_attr(feature = "serde", serde(rename = "accuracy"))]
9407        pub accuracy: u16,
9408        /// Number of satellites used in solution
9409        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
9410        pub n_sats: u8,
9411        /// Status flags
9412        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
9413        pub flags: u8,
9414    }
9415
9416    impl MsgVelEcefGnss {
9417        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
9418        ///
9419        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
9420        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9421        /// or because new variants of `VelocityMode` were added.
9422        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
9423            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
9424        }
9425
9426        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
9427        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
9428            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
9429        }
9430    }
9431
9432    impl ConcreteMessage for MsgVelEcefGnss {
9433        const MESSAGE_TYPE: u16 = 557;
9434        const MESSAGE_NAME: &'static str = "MSG_VEL_ECEF_GNSS";
9435    }
9436
9437    impl SbpMessage for MsgVelEcefGnss {
9438        fn message_name(&self) -> &'static str {
9439            <Self as ConcreteMessage>::MESSAGE_NAME
9440        }
9441        fn message_type(&self) -> Option<u16> {
9442            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
9443        }
9444        fn sender_id(&self) -> Option<u16> {
9445            self.sender_id
9446        }
9447        fn set_sender_id(&mut self, new_id: u16) {
9448            self.sender_id = Some(new_id);
9449        }
9450        fn encoded_len(&self) -> usize {
9451            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
9452        }
9453        fn is_valid(&self) -> bool {
9454            true
9455        }
9456        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
9457            Ok(self)
9458        }
9459
9460        #[cfg(feature = "swiftnav")]
9461        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
9462            let tow_s = (self.tow as f64) / 1000.0;
9463            let gps_time = match time::GpsTime::new(0, tow_s) {
9464                Ok(gps_time) => gps_time.tow(),
9465                Err(e) => return Some(Err(e.into())),
9466            };
9467            Some(Ok(time::MessageTime::Rover(gps_time.into())))
9468        }
9469    }
9470
9471    impl FriendlyName for MsgVelEcefGnss {
9472        fn friendly_name() -> &'static str {
9473            "VEL ECEF GNSS-only"
9474        }
9475    }
9476
9477    impl TryFrom<Sbp> for MsgVelEcefGnss {
9478        type Error = TryFromSbpError;
9479        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
9480            match msg {
9481                Sbp::MsgVelEcefGnss(m) => Ok(m),
9482                _ => Err(TryFromSbpError(msg)),
9483            }
9484        }
9485    }
9486
9487    impl WireFormat for MsgVelEcefGnss {
9488        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
9489            + <i32 as WireFormat>::MIN_LEN
9490            + <i32 as WireFormat>::MIN_LEN
9491            + <i32 as WireFormat>::MIN_LEN
9492            + <u16 as WireFormat>::MIN_LEN
9493            + <u8 as WireFormat>::MIN_LEN
9494            + <u8 as WireFormat>::MIN_LEN;
9495        fn len(&self) -> usize {
9496            WireFormat::len(&self.tow)
9497                + WireFormat::len(&self.x)
9498                + WireFormat::len(&self.y)
9499                + WireFormat::len(&self.z)
9500                + WireFormat::len(&self.accuracy)
9501                + WireFormat::len(&self.n_sats)
9502                + WireFormat::len(&self.flags)
9503        }
9504        fn write<B: BufMut>(&self, buf: &mut B) {
9505            WireFormat::write(&self.tow, buf);
9506            WireFormat::write(&self.x, buf);
9507            WireFormat::write(&self.y, buf);
9508            WireFormat::write(&self.z, buf);
9509            WireFormat::write(&self.accuracy, buf);
9510            WireFormat::write(&self.n_sats, buf);
9511            WireFormat::write(&self.flags, buf);
9512        }
9513        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
9514            MsgVelEcefGnss {
9515                sender_id: None,
9516                tow: WireFormat::parse_unchecked(buf),
9517                x: WireFormat::parse_unchecked(buf),
9518                y: WireFormat::parse_unchecked(buf),
9519                z: WireFormat::parse_unchecked(buf),
9520                accuracy: WireFormat::parse_unchecked(buf),
9521                n_sats: WireFormat::parse_unchecked(buf),
9522                flags: WireFormat::parse_unchecked(buf),
9523            }
9524        }
9525    }
9526
9527    /// Velocity mode
9528    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9529    pub enum VelocityMode {
9530        /// Invalid
9531        Invalid = 0,
9532
9533        /// Measured Doppler derived
9534        MeasuredDopplerDerived = 1,
9535
9536        /// Computed Doppler derived
9537        ComputedDopplerDerived = 2,
9538    }
9539
9540    impl std::fmt::Display for VelocityMode {
9541        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9542            match self {
9543                VelocityMode::Invalid => f.write_str("Invalid"),
9544                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
9545                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
9546            }
9547        }
9548    }
9549
9550    impl TryFrom<u8> for VelocityMode {
9551        type Error = u8;
9552        fn try_from(i: u8) -> Result<Self, u8> {
9553            match i {
9554                0 => Ok(VelocityMode::Invalid),
9555                1 => Ok(VelocityMode::MeasuredDopplerDerived),
9556                2 => Ok(VelocityMode::ComputedDopplerDerived),
9557                i => Err(i),
9558            }
9559        }
9560    }
9561}
9562
9563pub mod msg_vel_ned {
9564    #![allow(unused_imports)]
9565
9566    use super::*;
9567    use crate::messages::lib::*;
9568
9569    /// Velocity in NED
9570    ///
9571    /// This message reports the velocity in local North East Down (NED)
9572    /// coordinates. The NED coordinate system is defined as the local WGS84
9573    /// tangent plane centered at the current position. The full GPS time is given
9574    /// by the preceding MSG_GPS_TIME with the matching time-of-week (tow).
9575    ///
9576    /// The values in this message are from GNSS measurements fused with inertial
9577    /// measurements. To get values from GNSS measurements only use
9578    /// MSG_VEL_NED_GNSS.
9579    ///
9580    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9581    #[allow(clippy::derive_partial_eq_without_eq)]
9582    #[derive(Debug, PartialEq, Clone)]
9583    pub struct MsgVelNed {
9584        /// The message sender_id
9585        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
9586        pub sender_id: Option<u16>,
9587        /// GPS Time of Week
9588        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
9589        pub tow: u32,
9590        /// Velocity North coordinate
9591        #[cfg_attr(feature = "serde", serde(rename = "n"))]
9592        pub n: i32,
9593        /// Velocity East coordinate
9594        #[cfg_attr(feature = "serde", serde(rename = "e"))]
9595        pub e: i32,
9596        /// Velocity Down coordinate
9597        #[cfg_attr(feature = "serde", serde(rename = "d"))]
9598        pub d: i32,
9599        /// Horizontal velocity estimated standard deviation
9600        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
9601        pub h_accuracy: u16,
9602        /// Vertical velocity estimated standard deviation
9603        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
9604        pub v_accuracy: u16,
9605        /// Number of satellites used in solution
9606        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
9607        pub n_sats: u8,
9608        /// Status flags
9609        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
9610        pub flags: u8,
9611    }
9612
9613    impl MsgVelNed {
9614        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
9615        ///
9616        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
9617        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9618        /// or because new variants of `TypeOfReportedTow` were added.
9619        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
9620            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
9621        }
9622
9623        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
9624        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
9625            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
9626        }
9627
9628        /// Gets the [InsNavigationMode][self::InsNavigationMode] stored in the `flags` bitfield.
9629        ///
9630        /// Returns `Ok` if the bitrange contains a known `InsNavigationMode` variant.
9631        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9632        /// or because new variants of `InsNavigationMode` were added.
9633        pub fn ins_navigation_mode(&self) -> Result<InsNavigationMode, u8> {
9634            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
9635        }
9636
9637        /// Set the bitrange corresponding to the [InsNavigationMode][InsNavigationMode] of the `flags` bitfield.
9638        pub fn set_ins_navigation_mode(&mut self, ins_navigation_mode: InsNavigationMode) {
9639            set_bit_range!(&mut self.flags, ins_navigation_mode, u8, u8, 4, 3);
9640        }
9641
9642        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
9643        ///
9644        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
9645        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9646        /// or because new variants of `VelocityMode` were added.
9647        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
9648            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
9649        }
9650
9651        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
9652        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
9653            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
9654        }
9655    }
9656
9657    impl ConcreteMessage for MsgVelNed {
9658        const MESSAGE_TYPE: u16 = 526;
9659        const MESSAGE_NAME: &'static str = "MSG_VEL_NED";
9660    }
9661
9662    impl SbpMessage for MsgVelNed {
9663        fn message_name(&self) -> &'static str {
9664            <Self as ConcreteMessage>::MESSAGE_NAME
9665        }
9666        fn message_type(&self) -> Option<u16> {
9667            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
9668        }
9669        fn sender_id(&self) -> Option<u16> {
9670            self.sender_id
9671        }
9672        fn set_sender_id(&mut self, new_id: u16) {
9673            self.sender_id = Some(new_id);
9674        }
9675        fn encoded_len(&self) -> usize {
9676            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
9677        }
9678        fn is_valid(&self) -> bool {
9679            true
9680        }
9681        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
9682            Ok(self)
9683        }
9684
9685        #[cfg(feature = "swiftnav")]
9686        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
9687            let tow_s = (self.tow as f64) / 1000.0;
9688            let gps_time = match time::GpsTime::new(0, tow_s) {
9689                Ok(gps_time) => gps_time.tow(),
9690                Err(e) => return Some(Err(e.into())),
9691            };
9692            Some(Ok(time::MessageTime::Rover(gps_time.into())))
9693        }
9694    }
9695
9696    impl FriendlyName for MsgVelNed {
9697        fn friendly_name() -> &'static str {
9698            "VEL NED"
9699        }
9700    }
9701
9702    impl TryFrom<Sbp> for MsgVelNed {
9703        type Error = TryFromSbpError;
9704        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
9705            match msg {
9706                Sbp::MsgVelNed(m) => Ok(m),
9707                _ => Err(TryFromSbpError(msg)),
9708            }
9709        }
9710    }
9711
9712    impl WireFormat for MsgVelNed {
9713        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
9714            + <i32 as WireFormat>::MIN_LEN
9715            + <i32 as WireFormat>::MIN_LEN
9716            + <i32 as WireFormat>::MIN_LEN
9717            + <u16 as WireFormat>::MIN_LEN
9718            + <u16 as WireFormat>::MIN_LEN
9719            + <u8 as WireFormat>::MIN_LEN
9720            + <u8 as WireFormat>::MIN_LEN;
9721        fn len(&self) -> usize {
9722            WireFormat::len(&self.tow)
9723                + WireFormat::len(&self.n)
9724                + WireFormat::len(&self.e)
9725                + WireFormat::len(&self.d)
9726                + WireFormat::len(&self.h_accuracy)
9727                + WireFormat::len(&self.v_accuracy)
9728                + WireFormat::len(&self.n_sats)
9729                + WireFormat::len(&self.flags)
9730        }
9731        fn write<B: BufMut>(&self, buf: &mut B) {
9732            WireFormat::write(&self.tow, buf);
9733            WireFormat::write(&self.n, buf);
9734            WireFormat::write(&self.e, buf);
9735            WireFormat::write(&self.d, buf);
9736            WireFormat::write(&self.h_accuracy, buf);
9737            WireFormat::write(&self.v_accuracy, buf);
9738            WireFormat::write(&self.n_sats, buf);
9739            WireFormat::write(&self.flags, buf);
9740        }
9741        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
9742            MsgVelNed {
9743                sender_id: None,
9744                tow: WireFormat::parse_unchecked(buf),
9745                n: WireFormat::parse_unchecked(buf),
9746                e: WireFormat::parse_unchecked(buf),
9747                d: WireFormat::parse_unchecked(buf),
9748                h_accuracy: WireFormat::parse_unchecked(buf),
9749                v_accuracy: WireFormat::parse_unchecked(buf),
9750                n_sats: WireFormat::parse_unchecked(buf),
9751                flags: WireFormat::parse_unchecked(buf),
9752            }
9753        }
9754    }
9755
9756    /// Type of reported TOW
9757    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9758    pub enum TypeOfReportedTow {
9759        /// Time of Measurement
9760        TimeOfMeasurement = 0,
9761
9762        /// Other
9763        Other = 1,
9764    }
9765
9766    impl std::fmt::Display for TypeOfReportedTow {
9767        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9768            match self {
9769                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
9770                TypeOfReportedTow::Other => f.write_str("Other"),
9771            }
9772        }
9773    }
9774
9775    impl TryFrom<u8> for TypeOfReportedTow {
9776        type Error = u8;
9777        fn try_from(i: u8) -> Result<Self, u8> {
9778            match i {
9779                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
9780                1 => Ok(TypeOfReportedTow::Other),
9781                i => Err(i),
9782            }
9783        }
9784    }
9785
9786    /// INS Navigation Mode
9787    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9788    pub enum InsNavigationMode {
9789        /// None
9790        None = 0,
9791
9792        /// INS used
9793        InsUsed = 1,
9794    }
9795
9796    impl std::fmt::Display for InsNavigationMode {
9797        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9798            match self {
9799                InsNavigationMode::None => f.write_str("None"),
9800                InsNavigationMode::InsUsed => f.write_str("INS used"),
9801            }
9802        }
9803    }
9804
9805    impl TryFrom<u8> for InsNavigationMode {
9806        type Error = u8;
9807        fn try_from(i: u8) -> Result<Self, u8> {
9808            match i {
9809                0 => Ok(InsNavigationMode::None),
9810                1 => Ok(InsNavigationMode::InsUsed),
9811                i => Err(i),
9812            }
9813        }
9814    }
9815
9816    /// Velocity mode
9817    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9818    pub enum VelocityMode {
9819        /// Invalid
9820        Invalid = 0,
9821
9822        /// Measured Doppler derived
9823        MeasuredDopplerDerived = 1,
9824
9825        /// Computed Doppler derived
9826        ComputedDopplerDerived = 2,
9827
9828        /// Dead Reckoning
9829        DeadReckoning = 3,
9830    }
9831
9832    impl std::fmt::Display for VelocityMode {
9833        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9834            match self {
9835                VelocityMode::Invalid => f.write_str("Invalid"),
9836                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
9837                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
9838                VelocityMode::DeadReckoning => f.write_str("Dead Reckoning"),
9839            }
9840        }
9841    }
9842
9843    impl TryFrom<u8> for VelocityMode {
9844        type Error = u8;
9845        fn try_from(i: u8) -> Result<Self, u8> {
9846            match i {
9847                0 => Ok(VelocityMode::Invalid),
9848                1 => Ok(VelocityMode::MeasuredDopplerDerived),
9849                2 => Ok(VelocityMode::ComputedDopplerDerived),
9850                3 => Ok(VelocityMode::DeadReckoning),
9851                i => Err(i),
9852            }
9853        }
9854    }
9855}
9856
9857pub mod msg_vel_ned_cov {
9858    #![allow(unused_imports)]
9859
9860    use super::*;
9861    use crate::messages::lib::*;
9862
9863    /// Velocity in NED with Covariances
9864    ///
9865    /// This message reports the velocity in local North East Down (NED)
9866    /// coordinates. The NED coordinate system is defined as the local WGS84
9867    /// tangent plane centered at the current position. The full GPS time is given
9868    /// by the preceding MSG_GPS_TIME with the matching time-of-week (tow). This
9869    /// message is similar to the MSG_VEL_NED, but it includes the upper
9870    /// triangular portion of the 3x3 covariance matrix.
9871    ///
9872    /// The values in this message are from GNSS measurements fused with inertial
9873    /// measurements. To get values from GNSS measurements only use
9874    /// MSG_VEL_NED_COV_GNSS.
9875    ///
9876    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9877    #[allow(clippy::derive_partial_eq_without_eq)]
9878    #[derive(Debug, PartialEq, Clone)]
9879    pub struct MsgVelNedCov {
9880        /// The message sender_id
9881        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
9882        pub sender_id: Option<u16>,
9883        /// GPS Time of Week
9884        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
9885        pub tow: u32,
9886        /// Velocity North coordinate
9887        #[cfg_attr(feature = "serde", serde(rename = "n"))]
9888        pub n: i32,
9889        /// Velocity East coordinate
9890        #[cfg_attr(feature = "serde", serde(rename = "e"))]
9891        pub e: i32,
9892        /// Velocity Down coordinate
9893        #[cfg_attr(feature = "serde", serde(rename = "d"))]
9894        pub d: i32,
9895        /// Estimated variance of northward measurement
9896        #[cfg_attr(feature = "serde", serde(rename = "cov_n_n"))]
9897        pub cov_n_n: f32,
9898        /// Covariance of northward and eastward measurement
9899        #[cfg_attr(feature = "serde", serde(rename = "cov_n_e"))]
9900        pub cov_n_e: f32,
9901        /// Covariance of northward and downward measurement
9902        #[cfg_attr(feature = "serde", serde(rename = "cov_n_d"))]
9903        pub cov_n_d: f32,
9904        /// Estimated variance of eastward measurement
9905        #[cfg_attr(feature = "serde", serde(rename = "cov_e_e"))]
9906        pub cov_e_e: f32,
9907        /// Covariance of eastward and downward measurement
9908        #[cfg_attr(feature = "serde", serde(rename = "cov_e_d"))]
9909        pub cov_e_d: f32,
9910        /// Estimated variance of downward measurement
9911        #[cfg_attr(feature = "serde", serde(rename = "cov_d_d"))]
9912        pub cov_d_d: f32,
9913        /// Number of satellites used in solution
9914        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
9915        pub n_sats: u8,
9916        /// Status flags
9917        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
9918        pub flags: u8,
9919    }
9920
9921    impl MsgVelNedCov {
9922        /// Gets the [TypeOfReportedTow][self::TypeOfReportedTow] stored in the `flags` bitfield.
9923        ///
9924        /// Returns `Ok` if the bitrange contains a known `TypeOfReportedTow` variant.
9925        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9926        /// or because new variants of `TypeOfReportedTow` were added.
9927        pub fn type_of_reported_tow(&self) -> Result<TypeOfReportedTow, u8> {
9928            get_bit_range!(self.flags, u8, u8, 5, 5).try_into()
9929        }
9930
9931        /// Set the bitrange corresponding to the [TypeOfReportedTow][TypeOfReportedTow] of the `flags` bitfield.
9932        pub fn set_type_of_reported_tow(&mut self, type_of_reported_tow: TypeOfReportedTow) {
9933            set_bit_range!(&mut self.flags, type_of_reported_tow, u8, u8, 5, 5);
9934        }
9935
9936        /// Gets the [InsNavigationMode][self::InsNavigationMode] stored in the `flags` bitfield.
9937        ///
9938        /// Returns `Ok` if the bitrange contains a known `InsNavigationMode` variant.
9939        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9940        /// or because new variants of `InsNavigationMode` were added.
9941        pub fn ins_navigation_mode(&self) -> Result<InsNavigationMode, u8> {
9942            get_bit_range!(self.flags, u8, u8, 4, 3).try_into()
9943        }
9944
9945        /// Set the bitrange corresponding to the [InsNavigationMode][InsNavigationMode] of the `flags` bitfield.
9946        pub fn set_ins_navigation_mode(&mut self, ins_navigation_mode: InsNavigationMode) {
9947            set_bit_range!(&mut self.flags, ins_navigation_mode, u8, u8, 4, 3);
9948        }
9949
9950        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
9951        ///
9952        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
9953        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
9954        /// or because new variants of `VelocityMode` were added.
9955        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
9956            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
9957        }
9958
9959        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
9960        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
9961            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
9962        }
9963    }
9964
9965    impl ConcreteMessage for MsgVelNedCov {
9966        const MESSAGE_TYPE: u16 = 530;
9967        const MESSAGE_NAME: &'static str = "MSG_VEL_NED_COV";
9968    }
9969
9970    impl SbpMessage for MsgVelNedCov {
9971        fn message_name(&self) -> &'static str {
9972            <Self as ConcreteMessage>::MESSAGE_NAME
9973        }
9974        fn message_type(&self) -> Option<u16> {
9975            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
9976        }
9977        fn sender_id(&self) -> Option<u16> {
9978            self.sender_id
9979        }
9980        fn set_sender_id(&mut self, new_id: u16) {
9981            self.sender_id = Some(new_id);
9982        }
9983        fn encoded_len(&self) -> usize {
9984            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
9985        }
9986        fn is_valid(&self) -> bool {
9987            true
9988        }
9989        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
9990            Ok(self)
9991        }
9992
9993        #[cfg(feature = "swiftnav")]
9994        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
9995            let tow_s = (self.tow as f64) / 1000.0;
9996            let gps_time = match time::GpsTime::new(0, tow_s) {
9997                Ok(gps_time) => gps_time.tow(),
9998                Err(e) => return Some(Err(e.into())),
9999            };
10000            Some(Ok(time::MessageTime::Rover(gps_time.into())))
10001        }
10002    }
10003
10004    impl FriendlyName for MsgVelNedCov {
10005        fn friendly_name() -> &'static str {
10006            "VEL NED COV"
10007        }
10008    }
10009
10010    impl TryFrom<Sbp> for MsgVelNedCov {
10011        type Error = TryFromSbpError;
10012        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
10013            match msg {
10014                Sbp::MsgVelNedCov(m) => Ok(m),
10015                _ => Err(TryFromSbpError(msg)),
10016            }
10017        }
10018    }
10019
10020    impl WireFormat for MsgVelNedCov {
10021        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
10022            + <i32 as WireFormat>::MIN_LEN
10023            + <i32 as WireFormat>::MIN_LEN
10024            + <i32 as WireFormat>::MIN_LEN
10025            + <f32 as WireFormat>::MIN_LEN
10026            + <f32 as WireFormat>::MIN_LEN
10027            + <f32 as WireFormat>::MIN_LEN
10028            + <f32 as WireFormat>::MIN_LEN
10029            + <f32 as WireFormat>::MIN_LEN
10030            + <f32 as WireFormat>::MIN_LEN
10031            + <u8 as WireFormat>::MIN_LEN
10032            + <u8 as WireFormat>::MIN_LEN;
10033        fn len(&self) -> usize {
10034            WireFormat::len(&self.tow)
10035                + WireFormat::len(&self.n)
10036                + WireFormat::len(&self.e)
10037                + WireFormat::len(&self.d)
10038                + WireFormat::len(&self.cov_n_n)
10039                + WireFormat::len(&self.cov_n_e)
10040                + WireFormat::len(&self.cov_n_d)
10041                + WireFormat::len(&self.cov_e_e)
10042                + WireFormat::len(&self.cov_e_d)
10043                + WireFormat::len(&self.cov_d_d)
10044                + WireFormat::len(&self.n_sats)
10045                + WireFormat::len(&self.flags)
10046        }
10047        fn write<B: BufMut>(&self, buf: &mut B) {
10048            WireFormat::write(&self.tow, buf);
10049            WireFormat::write(&self.n, buf);
10050            WireFormat::write(&self.e, buf);
10051            WireFormat::write(&self.d, buf);
10052            WireFormat::write(&self.cov_n_n, buf);
10053            WireFormat::write(&self.cov_n_e, buf);
10054            WireFormat::write(&self.cov_n_d, buf);
10055            WireFormat::write(&self.cov_e_e, buf);
10056            WireFormat::write(&self.cov_e_d, buf);
10057            WireFormat::write(&self.cov_d_d, buf);
10058            WireFormat::write(&self.n_sats, buf);
10059            WireFormat::write(&self.flags, buf);
10060        }
10061        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
10062            MsgVelNedCov {
10063                sender_id: None,
10064                tow: WireFormat::parse_unchecked(buf),
10065                n: WireFormat::parse_unchecked(buf),
10066                e: WireFormat::parse_unchecked(buf),
10067                d: WireFormat::parse_unchecked(buf),
10068                cov_n_n: WireFormat::parse_unchecked(buf),
10069                cov_n_e: WireFormat::parse_unchecked(buf),
10070                cov_n_d: WireFormat::parse_unchecked(buf),
10071                cov_e_e: WireFormat::parse_unchecked(buf),
10072                cov_e_d: WireFormat::parse_unchecked(buf),
10073                cov_d_d: WireFormat::parse_unchecked(buf),
10074                n_sats: WireFormat::parse_unchecked(buf),
10075                flags: WireFormat::parse_unchecked(buf),
10076            }
10077        }
10078    }
10079
10080    /// Type of reported TOW
10081    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10082    pub enum TypeOfReportedTow {
10083        /// Time of Measurement
10084        TimeOfMeasurement = 0,
10085
10086        /// Other
10087        Other = 1,
10088    }
10089
10090    impl std::fmt::Display for TypeOfReportedTow {
10091        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10092            match self {
10093                TypeOfReportedTow::TimeOfMeasurement => f.write_str("Time of Measurement"),
10094                TypeOfReportedTow::Other => f.write_str("Other"),
10095            }
10096        }
10097    }
10098
10099    impl TryFrom<u8> for TypeOfReportedTow {
10100        type Error = u8;
10101        fn try_from(i: u8) -> Result<Self, u8> {
10102            match i {
10103                0 => Ok(TypeOfReportedTow::TimeOfMeasurement),
10104                1 => Ok(TypeOfReportedTow::Other),
10105                i => Err(i),
10106            }
10107        }
10108    }
10109
10110    /// INS Navigation Mode
10111    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10112    pub enum InsNavigationMode {
10113        /// None
10114        None = 0,
10115
10116        /// INS used
10117        InsUsed = 1,
10118    }
10119
10120    impl std::fmt::Display for InsNavigationMode {
10121        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10122            match self {
10123                InsNavigationMode::None => f.write_str("None"),
10124                InsNavigationMode::InsUsed => f.write_str("INS used"),
10125            }
10126        }
10127    }
10128
10129    impl TryFrom<u8> for InsNavigationMode {
10130        type Error = u8;
10131        fn try_from(i: u8) -> Result<Self, u8> {
10132            match i {
10133                0 => Ok(InsNavigationMode::None),
10134                1 => Ok(InsNavigationMode::InsUsed),
10135                i => Err(i),
10136            }
10137        }
10138    }
10139
10140    /// Velocity mode
10141    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10142    pub enum VelocityMode {
10143        /// Invalid
10144        Invalid = 0,
10145
10146        /// Measured Doppler derived
10147        MeasuredDopplerDerived = 1,
10148
10149        /// Computed Doppler derived
10150        ComputedDopplerDerived = 2,
10151
10152        /// Dead Reckoning
10153        DeadReckoning = 3,
10154    }
10155
10156    impl std::fmt::Display for VelocityMode {
10157        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10158            match self {
10159                VelocityMode::Invalid => f.write_str("Invalid"),
10160                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
10161                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
10162                VelocityMode::DeadReckoning => f.write_str("Dead Reckoning"),
10163            }
10164        }
10165    }
10166
10167    impl TryFrom<u8> for VelocityMode {
10168        type Error = u8;
10169        fn try_from(i: u8) -> Result<Self, u8> {
10170            match i {
10171                0 => Ok(VelocityMode::Invalid),
10172                1 => Ok(VelocityMode::MeasuredDopplerDerived),
10173                2 => Ok(VelocityMode::ComputedDopplerDerived),
10174                3 => Ok(VelocityMode::DeadReckoning),
10175                i => Err(i),
10176            }
10177        }
10178    }
10179}
10180
10181pub mod msg_vel_ned_cov_gnss {
10182    #![allow(unused_imports)]
10183
10184    use super::*;
10185    use crate::messages::lib::*;
10186
10187    /// GNSS-only Velocity in NED with Covariances
10188    ///
10189    /// This message reports the velocity in local North East Down (NED)
10190    /// coordinates. The NED coordinate system is defined as the local WGS84
10191    /// tangent plane centered at the current position. The full GPS time is given
10192    /// by the preceding MSG_GPS_TIME_GNSS with the matching time-of-week (tow).
10193    /// This message is similar to the MSG_VEL_NED_GNSS, but it includes the upper
10194    /// triangular portion of the 3x3 covariance matrix.
10195    ///
10196    /// The values in this message are from GNSS measurements only. To get values
10197    /// fused with inertial measurements use MSG_VEL_NED_COV.
10198    ///
10199    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10200    #[allow(clippy::derive_partial_eq_without_eq)]
10201    #[derive(Debug, PartialEq, Clone)]
10202    pub struct MsgVelNedCovGnss {
10203        /// The message sender_id
10204        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
10205        pub sender_id: Option<u16>,
10206        /// GPS Time of Week
10207        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
10208        pub tow: u32,
10209        /// Velocity North coordinate
10210        #[cfg_attr(feature = "serde", serde(rename = "n"))]
10211        pub n: i32,
10212        /// Velocity East coordinate
10213        #[cfg_attr(feature = "serde", serde(rename = "e"))]
10214        pub e: i32,
10215        /// Velocity Down coordinate
10216        #[cfg_attr(feature = "serde", serde(rename = "d"))]
10217        pub d: i32,
10218        /// Estimated variance of northward measurement
10219        #[cfg_attr(feature = "serde", serde(rename = "cov_n_n"))]
10220        pub cov_n_n: f32,
10221        /// Covariance of northward and eastward measurement
10222        #[cfg_attr(feature = "serde", serde(rename = "cov_n_e"))]
10223        pub cov_n_e: f32,
10224        /// Covariance of northward and downward measurement
10225        #[cfg_attr(feature = "serde", serde(rename = "cov_n_d"))]
10226        pub cov_n_d: f32,
10227        /// Estimated variance of eastward measurement
10228        #[cfg_attr(feature = "serde", serde(rename = "cov_e_e"))]
10229        pub cov_e_e: f32,
10230        /// Covariance of eastward and downward measurement
10231        #[cfg_attr(feature = "serde", serde(rename = "cov_e_d"))]
10232        pub cov_e_d: f32,
10233        /// Estimated variance of downward measurement
10234        #[cfg_attr(feature = "serde", serde(rename = "cov_d_d"))]
10235        pub cov_d_d: f32,
10236        /// Number of satellites used in solution
10237        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
10238        pub n_sats: u8,
10239        /// Status flags
10240        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
10241        pub flags: u8,
10242    }
10243
10244    impl MsgVelNedCovGnss {
10245        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
10246        ///
10247        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
10248        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
10249        /// or because new variants of `VelocityMode` were added.
10250        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
10251            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
10252        }
10253
10254        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
10255        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
10256            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
10257        }
10258    }
10259
10260    impl ConcreteMessage for MsgVelNedCovGnss {
10261        const MESSAGE_TYPE: u16 = 562;
10262        const MESSAGE_NAME: &'static str = "MSG_VEL_NED_COV_GNSS";
10263    }
10264
10265    impl SbpMessage for MsgVelNedCovGnss {
10266        fn message_name(&self) -> &'static str {
10267            <Self as ConcreteMessage>::MESSAGE_NAME
10268        }
10269        fn message_type(&self) -> Option<u16> {
10270            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
10271        }
10272        fn sender_id(&self) -> Option<u16> {
10273            self.sender_id
10274        }
10275        fn set_sender_id(&mut self, new_id: u16) {
10276            self.sender_id = Some(new_id);
10277        }
10278        fn encoded_len(&self) -> usize {
10279            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
10280        }
10281        fn is_valid(&self) -> bool {
10282            true
10283        }
10284        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
10285            Ok(self)
10286        }
10287
10288        #[cfg(feature = "swiftnav")]
10289        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
10290            let tow_s = (self.tow as f64) / 1000.0;
10291            let gps_time = match time::GpsTime::new(0, tow_s) {
10292                Ok(gps_time) => gps_time.tow(),
10293                Err(e) => return Some(Err(e.into())),
10294            };
10295            Some(Ok(time::MessageTime::Rover(gps_time.into())))
10296        }
10297    }
10298
10299    impl FriendlyName for MsgVelNedCovGnss {
10300        fn friendly_name() -> &'static str {
10301            "VEL NED COV GNSS-only"
10302        }
10303    }
10304
10305    impl TryFrom<Sbp> for MsgVelNedCovGnss {
10306        type Error = TryFromSbpError;
10307        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
10308            match msg {
10309                Sbp::MsgVelNedCovGnss(m) => Ok(m),
10310                _ => Err(TryFromSbpError(msg)),
10311            }
10312        }
10313    }
10314
10315    impl WireFormat for MsgVelNedCovGnss {
10316        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
10317            + <i32 as WireFormat>::MIN_LEN
10318            + <i32 as WireFormat>::MIN_LEN
10319            + <i32 as WireFormat>::MIN_LEN
10320            + <f32 as WireFormat>::MIN_LEN
10321            + <f32 as WireFormat>::MIN_LEN
10322            + <f32 as WireFormat>::MIN_LEN
10323            + <f32 as WireFormat>::MIN_LEN
10324            + <f32 as WireFormat>::MIN_LEN
10325            + <f32 as WireFormat>::MIN_LEN
10326            + <u8 as WireFormat>::MIN_LEN
10327            + <u8 as WireFormat>::MIN_LEN;
10328        fn len(&self) -> usize {
10329            WireFormat::len(&self.tow)
10330                + WireFormat::len(&self.n)
10331                + WireFormat::len(&self.e)
10332                + WireFormat::len(&self.d)
10333                + WireFormat::len(&self.cov_n_n)
10334                + WireFormat::len(&self.cov_n_e)
10335                + WireFormat::len(&self.cov_n_d)
10336                + WireFormat::len(&self.cov_e_e)
10337                + WireFormat::len(&self.cov_e_d)
10338                + WireFormat::len(&self.cov_d_d)
10339                + WireFormat::len(&self.n_sats)
10340                + WireFormat::len(&self.flags)
10341        }
10342        fn write<B: BufMut>(&self, buf: &mut B) {
10343            WireFormat::write(&self.tow, buf);
10344            WireFormat::write(&self.n, buf);
10345            WireFormat::write(&self.e, buf);
10346            WireFormat::write(&self.d, buf);
10347            WireFormat::write(&self.cov_n_n, buf);
10348            WireFormat::write(&self.cov_n_e, buf);
10349            WireFormat::write(&self.cov_n_d, buf);
10350            WireFormat::write(&self.cov_e_e, buf);
10351            WireFormat::write(&self.cov_e_d, buf);
10352            WireFormat::write(&self.cov_d_d, buf);
10353            WireFormat::write(&self.n_sats, buf);
10354            WireFormat::write(&self.flags, buf);
10355        }
10356        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
10357            MsgVelNedCovGnss {
10358                sender_id: None,
10359                tow: WireFormat::parse_unchecked(buf),
10360                n: WireFormat::parse_unchecked(buf),
10361                e: WireFormat::parse_unchecked(buf),
10362                d: WireFormat::parse_unchecked(buf),
10363                cov_n_n: WireFormat::parse_unchecked(buf),
10364                cov_n_e: WireFormat::parse_unchecked(buf),
10365                cov_n_d: WireFormat::parse_unchecked(buf),
10366                cov_e_e: WireFormat::parse_unchecked(buf),
10367                cov_e_d: WireFormat::parse_unchecked(buf),
10368                cov_d_d: WireFormat::parse_unchecked(buf),
10369                n_sats: WireFormat::parse_unchecked(buf),
10370                flags: WireFormat::parse_unchecked(buf),
10371            }
10372        }
10373    }
10374
10375    /// Velocity mode
10376    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10377    pub enum VelocityMode {
10378        /// Invalid
10379        Invalid = 0,
10380
10381        /// Measured Doppler derived
10382        MeasuredDopplerDerived = 1,
10383
10384        /// Computed Doppler derived
10385        ComputedDopplerDerived = 2,
10386    }
10387
10388    impl std::fmt::Display for VelocityMode {
10389        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10390            match self {
10391                VelocityMode::Invalid => f.write_str("Invalid"),
10392                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
10393                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
10394            }
10395        }
10396    }
10397
10398    impl TryFrom<u8> for VelocityMode {
10399        type Error = u8;
10400        fn try_from(i: u8) -> Result<Self, u8> {
10401            match i {
10402                0 => Ok(VelocityMode::Invalid),
10403                1 => Ok(VelocityMode::MeasuredDopplerDerived),
10404                2 => Ok(VelocityMode::ComputedDopplerDerived),
10405                i => Err(i),
10406            }
10407        }
10408    }
10409}
10410
10411pub mod msg_vel_ned_dep_a {
10412    #![allow(unused_imports)]
10413
10414    use super::*;
10415    use crate::messages::lib::*;
10416
10417    /// Deprecated
10418    ///
10419    /// Deprecated.
10420    ///
10421    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10422    #[allow(clippy::derive_partial_eq_without_eq)]
10423    #[derive(Debug, PartialEq, Clone)]
10424    pub struct MsgVelNedDepA {
10425        /// The message sender_id
10426        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
10427        pub sender_id: Option<u16>,
10428        /// GPS Time of Week
10429        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
10430        pub tow: u32,
10431        /// Velocity North coordinate
10432        #[cfg_attr(feature = "serde", serde(rename = "n"))]
10433        pub n: i32,
10434        /// Velocity East coordinate
10435        #[cfg_attr(feature = "serde", serde(rename = "e"))]
10436        pub e: i32,
10437        /// Velocity Down coordinate
10438        #[cfg_attr(feature = "serde", serde(rename = "d"))]
10439        pub d: i32,
10440        /// Horizontal velocity accuracy estimate (not implemented). Defaults to 0.
10441        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
10442        pub h_accuracy: u16,
10443        /// Vertical velocity accuracy estimate (not implemented). Defaults to 0.
10444        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
10445        pub v_accuracy: u16,
10446        /// Number of satellites used in solution
10447        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
10448        pub n_sats: u8,
10449        /// Status flags (reserved)
10450        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
10451        pub flags: u8,
10452    }
10453
10454    impl ConcreteMessage for MsgVelNedDepA {
10455        const MESSAGE_TYPE: u16 = 517;
10456        const MESSAGE_NAME: &'static str = "MSG_VEL_NED_DEP_A";
10457    }
10458
10459    impl SbpMessage for MsgVelNedDepA {
10460        fn message_name(&self) -> &'static str {
10461            <Self as ConcreteMessage>::MESSAGE_NAME
10462        }
10463        fn message_type(&self) -> Option<u16> {
10464            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
10465        }
10466        fn sender_id(&self) -> Option<u16> {
10467            self.sender_id
10468        }
10469        fn set_sender_id(&mut self, new_id: u16) {
10470            self.sender_id = Some(new_id);
10471        }
10472        fn encoded_len(&self) -> usize {
10473            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
10474        }
10475        fn is_valid(&self) -> bool {
10476            true
10477        }
10478        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
10479            Ok(self)
10480        }
10481
10482        #[cfg(feature = "swiftnav")]
10483        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
10484            let tow_s = (self.tow as f64) / 1000.0;
10485            let gps_time = match time::GpsTime::new(0, tow_s) {
10486                Ok(gps_time) => gps_time.tow(),
10487                Err(e) => return Some(Err(e.into())),
10488            };
10489            Some(Ok(time::MessageTime::Rover(gps_time.into())))
10490        }
10491    }
10492
10493    impl FriendlyName for MsgVelNedDepA {
10494        fn friendly_name() -> &'static str {
10495            "VEL NED DEP A"
10496        }
10497    }
10498
10499    impl TryFrom<Sbp> for MsgVelNedDepA {
10500        type Error = TryFromSbpError;
10501        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
10502            match msg {
10503                Sbp::MsgVelNedDepA(m) => Ok(m),
10504                _ => Err(TryFromSbpError(msg)),
10505            }
10506        }
10507    }
10508
10509    impl WireFormat for MsgVelNedDepA {
10510        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
10511            + <i32 as WireFormat>::MIN_LEN
10512            + <i32 as WireFormat>::MIN_LEN
10513            + <i32 as WireFormat>::MIN_LEN
10514            + <u16 as WireFormat>::MIN_LEN
10515            + <u16 as WireFormat>::MIN_LEN
10516            + <u8 as WireFormat>::MIN_LEN
10517            + <u8 as WireFormat>::MIN_LEN;
10518        fn len(&self) -> usize {
10519            WireFormat::len(&self.tow)
10520                + WireFormat::len(&self.n)
10521                + WireFormat::len(&self.e)
10522                + WireFormat::len(&self.d)
10523                + WireFormat::len(&self.h_accuracy)
10524                + WireFormat::len(&self.v_accuracy)
10525                + WireFormat::len(&self.n_sats)
10526                + WireFormat::len(&self.flags)
10527        }
10528        fn write<B: BufMut>(&self, buf: &mut B) {
10529            WireFormat::write(&self.tow, buf);
10530            WireFormat::write(&self.n, buf);
10531            WireFormat::write(&self.e, buf);
10532            WireFormat::write(&self.d, buf);
10533            WireFormat::write(&self.h_accuracy, buf);
10534            WireFormat::write(&self.v_accuracy, buf);
10535            WireFormat::write(&self.n_sats, buf);
10536            WireFormat::write(&self.flags, buf);
10537        }
10538        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
10539            MsgVelNedDepA {
10540                sender_id: None,
10541                tow: WireFormat::parse_unchecked(buf),
10542                n: WireFormat::parse_unchecked(buf),
10543                e: WireFormat::parse_unchecked(buf),
10544                d: WireFormat::parse_unchecked(buf),
10545                h_accuracy: WireFormat::parse_unchecked(buf),
10546                v_accuracy: WireFormat::parse_unchecked(buf),
10547                n_sats: WireFormat::parse_unchecked(buf),
10548                flags: WireFormat::parse_unchecked(buf),
10549            }
10550        }
10551    }
10552}
10553
10554pub mod msg_vel_ned_gnss {
10555    #![allow(unused_imports)]
10556
10557    use super::*;
10558    use crate::messages::lib::*;
10559
10560    /// GNSS-only Velocity in NED
10561    ///
10562    /// This message reports the velocity in local North East Down (NED)
10563    /// coordinates. The NED coordinate system is defined as the local WGS84
10564    /// tangent plane centered at the current position. The full GPS time is given
10565    /// by the preceding MSG_GPS_TIME_GNSS with the matching time-of-week (tow).
10566    ///
10567    /// The values in this message are from GNSS measurements only. To get values
10568    /// fused with inertial measurements use MSG_VEL_NED.
10569    ///
10570    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10571    #[allow(clippy::derive_partial_eq_without_eq)]
10572    #[derive(Debug, PartialEq, Clone)]
10573    pub struct MsgVelNedGnss {
10574        /// The message sender_id
10575        #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))]
10576        pub sender_id: Option<u16>,
10577        /// GPS Time of Week
10578        #[cfg_attr(feature = "serde", serde(rename = "tow"))]
10579        pub tow: u32,
10580        /// Velocity North coordinate
10581        #[cfg_attr(feature = "serde", serde(rename = "n"))]
10582        pub n: i32,
10583        /// Velocity East coordinate
10584        #[cfg_attr(feature = "serde", serde(rename = "e"))]
10585        pub e: i32,
10586        /// Velocity Down coordinate
10587        #[cfg_attr(feature = "serde", serde(rename = "d"))]
10588        pub d: i32,
10589        /// Horizontal velocity estimated standard deviation
10590        #[cfg_attr(feature = "serde", serde(rename = "h_accuracy"))]
10591        pub h_accuracy: u16,
10592        /// Vertical velocity estimated standard deviation
10593        #[cfg_attr(feature = "serde", serde(rename = "v_accuracy"))]
10594        pub v_accuracy: u16,
10595        /// Number of satellites used in solution
10596        #[cfg_attr(feature = "serde", serde(rename = "n_sats"))]
10597        pub n_sats: u8,
10598        /// Status flags
10599        #[cfg_attr(feature = "serde", serde(rename = "flags"))]
10600        pub flags: u8,
10601    }
10602
10603    impl MsgVelNedGnss {
10604        /// Gets the [VelocityMode][self::VelocityMode] stored in the `flags` bitfield.
10605        ///
10606        /// Returns `Ok` if the bitrange contains a known `VelocityMode` variant.
10607        /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message,
10608        /// or because new variants of `VelocityMode` were added.
10609        pub fn velocity_mode(&self) -> Result<VelocityMode, u8> {
10610            get_bit_range!(self.flags, u8, u8, 2, 0).try_into()
10611        }
10612
10613        /// Set the bitrange corresponding to the [VelocityMode][VelocityMode] of the `flags` bitfield.
10614        pub fn set_velocity_mode(&mut self, velocity_mode: VelocityMode) {
10615            set_bit_range!(&mut self.flags, velocity_mode, u8, u8, 2, 0);
10616        }
10617    }
10618
10619    impl ConcreteMessage for MsgVelNedGnss {
10620        const MESSAGE_TYPE: u16 = 558;
10621        const MESSAGE_NAME: &'static str = "MSG_VEL_NED_GNSS";
10622    }
10623
10624    impl SbpMessage for MsgVelNedGnss {
10625        fn message_name(&self) -> &'static str {
10626            <Self as ConcreteMessage>::MESSAGE_NAME
10627        }
10628        fn message_type(&self) -> Option<u16> {
10629            Some(<Self as ConcreteMessage>::MESSAGE_TYPE)
10630        }
10631        fn sender_id(&self) -> Option<u16> {
10632            self.sender_id
10633        }
10634        fn set_sender_id(&mut self, new_id: u16) {
10635            self.sender_id = Some(new_id);
10636        }
10637        fn encoded_len(&self) -> usize {
10638            WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN
10639        }
10640        fn is_valid(&self) -> bool {
10641            true
10642        }
10643        fn into_valid_msg(self) -> Result<Self, crate::messages::invalid::Invalid> {
10644            Ok(self)
10645        }
10646
10647        #[cfg(feature = "swiftnav")]
10648        fn gps_time(&self) -> Option<std::result::Result<time::MessageTime, time::GpsTimeError>> {
10649            let tow_s = (self.tow as f64) / 1000.0;
10650            let gps_time = match time::GpsTime::new(0, tow_s) {
10651                Ok(gps_time) => gps_time.tow(),
10652                Err(e) => return Some(Err(e.into())),
10653            };
10654            Some(Ok(time::MessageTime::Rover(gps_time.into())))
10655        }
10656    }
10657
10658    impl FriendlyName for MsgVelNedGnss {
10659        fn friendly_name() -> &'static str {
10660            "VEL NED GNSS-only"
10661        }
10662    }
10663
10664    impl TryFrom<Sbp> for MsgVelNedGnss {
10665        type Error = TryFromSbpError;
10666        fn try_from(msg: Sbp) -> Result<Self, Self::Error> {
10667            match msg {
10668                Sbp::MsgVelNedGnss(m) => Ok(m),
10669                _ => Err(TryFromSbpError(msg)),
10670            }
10671        }
10672    }
10673
10674    impl WireFormat for MsgVelNedGnss {
10675        const MIN_LEN: usize = <u32 as WireFormat>::MIN_LEN
10676            + <i32 as WireFormat>::MIN_LEN
10677            + <i32 as WireFormat>::MIN_LEN
10678            + <i32 as WireFormat>::MIN_LEN
10679            + <u16 as WireFormat>::MIN_LEN
10680            + <u16 as WireFormat>::MIN_LEN
10681            + <u8 as WireFormat>::MIN_LEN
10682            + <u8 as WireFormat>::MIN_LEN;
10683        fn len(&self) -> usize {
10684            WireFormat::len(&self.tow)
10685                + WireFormat::len(&self.n)
10686                + WireFormat::len(&self.e)
10687                + WireFormat::len(&self.d)
10688                + WireFormat::len(&self.h_accuracy)
10689                + WireFormat::len(&self.v_accuracy)
10690                + WireFormat::len(&self.n_sats)
10691                + WireFormat::len(&self.flags)
10692        }
10693        fn write<B: BufMut>(&self, buf: &mut B) {
10694            WireFormat::write(&self.tow, buf);
10695            WireFormat::write(&self.n, buf);
10696            WireFormat::write(&self.e, buf);
10697            WireFormat::write(&self.d, buf);
10698            WireFormat::write(&self.h_accuracy, buf);
10699            WireFormat::write(&self.v_accuracy, buf);
10700            WireFormat::write(&self.n_sats, buf);
10701            WireFormat::write(&self.flags, buf);
10702        }
10703        fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
10704            MsgVelNedGnss {
10705                sender_id: None,
10706                tow: WireFormat::parse_unchecked(buf),
10707                n: WireFormat::parse_unchecked(buf),
10708                e: WireFormat::parse_unchecked(buf),
10709                d: WireFormat::parse_unchecked(buf),
10710                h_accuracy: WireFormat::parse_unchecked(buf),
10711                v_accuracy: WireFormat::parse_unchecked(buf),
10712                n_sats: WireFormat::parse_unchecked(buf),
10713                flags: WireFormat::parse_unchecked(buf),
10714            }
10715        }
10716    }
10717
10718    /// Velocity mode
10719    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10720    pub enum VelocityMode {
10721        /// Invalid
10722        Invalid = 0,
10723
10724        /// Measured Doppler derived
10725        MeasuredDopplerDerived = 1,
10726
10727        /// Computed Doppler derived
10728        ComputedDopplerDerived = 2,
10729    }
10730
10731    impl std::fmt::Display for VelocityMode {
10732        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10733            match self {
10734                VelocityMode::Invalid => f.write_str("Invalid"),
10735                VelocityMode::MeasuredDopplerDerived => f.write_str("Measured Doppler derived"),
10736                VelocityMode::ComputedDopplerDerived => f.write_str("Computed Doppler derived"),
10737            }
10738        }
10739    }
10740
10741    impl TryFrom<u8> for VelocityMode {
10742        type Error = u8;
10743        fn try_from(i: u8) -> Result<Self, u8> {
10744            match i {
10745                0 => Ok(VelocityMode::Invalid),
10746                1 => Ok(VelocityMode::MeasuredDopplerDerived),
10747                2 => Ok(VelocityMode::ComputedDopplerDerived),
10748                i => Err(i),
10749            }
10750        }
10751    }
10752}