Threading and refactoring

+ Add a thread to query the DSN
+ Added a config
+ Moved some code around
main
Joey Hines 2021-06-13 14:44:58 -06:00
parent 596dcb493f
commit 3729fd87f0
No known key found for this signature in database
GPG Key ID: 80F567B5C968F91B
8 changed files with 372 additions and 70 deletions

204
Cargo.lock generated
View File

@ -1,5 +1,20 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "autocfg"
version = "1.0.1"
@ -24,6 +39,12 @@ version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.0.1"
@ -50,12 +71,28 @@ checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"serde",
"num-traits 0.2.14",
"serde 1.0.126",
"time",
"winapi",
]
[[package]]
name = "config"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369"
dependencies = [
"lazy_static",
"nom",
"rust-ini",
"serde 1.0.126",
"serde-hjson",
"serde_json",
"toml",
"yaml-rust",
]
[[package]]
name = "core-foundation"
version = "0.9.1"
@ -77,10 +114,22 @@ name = "dsn-visualizer"
version = "0.1.0"
dependencies = [
"chrono",
"config",
"reqwest",
"rpi-led-matrix",
"serde 1.0.126",
"xml-rs",
]
[[package]]
name = "embedded-graphics"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40a69991ceb896bd4810a0cf2bcc46fc94b7860573c71f965d8e5b3d66942fed"
dependencies = [
"byteorder",
]
[[package]]
name = "encoding_rs"
version = "0.8.28"
@ -170,6 +219,12 @@ dependencies = [
"slab",
]
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
[[package]]
name = "getrandom"
version = "0.2.3"
@ -334,12 +389,31 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lexical-core"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
dependencies = [
"arrayvec",
"bitflags",
"cfg-if",
"ryu",
"static_assertions",
]
[[package]]
name = "libc"
version = "0.2.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc"
[[package]]
name = "linked-hash-map"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "log"
version = "0.4.14"
@ -407,6 +481,17 @@ dependencies = [
"tempfile",
]
[[package]]
name = "nom"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
"lexical-core",
"memchr",
"version_check",
]
[[package]]
name = "ntapi"
version = "0.3.6"
@ -423,7 +508,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
"num-traits 0.2.14",
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
"num-traits 0.2.14",
]
[[package]]
@ -581,6 +675,23 @@ dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
@ -613,7 +724,7 @@ dependencies = [
"native-tls",
"percent-encoding",
"pin-project-lite",
"serde",
"serde 1.0.126",
"serde_urlencoded",
"tokio",
"tokio-native-tls",
@ -624,6 +735,23 @@ dependencies = [
"winreg",
]
[[package]]
name = "rpi-led-matrix"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b27442bb974a0fa23b9e6d630490679c3020ac1037c229c666e144d09d883b5"
dependencies = [
"embedded-graphics",
"gcc",
"libc",
]
[[package]]
name = "rust-ini"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
[[package]]
name = "ryu"
version = "1.0.5"
@ -663,11 +791,43 @@ dependencies = [
"libc",
]
[[package]]
name = "serde"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
[[package]]
name = "serde"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde-hjson"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
dependencies = [
"lazy_static",
"num-traits 0.1.43",
"regex",
"serde 0.8.23",
]
[[package]]
name = "serde_derive"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
@ -677,7 +837,7 @@ checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
dependencies = [
"itoa",
"ryu",
"serde",
"serde 1.0.126",
]
[[package]]
@ -689,7 +849,7 @@ dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
"serde 1.0.126",
]
[[package]]
@ -708,6 +868,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "1.0.73"
@ -798,6 +964,15 @@ dependencies = [
"tokio",
]
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde 1.0.126",
]
[[package]]
name = "tower-service"
version = "0.3.1"
@ -872,6 +1047,12 @@ version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa"
[[package]]
name = "version_check"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "want"
version = "0.3.0"
@ -895,7 +1076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
dependencies = [
"cfg-if",
"serde",
"serde 1.0.126",
"serde_json",
"wasm-bindgen-macro",
]
@ -1002,3 +1183,12 @@ name = "xml-rs"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]

View File

@ -9,4 +9,7 @@ edition = "2018"
[dependencies]
reqwest = {version = "0.11", features=["blocking"]}
chrono = {version = "0.4.19", features=["serde"]}
xml-rs = "0.8.3"
xml-rs = "0.8.3"
config = "0.11.0"
serde = {version = "1.0", features=["derive"]}
rpi-led-matrix = "0.2.2"

3
config.toml 100644
View File

@ -0,0 +1,3 @@
dsn_address = "https://eyes.nasa.gov/dsn/data/dsn.xml"
polling_rate = 5
spacecraft = []

24
src/config/mod.rs 100644
View File

@ -0,0 +1,24 @@
use serde::Deserialize;
use config::{Config, ConfigError, File};
#[derive(Debug, Deserialize, Clone)]
pub struct SpacecraftConfig {
pub spacecraft_name: String,
pub spacecraft_id: u64,
pub color: (u8, u8, u8)
}
#[derive(Debug, Deserialize, Clone)]
pub struct VisualizerConfig {
pub dsn_address: String,
pub polling_rate: u64,
pub spacecraft: Vec<SpacecraftConfig>
}
impl VisualizerConfig {
pub fn new(config_path: &str) -> Result<Self,ConfigError> {
let mut cfg = Config::new();
cfg.merge(File::with_name(config_path))?;
cfg.try_into()
}
}

75
src/dsn/error.rs 100644
View File

@ -0,0 +1,75 @@
use std::num::{ParseFloatError, ParseIntError};
use std::str::ParseBoolError;
#[derive(Debug)]
pub enum ParseError {
AttrMissing,
ParseIntErr(ParseIntError),
ParseFloatErr(ParseFloatError),
ParseBoolErr(ParseBoolError),
ParseChronoErr(chrono::ParseError),
}
impl From<ParseIntError> for ParseError {
fn from(error: ParseIntError) -> Self {
ParseError::ParseIntErr(error)
}
}
impl From<ParseFloatError> for ParseError {
fn from(error: ParseFloatError) -> Self {
ParseError::ParseFloatErr(error)
}
}
impl From<ParseBoolError> for ParseError {
fn from(error: ParseBoolError) -> Self {
ParseError::ParseBoolErr(error)
}
}
impl From<chrono::ParseError> for ParseError {
fn from(error: chrono::ParseError) -> Self {
ParseError::ParseChronoErr(error)
}
}
impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseError::AttrMissing => write!(f, "Attr missing"),
ParseError::ParseIntErr(e) => write!(f, "Int parse error: {}", e),
ParseError::ParseFloatErr(e) => write!(f, "Int parse error: {}", e),
ParseError::ParseBoolErr(e) => write!(f, "Bool parse error: {}", e),
ParseError::ParseChronoErr(e) => write!(f, "Chrono parse error: {}", e),
}
}
}
#[derive(Debug)]
pub enum DSNError {
ParseErr(ParseError),
ReqwestErr(reqwest::Error)
}
impl From<ParseError> for DSNError {
fn from(err: ParseError) -> Self {
DSNError::ParseErr(err)
}
}
impl From<reqwest::Error> for DSNError {
fn from(err: reqwest::Error) -> Self {
DSNError::ReqwestErr(err)
}
}
impl std::fmt::Display for DSNError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DSNError::ParseErr(e) => write!(f, "Req Parse Error: {}", e),
DSNError::ReqwestErr(e) => write!(f, "Reqwest Error: {}", e)
}
}
}

View File

@ -1,10 +1,40 @@
use crate::dsn::models::{Dish, ParseError, Signal, Station, Target};
use std::collections::HashMap;
use std::convert::TryFrom;
use std::io::BufReader;
use xml::reader::XmlEvent;
use std::time::{SystemTime, UNIX_EPOCH};
use reqwest::blocking::Client;
use xml::EventReader;
use xml::reader::XmlEvent;
use error::ParseError;
use crate::dsn::models::{Dish, Signal, Station, Target};
use crate::dsn::error::DSNError;
pub mod models;
pub mod error;
pub fn dsn_request(client: &Client, dsn_api_url: &str) -> Result<Vec<Station>, DSNError> {
let mut params = HashMap::new();
let timestamp = (SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis()
/ 5000) as u64;
params.insert("r", timestamp);
let resp = client
.get(dsn_api_url)
.query(&params)
.send()?
.text()?;
let file = BufReader::new(resp.as_bytes());
Ok(parse_dsn_resp(file)?)
}
pub fn parse_dsn_resp<T>(reader: BufReader<T>) -> Result<Vec<Station>, ParseError>
where

View File

@ -1,42 +1,9 @@
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)
}
}
use crate::dsn::error::ParseError;
fn get_attr(attrs: &[OwnedAttribute], name: &str) -> Result<String, ParseError> {
attrs

View File

@ -1,35 +1,45 @@
use crate::dsn::parse_dsn_resp;
use crate::dsn::dsn_request;
use reqwest::blocking::Client;
use std::collections::HashMap;
use std::io::BufReader;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::config::VisualizerConfig;
use std::sync::mpsc;
use std::time::Duration;
use crate::dsn::models::Station;
mod dsn;
mod config;
fn main() {
fn dsn_thread(config: VisualizerConfig, tx: mpsc::Sender<Vec<Station>>) {
let client = Client::new();
let sleep_duration = Duration::from_secs(config.polling_rate);
let mut params = HashMap::new();
let timestamp = (SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis()
/ 5000) as u64;
params.insert("r", timestamp);
loop {
match dsn_request(&client, &config.dsn_address) {
Ok(stations) => {
if tx.send(stations).is_err() {
break;
}
}
Err(e) => {
println!("Unable to fetch DSN status: {}", e)
}
}
let resp = client
.get("https://eyes.nasa.gov/dsn/data/dsn.xml")
.query(&params)
.send()
.unwrap()
.text()
.unwrap();
let file = BufReader::new(resp.as_bytes());
let stations = parse_dsn_resp(file).unwrap();
for station in stations {
println!("Station: {:?}\n Dishes: {:?}", station.name, station.dishes)
std::thread::sleep(sleep_duration);
}
}
fn main() {
let (tx,rx) = mpsc::channel::<Vec<Station>>();
let config = VisualizerConfig::new("config.toml").unwrap();
std::thread::spawn(move || dsn_thread(config, tx));
loop {
let stations = rx.recv().unwrap();
for station in stations {
println!("Station: {:?}\n Dishes: {:?}", station.name, station.dishes)
}
}
}