use crate::nmea::field::{FieldReader, FieldWriter, NmeaEncodable};
#[derive(Debug, Clone, PartialEq)]
pub struct Dbt {
pub depth_feet: Option<f32>,
pub depth_meters: Option<f32>,
pub depth_fathoms: Option<f32>,
}
impl Dbt {
pub fn parse(fields: &[&str]) -> Option<Self> {
let mut r = FieldReader::new(fields);
let depth_feet = r.f32();
r.skip();
let depth_meters = r.f32();
r.skip();
let depth_fathoms = r.f32();
Some(Self {
depth_feet,
depth_meters,
depth_fathoms,
})
}
}
impl NmeaEncodable for Dbt {
const SENTENCE_TYPE: &str = "DBT";
fn encode(&self) -> Vec<String> {
let mut w = FieldWriter::new();
w.f32(self.depth_feet);
w.fixed('f');
w.f32(self.depth_meters);
w.fixed('M');
w.f32(self.depth_fathoms);
w.fixed('F');
w.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parse_frame;
#[test]
fn dbt_empty() {
let f = parse_frame("$IIDBT,,,,,,*52").expect("valid");
let d = Dbt::parse(&f.fields).expect("parse");
assert!(d.depth_feet.is_none());
assert!(d.depth_meters.is_none());
assert!(d.depth_fathoms.is_none());
}
#[test]
fn dbt_gpsd() {
let f = parse_frame("$SDDBT,7.7,f,2.3,M,1.3,F*05").expect("valid DBT frame");
let d = Dbt::parse(&f.fields).expect("parse DBT");
assert!((d.depth_meters.expect("depth_meters present") - 2.3).abs() < 0.01);
}
#[test]
fn dbt_encode_roundtrip() {
let original = Dbt {
depth_feet: Some(35.53),
depth_meters: Some(10.83),
depth_fathoms: Some(5.85),
};
let sentence = original.to_sentence("II");
assert!(sentence.starts_with("$IIDBT,"));
let frame = parse_frame(sentence.trim()).expect("re-parse DBT sentence");
let parsed = Dbt::parse(&frame.fields).expect("parse DBT from re-encoded frame");
assert_eq!(original, parsed);
}
#[test]
fn dbt_signalk() {
let f = parse_frame("$IIDBT,035.53,f,010.83,M,005.85,F*23").expect("valid DBT frame");
let d = Dbt::parse(&f.fields).expect("parse DBT");
assert!((d.depth_meters.expect("depth_meters present") - 10.83).abs() < 0.01);
}
}