diff --git a/README.md b/README.md index e673145..29c38da 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ NMEA Standard Sentences - GNS * - GSA * - GSV * +- HDT - MDA - MTW - MWV diff --git a/src/lib.rs b/src/lib.rs index 9fe6e45..edef100 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ //! - GNS * //! - GSA * //! - GSV * +//! - HDT //! - MDA //! - MWV //! - RMC * diff --git a/src/parse.rs b/src/parse.rs index 1258121..293eace 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -107,6 +107,7 @@ pub enum ParseResult { GNS(GnsData), GSA(GsaData), GSV(GsvData), + HDT(HdtData), MDA(MdaData), MTW(MtwData), MWV(MwvData), @@ -131,6 +132,7 @@ impl From<&ParseResult> for SentenceType { ParseResult::GNS(_) => SentenceType::GNS, ParseResult::GSA(_) => SentenceType::GSA, ParseResult::GSV(_) => SentenceType::GSV, + ParseResult::HDT(_) => SentenceType::HDT, ParseResult::MDA(_) => SentenceType::MDA, ParseResult::MTW(_) => SentenceType::MTW, ParseResult::MWV(_) => SentenceType::MWV, @@ -178,6 +180,7 @@ pub fn parse_str(sentence_input: &str) -> Result { SentenceType::GBS => parse_gbs(nmea_sentence).map(ParseResult::GBS), SentenceType::GGA => parse_gga(nmea_sentence).map(ParseResult::GGA), SentenceType::GSV => parse_gsv(nmea_sentence).map(ParseResult::GSV), + SentenceType::HDT => parse_hdt(nmea_sentence).map(ParseResult::HDT), SentenceType::RMC => parse_rmc(nmea_sentence).map(ParseResult::RMC), SentenceType::GSA => parse_gsa(nmea_sentence).map(ParseResult::GSA), SentenceType::VTG => parse_vtg(nmea_sentence).map(ParseResult::VTG), diff --git a/src/parser.rs b/src/parser.rs index 6cf46c8..fd0ffe1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -357,6 +357,7 @@ impl<'a> Nmea { | ParseResult::GBS(_) | ParseResult::AAM(_) | ParseResult::ALM(_) + | ParseResult::HDT(_) | ParseResult::PGRMZ(_) | ParseResult::MTW(_) | ParseResult::MWV(_) diff --git a/src/sentences/hdt.rs b/src/sentences/hdt.rs new file mode 100644 index 0000000..c6653b3 --- /dev/null +++ b/src/sentences/hdt.rs @@ -0,0 +1,84 @@ +use nom::{ + bytes::complete::take_until, + character::complete::char, + combinator::{map_res, opt}, + IResult, +}; + +use super::utils::parse_float_num; +use crate::{Error, NmeaSentence, SentenceType}; + +/// HDT - Heading - True +/// +/// +/// +/// ```text +/// 1 2 3 +/// | | | +/// $--HDT,x.x,T*hh +/// ``` +/// 1. Heading, degrees True +/// 2. T = True +/// 3. Checksum +#[derive(Debug, PartialEq)] +pub struct HdtData { + /// Heading, degrees True + pub heading: Option, +} + +/// # Parse HDT message +/// +/// From gpsd/driver_nmea0183.c +/// +/// ```text +/// $HEHDT,341.8,T*21 +/// +/// HDT,x.x*hh +/// ``` +/// +/// The only data field is true heading in degrees. +/// The following field is required to be 'T' indicating a true heading. +/// It is followed by a mandatory nmea_checksum. +pub fn parse_hdt(sentence: NmeaSentence) -> Result { + if sentence.message_id != SentenceType::HDT { + Err(Error::WrongSentenceHeader { + expected: SentenceType::HDT, + found: sentence.message_id, + }) + } else { + Ok(do_parse_hdt(sentence.data)?.1) + } +} + +fn do_parse_hdt(i: &str) -> IResult<&str, HdtData> { + let (i, heading) = opt(map_res(take_until(","), parse_float_num::))(i)?; + let (i, _) = char(',')(i)?; + let (i, _) = char('T')(i)?; + Ok((i, HdtData { heading })) +} + +#[cfg(test)] +mod tests { + use approx::assert_relative_eq; + + use super::*; + use crate::parse::parse_nmea_sentence; + + #[test] + fn test_parse_hdt_full() { + let data = parse_hdt(NmeaSentence { + talker_id: "GP", + message_id: SentenceType::HDT, + data: "274.07,T", + checksum: 0x03, + }) + .unwrap(); + assert_relative_eq!(data.heading.unwrap(), 274.07); + + let s = parse_nmea_sentence("$GPHDT,,T*1B").unwrap(); + assert_eq!(s.checksum, s.calc_checksum()); + + let data = parse_hdt(s); + assert_eq!(data, Ok(HdtData { heading: None })); + } +} diff --git a/src/sentences/mod.rs b/src/sentences/mod.rs index 644d0e4..0c94cb9 100644 --- a/src/sentences/mod.rs +++ b/src/sentences/mod.rs @@ -10,6 +10,7 @@ mod gll; mod gns; mod gsa; mod gsv; +mod hdt; mod mda; mod mtw; mod mwv; @@ -37,6 +38,7 @@ pub use { gnss_type::GnssType, gsa::{parse_gsa, GsaData}, gsv::{parse_gsv, GsvData}, + hdt::{parse_hdt, HdtData}, mda::{parse_mda, MdaData}, mtw::{parse_mtw, MtwData, MtwUnit}, mwv::{parse_mwv, MwvData, MwvReference, MwvWindSpeedUnits}, diff --git a/tests/all_supported_messages.rs b/tests/all_supported_messages.rs index 915d312..b665cc9 100644 --- a/tests/all_supported_messages.rs +++ b/tests/all_supported_messages.rs @@ -21,6 +21,8 @@ fn test_all_supported_messages() { (SentenceType::GSA, "$GPGSA,A,3,23,31,22,16,03,07,,,,,,,1.8,1.1,1.4*3E"), // GSV (SentenceType::GSV, "$GPGSV,3,1,12,01,49,196,41,03,71,278,32,06,02,323,27,11,21,196,39*72"), + // HDT + (SentenceType::HDT, "$GPHDT,274.07,T*03"), // MDA (SentenceType::MDA, "$WIMWV,041.1,R,01.0,N,A*16"), // MWV