211 lines
5.6 KiB
Rust
211 lines
5.6 KiB
Rust
use std::convert::TryFrom;
|
|
|
|
use chrono::{DateTime, Utc};
|
|
use xml::attribute::OwnedAttribute;
|
|
|
|
use crate::dsn::error::ParseError;
|
|
|
|
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, Eq, PartialEq)]
|
|
pub enum SignalType {
|
|
Data,
|
|
Carrier,
|
|
None,
|
|
Unkown(String),
|
|
}
|
|
|
|
impl From<String> for SignalType {
|
|
fn from(s: String) -> Self {
|
|
match s.to_lowercase().as_str() {
|
|
"data" => SignalType::Data,
|
|
"carrier" => SignalType::Carrier,
|
|
"none" => SignalType::None,
|
|
_ => SignalType::Unkown(s),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SignalType {
|
|
fn default() -> Self {
|
|
SignalType::None
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct Signal {
|
|
pub signal_type: SignalType,
|
|
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 = SignalType::from(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 {
|
|
pub name: String,
|
|
pub id: u32,
|
|
/// Up Leg Range (km)
|
|
pub upleg_range: f64,
|
|
/// Down Leg Leg Range (km)
|
|
pub downleg_range: f64,
|
|
/// Round trip light time (s)
|
|
pub 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: Vec<Signal>,
|
|
pub down_signal: Vec<Signal>,
|
|
pub target: Vec<Target>,
|
|
}
|
|
|
|
impl Dish {
|
|
pub fn add_up_signal(mut self, signal: Signal) -> Self {
|
|
self.up_signal.push(signal);
|
|
self
|
|
}
|
|
|
|
pub fn add_down_signal(mut self, signal: Signal) -> Self {
|
|
self.down_signal.push(signal);
|
|
self
|
|
}
|
|
|
|
pub fn add_target(mut self, target: Target) -> Self {
|
|
self.target.push(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: Vec::new(),
|
|
down_signal: Vec::new(),
|
|
target: Vec::new(),
|
|
})
|
|
}
|
|
}
|