dsn-visualizer/src/dsn/models.rs

219 lines
5.9 KiB
Rust

use std::convert::TryFrom;
use std::num::{ParseFloatError, ParseIntError};
use std::str::ParseBoolError;
use chrono::{DateTime, Utc};
use xml::attribute::OwnedAttribute;
#[derive(Clone, Debug)]
pub enum ParseError {
AttrMissing,
AttrParseInt(ParseIntError),
AttrParseFloat(ParseFloatError),
AttrParseBool(ParseBoolError),
AttrParseChrono(chrono::ParseError),
}
impl From<ParseIntError> for ParseError {
fn from(error: ParseIntError) -> Self {
ParseError::AttrParseInt(error)
}
}
impl From<ParseFloatError> for ParseError {
fn from(error: ParseFloatError) -> Self {
ParseError::AttrParseFloat(error)
}
}
impl From<ParseBoolError> for ParseError {
fn from(error: ParseBoolError) -> Self {
ParseError::AttrParseBool(error)
}
}
impl From<chrono::ParseError> for ParseError {
fn from(error: chrono::ParseError) -> Self {
ParseError::AttrParseChrono(error)
}
}
fn get_attr(attrs: &[OwnedAttribute], name: &str) -> Result<String, ParseError> {
attrs
.iter()
.find_map(|o| {
if o.name.local_name.eq(name) {
Some(o.value.clone())
} else {
None
}
})
.ok_or(ParseError::AttrMissing)
}
#[derive(Clone, Debug)]
pub struct Station {
pub name: String,
pub friendly_name: String,
pub time_utc: u64,
pub tz_offset: i64,
pub dishes: Vec<Dish>,
}
impl Station {
pub fn add_dish(mut self, dish: Dish) -> Self {
self.dishes.push(dish);
self
}
}
impl TryFrom<Vec<OwnedAttribute>> for Station {
type Error = ParseError;
fn try_from(attrs: Vec<OwnedAttribute>) -> Result<Self, Self::Error> {
let name = get_attr(&attrs, "name")?;
let friendly_name = get_attr(&attrs, "friendlyName")?;
let time_utc = get_attr(&attrs, "timeUTC")?.parse::<u64>()?;
let tz_offset = get_attr(&attrs, "timeZoneOffset")?.parse::<i64>()?;
Ok(Self {
name,
friendly_name,
time_utc,
tz_offset,
dishes: Vec::new(),
})
}
}
#[derive(Clone, Debug, Default)]
pub struct Signal {
pub signal_type: String,
pub signal_type_debug: String,
pub data_rate: Option<f64>,
pub frequency: Option<f64>,
pub power: Option<f64>,
pub spacecraft: String,
pub spacecraft_id: Option<u32>,
}
impl TryFrom<Vec<OwnedAttribute>> for Signal {
type Error = ParseError;
fn try_from(attrs: Vec<OwnedAttribute>) -> Result<Self, Self::Error> {
let signal_type = get_attr(&attrs, "signalType")?;
let signal_type_debug = get_attr(&attrs, "signalTypeDebug")?;
let data_rate = get_attr(&attrs, "dataRate")?.parse::<f64>().ok();
let frequency = get_attr(&attrs, "frequency")?.parse::<f64>().ok();
let power = get_attr(&attrs, "power")?.parse::<f64>().ok();
let spacecraft = get_attr(&attrs, "spacecraft")?;
let spacecraft_id = get_attr(&attrs, "spacecraftId")?.parse::<u32>().ok();
Ok(Self {
signal_type,
signal_type_debug,
data_rate,
frequency,
power,
spacecraft,
spacecraft_id,
})
}
}
#[derive(Clone, Debug, Default)]
pub struct Target {
name: String,
id: u32,
/// Up Leg Range (km)
upleg_range: f64,
/// Down Leg Leg Range (km)
downleg_range: f64,
/// Round trip light time (s)
rtlt: f64,
}
impl TryFrom<Vec<OwnedAttribute>> for Target {
type Error = ParseError;
fn try_from(attrs: Vec<OwnedAttribute>) -> Result<Self, Self::Error> {
let name = get_attr(&attrs, "name")?;
let id = get_attr(&attrs, "id")?.parse::<u32>()?;
let upleg_range = get_attr(&attrs, "uplegRange")?.parse::<f64>()?;
let downleg_range = get_attr(&attrs, "downlegRange")?.parse::<f64>()?;
let rtlt = get_attr(&attrs, "rtlt")?.parse::<f64>()?;
Ok(Self {
name,
id,
upleg_range,
downleg_range,
rtlt,
})
}
}
#[derive(Clone, Debug)]
pub struct Dish {
pub name: String,
pub azimuth_angle: Option<f64>,
pub elevation_angle: Option<f64>,
pub wind_speed: Option<f64>,
pub is_mspa: bool,
pub is_array: bool,
pub is_ddor: bool,
pub created: DateTime<Utc>,
pub updated: DateTime<Utc>,
pub up_signal: Signal,
pub down_signal: Signal,
pub target: Target,
}
impl Dish {
pub fn set_up_signal(mut self, signal: Signal) -> Self {
self.up_signal = signal;
self
}
pub fn set_down_signal(mut self, signal: Signal) -> Self {
self.down_signal = signal;
self
}
pub fn set_target(mut self, target: Target) -> Self {
self.target = target;
self
}
}
impl TryFrom<Vec<OwnedAttribute>> for Dish {
type Error = ParseError;
fn try_from(attrs: Vec<OwnedAttribute>) -> Result<Self, Self::Error> {
let name = get_attr(&attrs, "name")?;
let azimuth_angle = get_attr(&attrs, "azimuthAngle")?.parse::<f64>().ok();
let elevation_angle = get_attr(&attrs, "elevationAngle")?.parse::<f64>().ok();
let wind_speed = get_attr(&attrs, "windSpeed")?.parse::<f64>().ok();
let is_mspa = get_attr(&attrs, "isMSPA")?.parse::<bool>()?;
let is_array = get_attr(&attrs, "isArray")?.parse::<bool>()?;
let is_ddor = get_attr(&attrs, "isDDOR")?.parse::<bool>()?;
let created = get_attr(&attrs, "created")?.parse::<DateTime<Utc>>()?;
let updated = get_attr(&attrs, "updated")?.parse::<DateTime<Utc>>()?;
Ok(Self {
name,
azimuth_angle,
elevation_angle,
wind_speed,
is_mspa,
is_array,
is_ddor,
created,
updated,
up_signal: Signal::default(),
down_signal: Signal::default(),
target: Target::default(),
})
}
}