use crate::commands::dtm::DTM;
use crate::commands::gbs::GBS;
use crate::commands::gga::GGA;
use crate::commands::gll::GLL;
use crate::commands::gns::GNS;
use crate::commands::gsa::GSA;
use crate::commands::gsv::GSVPage;
use crate::commands::rmc::RMC;
use crate::commands::vtg::VTG;
use core::num;
#[derive(Debug, Clone, PartialEq)]
pub enum Error {
ParseError(String),
UnknownCommand(String),
ChecksumError(u8, u8),
}
impl From<num::ParseIntError> for Error {
fn from(e: num::ParseIntError) -> Error {
Error::ParseError(format!("ParseIntError {}", e))
}
}
impl From<num::ParseFloatError> for Error {
fn from(e: num::ParseFloatError) -> Error {
Error::ParseError(format!("ParseFloatError {}", e))
}
}
pub(crate) trait Command<T> {
fn parse_command(&self, command: Vec<String>) -> Result<T, Error>;
}
#[derive(Debug, Clone, PartialEq)]
pub enum CommandTypes {
GGA(GGA),
GSV(GSVPage),
GLL(GLL),
GSA(GSA),
RMC(RMC),
VTG(VTG),
DTM(DTM),
GBS(GBS),
GNS(GNS),
}
impl CommandTypes {
pub(crate) fn from_str(s: &str) -> Result<CommandTypes, &str> {
match s {
"GGA" => Ok(CommandTypes::GGA(GGA::default())),
"GSV" => Ok(CommandTypes::GSV(GSVPage::default())),
"GLL" => Ok(CommandTypes::GLL(GLL::default())),
"GSA" => Ok(CommandTypes::GSA(GSA::default())),
"VTG" => Ok(CommandTypes::VTG(VTG::default())),
"RMC" => Ok(CommandTypes::RMC(RMC::default())),
"DTM" => Ok(CommandTypes::DTM(DTM::default())),
"GBS" => Ok(CommandTypes::GBS(GBS::default())),
"GNS" => Ok(CommandTypes::GNS(GNS::default())),
_ => Err("Invalid command type"),
}
}
pub(crate) fn parse_commands(&mut self, command: Vec<String>) -> Result<CommandTypes, Error> {
match self {
CommandTypes::GGA(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::GGA(e.clone())),
Err(e) => Err(e),
},
CommandTypes::GSV(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::GSV(e.clone())),
Err(e) => Err(e),
},
CommandTypes::GLL(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::GLL(e.clone())),
Err(e) => Err(e),
},
CommandTypes::GSA(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::GSA(e.clone())),
Err(e) => Err(e),
},
CommandTypes::VTG(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::VTG(e.clone())),
Err(e) => Err(e),
},
CommandTypes::RMC(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::RMC(e.clone())),
Err(e) => Err(e),
},
CommandTypes::DTM(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::DTM(e.clone())),
Err(e) => Err(e),
},
CommandTypes::GBS(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::GBS(e.clone())),
Err(e) => Err(e),
},
CommandTypes::GNS(e) => match e.parse_command(command) {
Ok(e) => Ok(CommandTypes::GNS(e.clone())),
Err(e) => Err(e),
},
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Status {
Valid,
Invalid,
}
impl Status {
pub(crate) fn from_str(s: &str) -> Result<Status, &str> {
match s {
"A" => Ok(Status::Valid),
"V" => Ok(Status::Invalid),
_ => Err("Invalid status"),
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Time {
pub hour: u8,
pub minute: u8,
pub second: u8,
pub decimal_seconds: u8,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Date {
pub year: usize,
pub month: u8,
pub day: u8,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Cordinate {
pub degree: usize,
pub minute: f64,
}
#[derive(Debug, Clone, PartialEq)]
pub enum GGAStatus {
Invalid,
S2d3D,
Dgnss,
FixedRtk,
FloatRtk,
DeadReckoning,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ModeIndicator {
NoFix,
Autonomous,
Differential,
Precise,
RealTime,
FloatRtk,
Estimate,
Manual,
Simulation,
}
impl ModeIndicator {
pub(crate) fn from_str(s: &str) -> Result<ModeIndicator, &str> {
match s {
"N" => Ok(ModeIndicator::NoFix),
"A" => Ok(ModeIndicator::Autonomous),
"D" => Ok(ModeIndicator::Differential),
"P" => Ok(ModeIndicator::Precise),
"R" => Ok(ModeIndicator::RealTime),
"F" => Ok(ModeIndicator::FloatRtk),
"E" => Ok(ModeIndicator::Estimate),
"M" => Ok(ModeIndicator::Manual),
"S" => Ok(ModeIndicator::Simulation),
_ => Err("Invalid mode indicator"),
}
}
pub(crate) fn from_char(s: char) -> Option<ModeIndicator> {
match s {
'N' => Some(ModeIndicator::NoFix),
'A' => Some(ModeIndicator::Autonomous),
'D' => Some(ModeIndicator::Differential),
'P' => Some(ModeIndicator::Precise),
'R' => Some(ModeIndicator::RealTime),
'F' => Some(ModeIndicator::FloatRtk),
'E' => Some(ModeIndicator::Estimate),
'M' => Some(ModeIndicator::Manual),
'S' => Some(ModeIndicator::Simulation),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum GSAOperationMode {
Manual,
Automatic,
}
impl GSAOperationMode {
pub(crate) fn from_str(s: &str) -> Result<GSAOperationMode, &str> {
match s {
"M" => Ok(GSAOperationMode::Manual),
"A" => Ok(GSAOperationMode::Automatic),
_ => Err("Invalid operation mode"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum NavigationMode {
NoFix,
Fix2D,
Fix3D,
}
impl NavigationMode {
pub(crate) fn from_str(s: &str) -> Result<NavigationMode, &str> {
match s {
"1" => Ok(NavigationMode::NoFix),
"2" => Ok(NavigationMode::Fix2D),
"3" => Ok(NavigationMode::Fix3D),
_ => Err("Invalid navigation mode"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum VTGUnit {
Knots,
Kmh,
Mph,
}
impl VTGUnit {
pub(crate) fn from_str(s: &str) -> Result<VTGUnit, &str> {
match s {
"N" => Ok(VTGUnit::Knots),
"K" => Ok(VTGUnit::Kmh),
"M" => Ok(VTGUnit::Mph),
_ => Err("Invalid VTG unit"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum NavigationalStatus {
Safe,
Caution,
Unsafe,
NotValid,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CardinalDirection {
North,
South,
East,
West,
}
impl CardinalDirection {
pub(crate) fn from_char(s: char) -> Option<CardinalDirection> {
match s {
'N' => Some(CardinalDirection::North),
'S' => Some(CardinalDirection::South),
'E' => Some(CardinalDirection::East),
'W' => Some(CardinalDirection::West),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TalkerIds {
GA,
GB,
GP,
GL,
GN,
GQ,
}
impl TalkerIds {
pub fn is_correct(code: &str) -> bool {
matches!(code, "$GA" | "$GB" | "$GP" | "$GL" | "$GN" | "$GQ")
}
pub fn parse(code: &str) -> TalkerIds {
match code {
"$GA" => TalkerIds::GA,
"$GB" => TalkerIds::GB,
"$GP" => TalkerIds::GP,
"$GL" => TalkerIds::GL,
"$GN" => TalkerIds::GN,
"$GQ" => TalkerIds::GQ,
_ => unreachable!(),
}
}
}