use crate::nmea::field::{FieldReader, FieldWriter, NmeaEncodable};
#[derive(Debug, Clone, PartialEq)]
pub struct Rsa {
pub starboard_angle: Option<f32>,
pub starboard_status: Option<char>,
pub port_angle: Option<f32>,
pub port_status: Option<char>,
}
impl Rsa {
pub fn parse(fields: &[&str]) -> Option<Self> {
let mut r = FieldReader::new(fields);
Some(Self {
starboard_angle: r.f32(),
starboard_status: r.char(),
port_angle: r.f32(),
port_status: r.char(),
})
}
}
impl NmeaEncodable for Rsa {
const SENTENCE_TYPE: &str = "RSA";
fn encode(&self) -> Vec<String> {
let mut w = FieldWriter::new();
w.f32(self.starboard_angle);
w.char(self.starboard_status);
w.f32(self.port_angle);
w.char(self.port_status);
w.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parse_frame;
#[test]
fn rsa_dual_rudder_gonmea() {
let frame = parse_frame("$IIRSA,10.5,A,0.4,A*70").expect("valid go-nmea RSA frame");
let rsa = Rsa::parse(&frame.fields).expect("parse RSA");
assert!((rsa.starboard_angle.expect("stbd") - 10.5).abs() < 0.1);
assert_eq!(rsa.starboard_status, Some('A'));
assert!((rsa.port_angle.expect("port") - 0.4).abs() < 0.1);
assert_eq!(rsa.port_status, Some('A'));
}
#[test]
fn rsa_empty() {
let f = Rsa {
starboard_angle: None,
starboard_status: None,
port_angle: None,
port_status: None,
}
.to_sentence("II");
let frame = parse_frame(f.trim()).expect("valid");
let r = Rsa::parse(&frame.fields).expect("parse");
assert!(r.starboard_angle.is_none());
assert!(r.starboard_status.is_none());
assert!(r.port_angle.is_none());
assert!(r.port_status.is_none());
}
#[test]
fn rsa_encode_roundtrip() {
let original = Rsa {
starboard_angle: Some(10.5),
starboard_status: Some('A'),
port_angle: Some(-5.2),
port_status: Some('A'),
};
let sentence = original.to_sentence("II");
let frame = parse_frame(sentence.trim()).expect("re-parse");
let parsed = Rsa::parse(&frame.fields).expect("re-parse RSA");
assert_eq!(original, parsed);
}
#[test]
fn rsa_starboard_only() {
let frame = parse_frame("$IIRSA,10.5,A,,V*4D").expect("valid RSA frame");
let rsa = Rsa::parse(&frame.fields).expect("parse RSA");
assert!((rsa.starboard_angle.expect("stbd") - 10.5).abs() < 0.1);
assert_eq!(rsa.starboard_status, Some('A'));
assert!(rsa.port_angle.is_none());
assert_eq!(rsa.port_status, Some('V'));
}
}