rust_nmea/commands/
gll.rs

1use crate::types::{CardinalDirection, Command, Cordinate, Error, ModeIndicator, Status, Time};
2
3/// GLL ( Geographic Position - Latitude/Longitude )
4#[derive(Debug, Clone, PartialEq)]
5pub struct GLL {
6    /// Latitude in ddmm.mmmm format
7    pub lat: Cordinate,
8    /// N=North/S=South indicator
9    pub northing_indicator: CardinalDirection,
10    /// Longitude in dddmm.mmmm format
11    pub lon: Cordinate,
12    /// E=East/W=West indicator
13    pub easting_indicator: CardinalDirection,
14    /// UTC Time in hhmmss.sss format
15    pub time: Time,
16    /// Status
17    pub status: Status,
18    /// Mode Indicator
19    pub mode_indicator: ModeIndicator,
20}
21
22impl Default for GLL {
23    fn default() -> Self {
24        Self {
25            lat: Default::default(),
26            lon: Default::default(),
27            time: Default::default(),
28            status: Status::Invalid,
29            mode_indicator: ModeIndicator::NoFix,
30            northing_indicator: CardinalDirection::North,
31            easting_indicator: CardinalDirection::East,
32        }
33    }
34}
35
36impl Command<GLL> for GLL {
37    fn parse_command(&self, command: Vec<String>) -> Result<GLL, crate::types::Error> {
38        let latitude_degree = command[0][..3].parse()?;
39        let latitude_minute = command[0][3..].parse()?;
40        let northing_indicator = match command[1].chars().next() {
41            Some(e) => e,
42            None => return Err(Error::ParseError("Invalid northing indicator".to_string())),
43        };
44
45        let northing_indicator = match CardinalDirection::from_char(northing_indicator) {
46            Some(e) => e,
47            None => return Err(Error::ParseError("Invalid northing indicator".to_string())),
48        };
49
50        let longitude_degree = command[2][..3].parse()?;
51        let longitude_minute = command[2][3..].parse()?;
52        let easting_indicator = match command[3].chars().next() {
53            Some(e) => e,
54            None => return Err(Error::ParseError("Invalid easting indicator".to_string())),
55        };
56
57        let easting_indicator = match CardinalDirection::from_char(easting_indicator) {
58            Some(e) => e,
59            None => return Err(Error::ParseError("Invalid easting indicator".to_string())),
60        };
61
62        let lat = Cordinate {
63            degree: latitude_degree,
64            minute: latitude_minute,
65        };
66
67        let lon = Cordinate {
68            degree: longitude_degree,
69            minute: longitude_minute,
70        };
71
72        let time_split: Vec<&str> = if command[0].contains('.') {
73            command[0].split('.').collect()
74        } else {
75            vec![&command[0], "0"]
76        };
77
78        let hour = time_split[0][..2].parse::<u8>()?;
79        let minute = time_split[0][2..4].parse::<u8>()?;
80        let second = time_split[0][4..6].parse::<u8>()?;
81        let decimal_seconds = time_split[1].parse::<u8>()?;
82        let time = Time {
83            hour,
84            minute,
85            second,
86            decimal_seconds,
87        };
88        let status = match Status::from_str(&command[5]) {
89            Ok(e) => e,
90            Err(_) => {
91                return Err(Error::ParseError("Invalid status".to_string()));
92            }
93        };
94        let mode_indicator = match ModeIndicator::from_str(&command[6]) {
95            Ok(e) => e,
96            Err(_) => return Err(Error::ParseError("Invalid mode indicator".to_string())),
97        };
98
99        Ok(GLL {
100            lat,
101            northing_indicator,
102            lon,
103            easting_indicator,
104            time,
105            status,
106            mode_indicator,
107        })
108    }
109}