use crate::ParseError;
#[derive(Clone, Debug, PartialEq)]
pub enum MtMessageType {
Test,
Alert,
Unknown
}
impl std::convert::From<char> for MtMessageType {
fn from(c: char) -> Self {
match c {
'T' => MtMessageType::Test,
'A' => MtMessageType::Alert,
_ => MtMessageType::Unknown,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MtStructured {
pub header: String,
pub id: String,
pub sequence_number: usize,
pub message_type: MtMessageType,
pub format_flag: char,
pub beacon: String,
pub signal_strength: [char; 2],
pub lat_degrees: u8,
pub lat_minutes: u8,
pub lat_seconds: u8,
pub n: char,
pub long_degrees: u16,
pub long_minutes: u8,
pub long_seconds: u8,
pub w: char,
pub checksum: u16,
}
pub fn is_mt(message: &str) -> bool {
return message.starts_with("MT1");
}
pub fn parse(message: &str) -> Result<MtStructured, ParseError> {
const MT1_LEN: usize = 47;
if message.len() != MT1_LEN {
return Err(ParseError::SizeNotMatch {
expected: MT1_LEN,
found: message.len(),
});
}
let header = message[0..3].to_string();
let id = message[3..6].to_string();
let sequence_number = message[6..9].parse::<usize>()?;
let message_type = (message.as_bytes()[9] as char).into();
let format_flag = message.as_bytes()[10] as char;
let beacon = message[11..26].to_string();
let signal_strength = [
message.as_bytes()[26] as char,
message.as_bytes()[27] as char,
];
let lat_degrees = message[28..30].parse::<u8>()?;
let lat_minutes = message[30..32].parse::<u8>()?;
let lat_seconds = message[32..34].parse::<u8>()?;
let n = message.as_bytes()[34] as char;
let long_degrees = message[35..38].parse::<u16>()?;
let long_minutes = message[38..40].parse::<u8>()?;
let long_seconds = message[40..42].parse::<u8>()?;
let w = message.as_bytes()[42] as char;
let checksum = u16::from_str_radix(&message[43..47], 16).unwrap_or(0);
let result = MtStructured {
header,
id,
sequence_number,
message_type,
format_flag,
beacon,
signal_strength,
lat_degrees,
lat_minutes,
lat_seconds,
n,
long_degrees,
long_minutes,
long_seconds,
w,
checksum,
};
Ok(result)
}