Init
This commit is contained in:
commit
56d058c2fd
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
.env
|
1190
Cargo.lock
generated
Normal file
1190
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "satellit-ansage"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dotenv = "0.15.0"
|
||||||
|
reqwest = { version = "0.11.16", features = ["json"] }
|
||||||
|
serde = { version = "1.0.160", features = ["derive"] }
|
||||||
|
serde_json = "1.0.96"
|
||||||
|
tokio = { version = "1.27.0", features = ["full"] }
|
19
src/main.rs
Normal file
19
src/main.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use std::{env, error::Error};
|
||||||
|
|
||||||
|
use crate::n2yo::N2YO;
|
||||||
|
|
||||||
|
mod n2yo;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
dotenv::dotenv().ok();
|
||||||
|
let api_key = env::var("N2YO_API_KEY")?;
|
||||||
|
|
||||||
|
let n2yo = N2YO::new(api_key);
|
||||||
|
|
||||||
|
let tle = n2yo.tle(25544).await?;
|
||||||
|
|
||||||
|
println!("{}", tle.tle);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
199
src/n2yo/mod.rs
Normal file
199
src/n2yo/mod.rs
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
use reqwest::Client;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
use self::proto::{Above, Positions, RadioPasses, VisualPasses, TLE};
|
||||||
|
|
||||||
|
mod proto;
|
||||||
|
|
||||||
|
const BASE_URL: &str = "https://api.n2yo.com/rest/v1/satellite";
|
||||||
|
|
||||||
|
pub struct N2YO {
|
||||||
|
api_key: String,
|
||||||
|
client: Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
impl N2YO {
|
||||||
|
pub fn new(api_key: String) -> Self {
|
||||||
|
Self {
|
||||||
|
api_key,
|
||||||
|
client: Client::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn query<T: DeserializeOwned>(&self, s: &str) -> Result<T> {
|
||||||
|
let result = self
|
||||||
|
.client
|
||||||
|
.get(s)
|
||||||
|
.query(&[("apiKey", &self.api_key)])
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get TLE
|
||||||
|
///
|
||||||
|
/// Retrieve the Two Line Elements (TLE) for a satellite identified by NORAD id.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn tle(&self, id: u64) -> Result<TLE> {
|
||||||
|
self.query(&format!("{BASE_URL}/tle/{id}")).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get satellite positions
|
||||||
|
///
|
||||||
|
/// Retrieve the future positions of any satellite as groundtrack (latitude, longitude) to display
|
||||||
|
/// orbits on maps. Also return the satellite's azimuth and elevation with respect to the observer
|
||||||
|
/// location. Each element in the response array is one second of calculation. First element is
|
||||||
|
/// calculated for current UTC time.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn positions(
|
||||||
|
&self,
|
||||||
|
id: u64,
|
||||||
|
lat: f64,
|
||||||
|
lng: f64,
|
||||||
|
alt: f64,
|
||||||
|
seconds: u16,
|
||||||
|
) -> Result<Positions> {
|
||||||
|
self.query(&format!(
|
||||||
|
"{BASE_URL}/positions/{id}/{lat}/{lng}/{alt}/{seconds}"
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get visual passes
|
||||||
|
///
|
||||||
|
/// Get predicted visual passes for any satellite relative to a location on Earth. A "visual pass"
|
||||||
|
/// is a pass that should be optically visible on the entire (or partial) duration of crossing the
|
||||||
|
/// sky. For that to happen, the satellite must be above the horizon, illumintaed by Sun (not in
|
||||||
|
/// Earth shadow), and the sky dark enough to allow visual satellite observation.
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn visual_passes(
|
||||||
|
&self,
|
||||||
|
id: u64,
|
||||||
|
lat: f64,
|
||||||
|
lng: f64,
|
||||||
|
alt: f64,
|
||||||
|
days: u8,
|
||||||
|
min_visibility: u64,
|
||||||
|
) -> Result<VisualPasses> {
|
||||||
|
self.query(&format!(
|
||||||
|
"{BASE_URL}/positions/{id}/{lat}/{lng}/{alt}/{days}/{min_visibility}"
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get radio passes
|
||||||
|
///
|
||||||
|
/// The "radio passes" are similar to "visual passes", the only difference being the requirement
|
||||||
|
/// for the objects to be optically visible for observers. This function is useful mainly for
|
||||||
|
/// predicting satellite passes to be used for radio communications. The quality of the pass depends
|
||||||
|
/// essentially on the highest elevation value during the pass, which is one of the input parameters.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn radio_passes(
|
||||||
|
&self,
|
||||||
|
id: u64,
|
||||||
|
lat: f64,
|
||||||
|
lng: f64,
|
||||||
|
alt: f64,
|
||||||
|
days: u8,
|
||||||
|
min_elevation: u64,
|
||||||
|
) -> Result<RadioPasses> {
|
||||||
|
self.query(&format!(
|
||||||
|
"{BASE_URL}/positions/{id}/{lat}/{lng}/{alt}/{days}/{min_elevation}"
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// What's up?
|
||||||
|
///
|
||||||
|
/// The "above" function will return all objects within a given search radius above observer's location.
|
||||||
|
/// The radius (θ), expressed in degrees, is measured relative to the point in the sky directly above
|
||||||
|
/// an observer (azimuth). This image may offer a better explanation:
|
||||||
|
///
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// The search radius range is 0 to 90 degrees, nearly 0 meaning to show only satellites passing exactly
|
||||||
|
/// above the observer location, while 90 degrees to return all satellites above the horizon. Since there
|
||||||
|
/// are many satellites and debris in the sky at any point in time, the result could be filtered by
|
||||||
|
/// satellite category (integer). The following categories are currently available at n2yo.com:
|
||||||
|
///
|
||||||
|
/// | Category | id |
|
||||||
|
/// |----------|---:|
|
||||||
|
/// |Amateur radio|18|
|
||||||
|
/// |Beidou Navigation System|35|
|
||||||
|
/// |Brightest|1|
|
||||||
|
/// |Celestis|45|
|
||||||
|
/// |Chinese Space Station|54|
|
||||||
|
/// |CubeSats|32|
|
||||||
|
/// |Disaster monitoring|8|
|
||||||
|
/// |Earth resources|6|
|
||||||
|
/// |Education|29|
|
||||||
|
/// |Engineering|28|
|
||||||
|
/// |Experimental|19|
|
||||||
|
/// |Flock|48|
|
||||||
|
/// |Galileo|22|
|
||||||
|
/// |Geodetic|27|
|
||||||
|
/// |Geostationary|10|
|
||||||
|
/// |Global Positioning System (GPS) Constellation|50|
|
||||||
|
/// |Global Positioning System (GPS) Operational|20|
|
||||||
|
/// |Globalstar|17|
|
||||||
|
/// |Glonass Constellation|51|
|
||||||
|
/// |Glonass Operational|21|
|
||||||
|
/// |GOES|5|
|
||||||
|
/// |Gonets|40|
|
||||||
|
/// |Gorizont|12|
|
||||||
|
/// |Intelsat|11|
|
||||||
|
/// |Iridium|15|
|
||||||
|
/// IRNSS|46|
|
||||||
|
/// ISS|2|
|
||||||
|
/// Lemur|49|
|
||||||
|
/// Military|30|
|
||||||
|
/// Molniya|14|
|
||||||
|
/// Navy Navigation Satellite System|24|
|
||||||
|
/// NOAA|4|
|
||||||
|
/// O3B Networks|43|
|
||||||
|
/// OneWeb|53|
|
||||||
|
/// Orbcomm|16|
|
||||||
|
/// Parus|38|
|
||||||
|
/// QZSS|47|
|
||||||
|
/// Radar Calibration|31|
|
||||||
|
/// Raduga|13|
|
||||||
|
/// Russian LEO Navigation|25|
|
||||||
|
/// Satellite-Based Augmentation System|23|
|
||||||
|
/// Search & rescue|7|
|
||||||
|
/// Space & Earth Science|26|
|
||||||
|
/// Starlink|52|
|
||||||
|
/// Strela|39|
|
||||||
|
/// Tracking and Data Relay Satellite System|9|
|
||||||
|
/// Tselina|44|
|
||||||
|
/// Tsikada|42|
|
||||||
|
/// Tsiklon|41|
|
||||||
|
/// TV|34|
|
||||||
|
/// Weather|3|
|
||||||
|
/// Westford Needles|37|
|
||||||
|
/// XM and Sirius|33|
|
||||||
|
/// Yaogan|36|
|
||||||
|
///
|
||||||
|
/// Please use this function responsably as there is a lot of CPU needed in order to calculate exact
|
||||||
|
/// positions for all satellites in the sky. The function will return altitude, latitude and longitude
|
||||||
|
/// of satellites footprints to be displayed on a map, and some minimal information to identify the object.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub async fn above(
|
||||||
|
&self,
|
||||||
|
lat: f64,
|
||||||
|
lng: f64,
|
||||||
|
alt: f64,
|
||||||
|
search_radius: u8,
|
||||||
|
category_id: u8,
|
||||||
|
) -> Result<Above> {
|
||||||
|
self.query(&format!(
|
||||||
|
"{BASE_URL}/above/{lat}/{lng}/{alt}/{search_radius}/{category_id}"
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
472
src/n2yo/proto.rs
Normal file
472
src/n2yo/proto.rs
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
#![allow(clippy::upper_case_acronyms)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Info {
|
||||||
|
/// NORAD id used in input
|
||||||
|
#[serde(rename = "satid")]
|
||||||
|
pub sat_id: u64,
|
||||||
|
|
||||||
|
/// Satellite name
|
||||||
|
#[serde(rename = "satname")]
|
||||||
|
pub sat_name: String,
|
||||||
|
|
||||||
|
/// Count of transactions performed with this API key in last 60 minutes
|
||||||
|
#[serde(rename = "transactionscount")]
|
||||||
|
pub transaction_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct TLE {
|
||||||
|
pub info: Info,
|
||||||
|
/// TLE on single line string. Split the line in two by \r\n to get original two lines
|
||||||
|
pub tle: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Positions {
|
||||||
|
pub info: Info,
|
||||||
|
pub positions: Vec<Position>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Position {
|
||||||
|
/// Satellite footprint latitude (decimal degrees format)
|
||||||
|
#[serde(rename = "satlatitude")]
|
||||||
|
pub sat_latitude: f64,
|
||||||
|
|
||||||
|
/// Satellite footprint longitude (decimal degrees format)
|
||||||
|
#[serde(rename = "satlongitude")]
|
||||||
|
pub sat_longitude: f64,
|
||||||
|
|
||||||
|
#[serde(rename = "sataltitude")]
|
||||||
|
pub sat_altitude: f64,
|
||||||
|
|
||||||
|
/// Satellite azimuth with respect to observer's location (degrees)
|
||||||
|
pub azimuth: f64,
|
||||||
|
|
||||||
|
/// Satellite elevation with respect to observer's location (degrees)
|
||||||
|
pub elevation: f64,
|
||||||
|
|
||||||
|
/// Satellite right ascension (degrees)
|
||||||
|
pub ra: f64,
|
||||||
|
|
||||||
|
/// Satellite declination (degrees)
|
||||||
|
pub dec: f64,
|
||||||
|
|
||||||
|
/// Unix time for this position (seconds). You should convert this UTC value to observer's time zone
|
||||||
|
pub timestamp: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct PassInfo {
|
||||||
|
/// NORAD id used in input
|
||||||
|
#[serde(rename = "satid")]
|
||||||
|
pub sat_id: u64,
|
||||||
|
|
||||||
|
/// Satellite name
|
||||||
|
#[serde(rename = "satname")]
|
||||||
|
pub sat_name: String,
|
||||||
|
|
||||||
|
/// Count of transactions performed with this API key in last 60 minutes
|
||||||
|
#[serde(rename = "transactionscount")]
|
||||||
|
pub transaction_count: u64,
|
||||||
|
|
||||||
|
/// Count of passes returned
|
||||||
|
#[serde(rename = "passescount")]
|
||||||
|
pub pass_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub enum Compass {
|
||||||
|
N,
|
||||||
|
NNE,
|
||||||
|
NE,
|
||||||
|
ENE,
|
||||||
|
E,
|
||||||
|
ESE,
|
||||||
|
SE,
|
||||||
|
SSE,
|
||||||
|
S,
|
||||||
|
SSW,
|
||||||
|
SW,
|
||||||
|
WSW,
|
||||||
|
W,
|
||||||
|
WNW,
|
||||||
|
NW,
|
||||||
|
NNW,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct VisualPasses {
|
||||||
|
pub info: PassInfo,
|
||||||
|
pub passes: Option<Vec<VisualPass>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct VisualPass {
|
||||||
|
// start
|
||||||
|
/// Satellite azimuth for the start of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "startAz")]
|
||||||
|
pub start_az: f64,
|
||||||
|
|
||||||
|
/// Satellite azimuth for the start of this pass (relative to the observer). Possible values: N, NE, E, SE, S, SW, W, NW
|
||||||
|
#[serde(rename = "startAzCompass")]
|
||||||
|
pub start_az_compass: Compass,
|
||||||
|
|
||||||
|
/// Satellite elevation for the start of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "startEl")]
|
||||||
|
pub start_el: f64,
|
||||||
|
|
||||||
|
/// Unix time for the start of this pass. You should convert this UTC value to observer's time zone
|
||||||
|
#[serde(rename = "startUTC")]
|
||||||
|
pub start_utc: u64,
|
||||||
|
|
||||||
|
// max
|
||||||
|
/// Satellite azimuth for the max elevation of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "maxAz")]
|
||||||
|
pub max_az: f64,
|
||||||
|
|
||||||
|
/// Satellite azimuth for the max elevation of this pass (relative to the observer). Possible values: N, NE, E, SE, S, SW, W, NW
|
||||||
|
#[serde(rename = "maxAzCompass")]
|
||||||
|
pub max_az_compass: Compass,
|
||||||
|
|
||||||
|
/// Satellite max elevation for this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "maxEl")]
|
||||||
|
pub max_el: f64,
|
||||||
|
|
||||||
|
/// Unix time for the max elevation of this pass. You should convert this UTC value to observer's time zone
|
||||||
|
#[serde(rename = "maxUTC")]
|
||||||
|
pub max_utc: u64,
|
||||||
|
|
||||||
|
// end
|
||||||
|
/// Satellite azimuth for the end of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "endAz")]
|
||||||
|
pub end_az: f64,
|
||||||
|
|
||||||
|
/// Satellite azimuth for the end of this pass (relative to the observer). Possible values: N, NE, E, SE, S, SW, W, NW
|
||||||
|
#[serde(rename = "endAzCompass")]
|
||||||
|
pub end_az_compass: Compass,
|
||||||
|
|
||||||
|
/// Satellite elevation for the end of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "endEl")]
|
||||||
|
pub end_el: f64,
|
||||||
|
|
||||||
|
/// Unix time for the end of this pass. You should convert this UTC value to observer's time zone
|
||||||
|
#[serde(rename = "endUTC")]
|
||||||
|
pub end_utc: u64,
|
||||||
|
|
||||||
|
/// Max visual magnitude of the pass, same scale as star brightness. If magnitude cannot be determined, the value is 100000
|
||||||
|
pub mag: f64,
|
||||||
|
|
||||||
|
/// Total visible duration of this pass (in seconds)
|
||||||
|
pub duration: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct RadioPasses {
|
||||||
|
pub info: PassInfo,
|
||||||
|
pub passes: Option<Vec<RadioPass>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct RadioPass {
|
||||||
|
// start
|
||||||
|
/// Satellite azimuth for the start of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "startAz")]
|
||||||
|
pub start_az: f64,
|
||||||
|
|
||||||
|
/// Satellite azimuth for the start of this pass (relative to the observer). Possible values: N, NE, E, SE, S, SW, W, NW
|
||||||
|
#[serde(rename = "startAzCompass")]
|
||||||
|
pub start_az_compass: Compass,
|
||||||
|
|
||||||
|
/// Unix time for the start of this pass. You should convert this UTC value to observer's time zone
|
||||||
|
#[serde(rename = "startUTC")]
|
||||||
|
pub start_utc: u64,
|
||||||
|
|
||||||
|
// max
|
||||||
|
/// Satellite azimuth for the max elevation of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "maxAz")]
|
||||||
|
pub max_az: f64,
|
||||||
|
|
||||||
|
/// Satellite azimuth for the max elevation of this pass (relative to the observer). Possible values: N, NE, E, SE, S, SW, W, NW
|
||||||
|
#[serde(rename = "maxAzCompass")]
|
||||||
|
pub max_az_compass: Compass,
|
||||||
|
|
||||||
|
/// Satellite max elevation for this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "maxEl")]
|
||||||
|
pub max_el: f64,
|
||||||
|
|
||||||
|
/// Unix time for the max elevation of this pass. You should convert this UTC value to observer's time zone
|
||||||
|
#[serde(rename = "maxUTC")]
|
||||||
|
pub max_utc: u64,
|
||||||
|
|
||||||
|
// end
|
||||||
|
/// Satellite azimuth for the end of this pass (relative to the observer, in degrees)
|
||||||
|
#[serde(rename = "endAz")]
|
||||||
|
pub end_az: f64,
|
||||||
|
|
||||||
|
/// Satellite azimuth for the end of this pass (relative to the observer). Possible values: N, NE, E, SE, S, SW, W, NW
|
||||||
|
#[serde(rename = "endAzCompass")]
|
||||||
|
pub end_az_compass: Compass,
|
||||||
|
|
||||||
|
/// Unix time for the end of this pass. You should convert this UTC value to observer's time zone
|
||||||
|
#[serde(rename = "endUTC")]
|
||||||
|
pub end_utc: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Above {
|
||||||
|
pub info: AboveInfo,
|
||||||
|
pub above: Option<Vec<AboveSat>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct AboveInfo {
|
||||||
|
/// Category name (ANY if category id requested was 0)
|
||||||
|
pub category: String,
|
||||||
|
|
||||||
|
/// Count of transactions performed with this API key in last 60 minutes
|
||||||
|
#[serde(rename = "transactionscount")]
|
||||||
|
pub transaction_count: u64,
|
||||||
|
|
||||||
|
/// Count of satellites returned
|
||||||
|
#[serde(rename = "satcount")]
|
||||||
|
pub sat_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct AboveSat {
|
||||||
|
/// Satellite NORAD id
|
||||||
|
#[serde(rename = "satid")]
|
||||||
|
pub sat_id: u64,
|
||||||
|
|
||||||
|
/// Satellite international designator
|
||||||
|
#[serde(rename = "satname")]
|
||||||
|
pub sat_name: String,
|
||||||
|
|
||||||
|
/// Satellite name
|
||||||
|
#[serde(rename = "intDesignator")]
|
||||||
|
pub int_designator: String,
|
||||||
|
|
||||||
|
/// Satellite launch date (YYYY-MM-DD)
|
||||||
|
#[serde(rename = "launchDate")]
|
||||||
|
pub launch_date: String,
|
||||||
|
|
||||||
|
/// Satellite footprint latitude (decimal degrees format)
|
||||||
|
#[serde(rename = "satlat")]
|
||||||
|
pub sat_lat: f64,
|
||||||
|
|
||||||
|
/// Satellite footprint longitude (decimal degrees format)
|
||||||
|
#[serde(rename = "satlng")]
|
||||||
|
pub sat_lng: f64,
|
||||||
|
|
||||||
|
/// Satellite altitude (km)
|
||||||
|
#[serde(rename = "satalt")]
|
||||||
|
pub sat_alt: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tle() {
|
||||||
|
let data = r#"{
|
||||||
|
"info": {
|
||||||
|
"satid": 25544,
|
||||||
|
"satname": "SPACE STATION",
|
||||||
|
"transactionscount": 4
|
||||||
|
},
|
||||||
|
"tle": "1 25544U 98067A 18077.09047010 .00001878 00000-0 35621-4 0 9999\r\n2 25544 51.6412 112.8495 0001928 208.4187 178.9720 15.54106440104358"
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let parsed = serde_json::from_str::<TLE>(data);
|
||||||
|
assert!(parsed.is_ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_positions() {
|
||||||
|
let data = r#"{
|
||||||
|
"info": {
|
||||||
|
"satname": "SPACE STATION",
|
||||||
|
"satid": 25544,
|
||||||
|
"transactionscount": 5
|
||||||
|
},
|
||||||
|
"positions": [
|
||||||
|
{
|
||||||
|
"satlatitude": -39.90318514,
|
||||||
|
"satlongitude": 158.28897924,
|
||||||
|
"sataltitude": 417.85,
|
||||||
|
"azimuth": 254.31,
|
||||||
|
"elevation": -69.09,
|
||||||
|
"ra": 44.77078138,
|
||||||
|
"dec": -43.99279118,
|
||||||
|
"timestamp": 1521354418
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"satlatitude": -39.86493451,
|
||||||
|
"satlongitude": 158.35261287,
|
||||||
|
"sataltitude": 417.84,
|
||||||
|
"azimuth": 254.33,
|
||||||
|
"elevation": -69.06,
|
||||||
|
"ra": 44.81676119,
|
||||||
|
"dec": -43.98086419,
|
||||||
|
"timestamp": 1521354419
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let parsed = serde_json::from_str::<Positions>(data);
|
||||||
|
assert!(parsed.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_visualpasses() {
|
||||||
|
let data = r#"{
|
||||||
|
"info": {
|
||||||
|
"satid": 25544,
|
||||||
|
"satname": "SPACE STATION",
|
||||||
|
"transactionscount": 4,
|
||||||
|
"passescount": 3
|
||||||
|
},
|
||||||
|
"passes": [
|
||||||
|
{
|
||||||
|
"startAz": 307.21,
|
||||||
|
"startAzCompass": "NW",
|
||||||
|
"startEl": 13.08,
|
||||||
|
"startUTC": 1521368025,
|
||||||
|
"maxAz": 225.45,
|
||||||
|
"maxAzCompass": "SW",
|
||||||
|
"maxEl": 78.27,
|
||||||
|
"maxUTC": 1521368345,
|
||||||
|
"endAz": 132.82,
|
||||||
|
"endAzCompass": "SE",
|
||||||
|
"endEl": 0,
|
||||||
|
"endUTC": 1521368660,
|
||||||
|
"mag": -2.4,
|
||||||
|
"duration": 485
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startAz": 311.56,
|
||||||
|
"startAzCompass": "NW",
|
||||||
|
"startEl": 50.94,
|
||||||
|
"startUTC": 1521451295,
|
||||||
|
"maxAz": 37.91,
|
||||||
|
"maxAzCompass": "NE",
|
||||||
|
"maxEl": 52.21,
|
||||||
|
"maxUTC": 1521451615,
|
||||||
|
"endAz": 118.61,
|
||||||
|
"endAzCompass": "ESE",
|
||||||
|
"endEl": 0,
|
||||||
|
"endUTC": 1521451925,
|
||||||
|
"mag": -2,
|
||||||
|
"duration": 325
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startAz": 291.06,
|
||||||
|
"startAzCompass": "WNW",
|
||||||
|
"startEl": 3.47,
|
||||||
|
"startUTC": 1521457105,
|
||||||
|
"maxAz": 231.58,
|
||||||
|
"maxAzCompass": "SW",
|
||||||
|
"maxEl": 14.75,
|
||||||
|
"maxUTC": 1521457380,
|
||||||
|
"endAz": 170.63,
|
||||||
|
"endAzCompass": "S",
|
||||||
|
"endEl": 0,
|
||||||
|
"endUTC": 1521457650,
|
||||||
|
"mag": -0.1,
|
||||||
|
"duration": 485
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let parsed = serde_json::from_str::<VisualPasses>(data);
|
||||||
|
assert!(parsed.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_radiopasses() {
|
||||||
|
let data = r#"{
|
||||||
|
"info": {
|
||||||
|
"satid": 25544,
|
||||||
|
"satname": "SPACE STATION",
|
||||||
|
"transactionscount": 2,
|
||||||
|
"passescount": 2
|
||||||
|
},
|
||||||
|
"passes": [
|
||||||
|
{
|
||||||
|
"startAz": 311.57,
|
||||||
|
"startAzCompass": "NW",
|
||||||
|
"startUTC": 1521451295,
|
||||||
|
"maxAz": 37.98,
|
||||||
|
"maxAzCompass": "NE",
|
||||||
|
"maxEl": 52.19,
|
||||||
|
"maxUTC": 1521451615,
|
||||||
|
"endAz": 118.6,
|
||||||
|
"endAzCompass": "ESE",
|
||||||
|
"endUTC": 1521451925
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startAz": 242.34,
|
||||||
|
"startAzCompass": "WSW",
|
||||||
|
"startUTC": 1521600275,
|
||||||
|
"maxAz": 328.03,
|
||||||
|
"maxAzCompass": "NW",
|
||||||
|
"maxEl": 49.59,
|
||||||
|
"maxUTC": 1521600595,
|
||||||
|
"endAz": 47.97,
|
||||||
|
"endAzCompass": "NE",
|
||||||
|
"endUTC": 1521600905
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
let parsed = serde_json::from_str::<RadioPasses>(data);
|
||||||
|
assert!(parsed.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_above() {
|
||||||
|
let data = r#"{
|
||||||
|
"info": {
|
||||||
|
"category": "Amateur radio",
|
||||||
|
"transactionscount": 17,
|
||||||
|
"satcount": 3
|
||||||
|
},
|
||||||
|
"above": [
|
||||||
|
{
|
||||||
|
"satid": 20480,
|
||||||
|
"satname": "JAS 1B (FUJI 2)",
|
||||||
|
"intDesignator": "1990-013C",
|
||||||
|
"launchDate": "1990-02-07",
|
||||||
|
"satlat": 49.5744,
|
||||||
|
"satlng": -96.7081,
|
||||||
|
"satalt": 1227.9326
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"satid": 26609,
|
||||||
|
"satname": "AMSAT OSCAR 40",
|
||||||
|
"intDesignator": "2000-072B",
|
||||||
|
"launchDate": "2000-11-16",
|
||||||
|
"satlat": 5.5105,
|
||||||
|
"satlng": -21.4478,
|
||||||
|
"satalt": 49678.6389
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"satid": 40719,
|
||||||
|
"satname": "DEORBITSAIL",
|
||||||
|
"intDesignator": "2015-032E",
|
||||||
|
"launchDate": "2015-07-10",
|
||||||
|
"satlat": 43.8106,
|
||||||
|
"satlng": -90.3944,
|
||||||
|
"satalt": 657.5516
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
let parsed = serde_json::from_str::<Above>(data);
|
||||||
|
assert!(parsed.is_ok());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user