use crate::nmea::field::{FieldReader, FieldWriter};
#[derive(Debug, Clone, PartialEq)]
pub struct Dbk {
pub depth_feet: Option<f32>,
pub depth_meters: Option<f32>,
pub depth_fathoms: Option<f32>,
}
impl Dbk {
pub const SENTENCE_TYPE: &str = "DBK";
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,
})
}
pub 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()
}
pub fn to_sentence(&self, talker: &str) -> String {
let fields = self.encode();
let field_refs: Vec<&str> = fields.iter().map(|s| s.as_str()).collect();
crate::encode_frame('$', talker, Self::SENTENCE_TYPE, &field_refs)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parse_frame;
#[test]
fn dbk_empty() {
let f = parse_frame("$IIDBK,,f,,M,,F*20").expect("valid");
let d = Dbk::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 dbk_encode_roundtrip() {
let dbk = Dbk {
depth_feet: Some(35.53),
depth_meters: Some(10.83),
depth_fathoms: Some(5.85),
};
let sentence = dbk.to_sentence("II");
assert!(sentence.starts_with("$IIDBK,"));
let frame = parse_frame(sentence.trim()).expect("re-parse");
let dbk2 = Dbk::parse(&frame.fields).expect("re-parse DBK");
assert_eq!(dbk, dbk2);
}
#[test]
fn dbk_full_gonmea() {
let f = parse_frame("$SDDBK,12.3,f,3.7,M,2.0,F*2F").expect("valid DBK from go-nmea");
let d = Dbk::parse(&f.fields).expect("parse DBK");
assert!((d.depth_feet.expect("depth_feet present") - 12.3).abs() < 0.01);
assert!((d.depth_meters.expect("depth_meters present") - 3.7).abs() < 0.01);
assert!((d.depth_fathoms.expect("depth_fathoms present") - 2.0).abs() < 0.01);
}
#[test]
fn dbk_signalk() {
let f =
parse_frame("$IIDBK,035.53,f,010.83,M,005.85,F*3C").expect("valid DBK from SignalK");
let d = Dbk::parse(&f.fields).expect("parse DBK");
assert!((d.depth_meters.expect("depth_meters present") - 10.83).abs() < 0.01);
}
}