use crate::nmea::field::{FieldReader, FieldWriter, NmeaEncodable};
#[derive(Debug, Clone, PartialEq)]
pub struct Pashr {
pub time: Option<String>,
pub heading: Option<f32>,
pub roll: Option<f32>,
pub pitch: Option<f32>,
pub heave: Option<f32>,
pub roll_accuracy: Option<f32>,
pub pitch_accuracy: Option<f32>,
pub heading_accuracy: Option<f32>,
pub gnss_quality: Option<u8>,
pub imu_alignment: Option<u8>,
}
impl Pashr {
pub fn parse(fields: &[&str]) -> Option<Self> {
let mut r = FieldReader::new(fields);
let time = r.string();
let heading = r.f32();
r.skip(); let roll = r.f32();
let pitch = r.f32();
let heave = r.f32();
let roll_accuracy = r.f32();
let pitch_accuracy = r.f32();
let heading_accuracy = r.f32();
let gnss_quality = r.u8();
let imu_alignment = r.u8();
Some(Self {
time,
heading,
roll,
pitch,
heave,
roll_accuracy,
pitch_accuracy,
heading_accuracy,
gnss_quality,
imu_alignment,
})
}
}
impl NmeaEncodable for Pashr {
const SENTENCE_TYPE: &str = "SHR";
const PROPRIETARY_ID: &str = "PASHR";
fn encode(&self) -> Vec<String> {
let mut w = FieldWriter::new();
w.string(self.time.as_deref());
w.f32(self.heading);
w.fixed('T');
w.f32(self.roll);
w.f32(self.pitch);
w.f32(self.heave);
w.f32(self.roll_accuracy);
w.f32(self.pitch_accuracy);
w.f32(self.heading_accuracy);
w.u8(self.gnss_quality);
w.u8(self.imu_alignment);
w.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parse_frame;
#[test]
fn pashr_empty() {
let s = Pashr {
time: None,
heading: None,
roll: None,
pitch: None,
heave: None,
roll_accuracy: None,
pitch_accuracy: None,
heading_accuracy: None,
gnss_quality: None,
imu_alignment: None,
}
.to_proprietary_sentence();
let f = parse_frame(s.trim()).expect("valid");
let p = Pashr::parse(&f.fields).expect("parse");
assert!(p.time.is_none());
assert!(p.heading.is_none());
}
#[test]
fn pashr_encode_roundtrip() {
let original = Pashr {
time: Some("085335.000".to_string()),
heading: Some(224.19),
roll: Some(-1.26),
pitch: Some(0.83),
heave: Some(0.10),
roll_accuracy: Some(0.101),
pitch_accuracy: Some(0.113),
heading_accuracy: Some(0.267),
gnss_quality: Some(1),
imu_alignment: Some(0),
};
let sentence = original.to_proprietary_sentence();
let frame = parse_frame(sentence.trim()).expect("re-parse");
let parsed = Pashr::parse(&frame.fields).expect("parse");
assert_eq!(original, parsed);
}
#[test]
fn pashr_pashr_gonmea() {
let frame =
parse_frame("$PASHR,085335.000,224.19,T,-01.26,+00.83,+00.10,0.101,0.113,0.267,1,0*07")
.expect("valid");
let p = Pashr::parse(&frame.fields).expect("parse");
assert_eq!(p.time.as_deref(), Some("085335.000"));
assert!((p.heading.expect("heading") - 224.19).abs() < 0.01);
assert_eq!(p.gnss_quality, Some(1));
assert_eq!(p.imu_alignment, Some(0));
}
}