use crate::nmea::field::{FieldReader, FieldWriter, NmeaEncodable};
#[derive(Debug, Clone, PartialEq)]
pub struct Dbs {
pub depth_feet: Option<f32>,
pub depth_meters: Option<f32>,
pub depth_fathoms: Option<f32>,
}
impl Dbs {
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 Dbs {
const SENTENCE_TYPE: &str = "DBS";
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 dbs_empty() {
let f = parse_frame("$IIDBS,,,,,,*55").expect("empty DBS frame");
let d = Dbs::parse(&f.fields).expect("parse DBS");
assert!(d.depth_feet.is_none());
assert!(d.depth_meters.is_none());
assert!(d.depth_fathoms.is_none());
}
#[test]
fn dbs_encode_roundtrip() {
let original = Dbs {
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("$IIDBS,"));
let frame = parse_frame(sentence.trim()).expect("re-parse DBS sentence");
let parsed = Dbs::parse(&frame.fields).expect("parse DBS from re-encoded frame");
assert_eq!(original, parsed);
}
#[test]
fn dbs_signalk() {
let f = parse_frame("$IIDBS,035.53,f,010.83,M,005.85,F*24").expect("valid DBS frame");
let d = Dbs::parse(&f.fields).expect("parse DBS");
assert!((d.depth_meters.expect("depth_meters present") - 10.83).abs() < 0.01);
}
}