mod readme;
use moontime::*;
use std::{
env::set_var,
sync::{
Arc,
Mutex
},
};
use serde::{
Serialize,
Deserialize,
};
use spice::SpiceLock;
use axum::{
routing::get,
routing::post,
extract::{
State,
Query,
Json,
},
Router,
};
use lambda_http::{
run ,Error
};
async fn get_readme( ) -> Result<String, String>
{
Ok( format!("\nVersion: {}\nAuthor: {}\nHomepage: {}\n\n{}",
env!("CARGO_PKG_VERSION"),
env!("CARGO_PKG_AUTHORS"),
env!("CARGO_PKG_HOMEPAGE"),
readme::README,
))
}
#[tokio::main]
async fn main() -> Result<(), Error>
{
set_var("AWS_LAMBDA_HTTP_IGNORE_STAGE_IN_PATH", "true");
for (key, value) in std::env::vars() {
println!("{}: {}", key, value);
}
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.with_target(false)
.without_time()
.init();
let cwd = std::env::current_dir().unwrap();
println!("Current directory: {:?}", cwd);
let cwd_contents = std::fs::read_dir(cwd).unwrap();
for entry in cwd_contents {
let entry = entry.unwrap();
println!("{:?}", entry.path());
}
let in_lambda = std::env::var("LAMBDA_TASK_ROOT").is_ok();
let sl = SpiceLock::try_acquire().unwrap();
sl.furnsh("data/latest_leapseconds.tls");
sl.furnsh("data/de440s.bsp");
sl.furnsh("data/moon_pa_de440_200625.bpc");
sl.furnsh("data/moon_de440_200625.tf");
sl.furnsh("data/pck00010.tpc");
let tlskernel =
Arc::new(Mutex::new(sl));
let app : Router
= Router::new()
.route("/s/et", get(get_et_time))
.route("/s/et", post(post_et_time))
.route("/s/moon/solartime", get(moon_get_solar_time))
.route("/s/moon/solartime", post(moon_post_solar_time))
.route("/s/moon/sun/azel", get(moon_get_solar_azel))
.route("/s/moon/sun/azel", post(moon_post_solar_azel))
.route("/s/cadre/solartime", get(cadre_get_solar_time))
.route("/s/cadre/solartime", post(cadre_post_solar_time))
.route("/s/cadre/sun/azel", get(cadre_get_solar_azel))
.route("/s/cadre/sun/azel", post(cadre_post_solar_azel))
.route("/s/readme", get(get_readme))
.route("/s/readme", post(get_readme))
.with_state(tlskernel);
if in_lambda{
println!("Running in AWS Lambda");
std::env::set_var("AWS_LAMBDA_HTTP_IGNORE_STAGE_IN_PATH", "true");
run(app).await
} else {
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
match axum::serve(listener,app).await
{
Ok(_) => {
println!("Server started on port 3000");
Ok(())
},
Err(e) => {
println!("Error starting server: {}", e);
Err(Error::from(e))
}
}
}
}
#[derive(Serialize, Deserialize, Debug)]
struct GetEtTime {
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
#[serde(default = "default_format")]
f: FormatSpecifier,
}
async fn get_et_time(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Query(GetEtTime {t, f}): Query<GetEtTime>
)
-> Result<String, ()>
{
println!("t: {:?}, f: {:?}", t, f);
let res = moontime::get_et(sl_mutex, t);
Ok(moontime::format_as(res,f, Some("et")))
}
#[derive(Serialize, Deserialize, Debug)]
struct EtBody {
#[serde(with = "default_datetime_standard", default = "default_datetime")]
pub t: DateTime,
#[serde(default = "default_format")]
pub f: FormatSpecifier,
}
async fn post_et_time(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Json(EtBody {t, f}): Json<EtBody>
)
-> Result<String, ()>
{
println!("t: {:?}, f: {:?}", t, f);
let res = moontime::get_et(sl_mutex, t);
Ok(moontime::format_as(res,f, Some("et")))
}
#[derive(Serialize, Deserialize, Debug)]
struct MoonSolarTime {
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
#[serde(default = "default_format")]
f: FormatSpecifier,
p: Position,
}
async fn moon_post_solar_time(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Json(MoonSolarTime{f, t, p}): Json<MoonSolarTime>
) -> Result<String, ()>
{
let result = moontime::solar_time(sl_mutex, t, p.to_radians()).unwrap();
Ok(moontime::format_as(result, f, Some("solar time")))
}
async fn moon_get_solar_time(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Query(MoonSolarTime{t, f, p}): Query<MoonSolarTime>,
) -> Result<String, ()>
{
println!("t: {:?}, f: {:?}, p: {:?}", t, f, p);
let result = moontime::solar_time(sl_mutex, t, p).unwrap();
Ok(moontime::format_as(result, f, Some("solar time")))
}
#[derive(Serialize, Deserialize, Debug)]
struct MoonPostSolarAzel {
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
#[serde(default = "default_format")]
f: FormatSpecifier,
#[serde(default = "default_degrees")]
u: UnitSpecifier,
p: Position,
}
async fn moon_post_solar_azel(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Json(MoonPostSolarAzel{t, f, u, p}): Json<MoonPostSolarAzel>
) -> Result<String, ()>
{
println!("function: moon_post_solar_azel");
println!("time: {:?}", t);
println!("format: {:?}", f);
println!("units: {:?}", u);
println!("pos: {:?}", p);
let res = moontime::solar_azel(sl_mutex, t, p);
let res = moontime::translate_to(res, u);
let res = moontime::format_as(res, f, None);
Ok(res)
}
#[derive(Serialize, Deserialize, Debug)]
struct MoonQuerySolarAzel {
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
#[serde(default = "default_format")]
f: FormatSpecifier,
#[serde(default = "default_degrees")]
u: UnitSpecifier,
p: Position,
}
async fn moon_get_solar_azel(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Query(MoonQuerySolarAzel{t, f, u, p}): Query<MoonQuerySolarAzel>
) -> Result<String, ()>
{
println!("function: moon_get_solar_azel");
println!("time: {:?}", t);
println!("format: {:?}", f);
println!("units: {:?}", u);
println!("pos: {:?}", p);
let res = moontime::solar_azel(sl_mutex, t, p);
let res = moontime::translate_to(res, u);
let res = moontime::format_as(res, f, None);
Ok(res)
}
#[derive(Serialize, Deserialize, Debug)]
struct CADREPostSolarTime {
#[serde(default = "default_format")]
f: FormatSpecifier,
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
}
async fn cadre_post_solar_time(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Json(CADREPostSolarTime{f, t}): Json<CADREPostSolarTime>
) -> Result<String, ()>
{
let p = Position::cadre();
println!("t: {:?}, f: {:?}, p: {:?}", t, f, p);
let result = moontime::solar_time(sl_mutex, t, p.to_radians()).unwrap();
Ok(moontime::format_as(result, f,Some("solar time")))
}
#[derive(Serialize, Deserialize, Debug)]
struct CADRESolarTimeQuery{
#[serde(default = "default_format")]
f: FormatSpecifier,
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
}
async fn cadre_get_solar_time(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Query(CADRESolarTimeQuery{t, f}): Query<CADRESolarTimeQuery>,
) -> Result<String, ()>
{
let p = Position::cadre();
println!("t: {:?}, f: {:?}, p: {:?}", t, f, p);
let result = moontime::solar_time(sl_mutex, t, p).unwrap();
Ok(moontime::format_as(result, f,Some("solar time")))
}
#[derive(Serialize, Deserialize, Debug)]
struct CADREPostSolarAzel {
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
#[serde(default = "default_format")]
f: FormatSpecifier,
#[serde(default = "default_degrees")]
u: UnitSpecifier,
}
async fn cadre_post_solar_azel(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Json(CADREPostSolarAzel{t, f, u}): Json<CADREPostSolarAzel>
) -> Result<String, ()>
{
let p = Position::cadre();
println!("time: {:?}", t);
println!("format: {:?}", f);
println!("units: {:?}", u);
println!("pos: {:?}", p);
let res = moontime::solar_azel(sl_mutex, t, p);
let res = moontime::translate_to(res, u);
let res = moontime::format_as(res, f, None);
Ok(res)
}
#[derive(Serialize, Deserialize, Debug)]
struct CADREQuerySolarAzel {
#[serde(with = "default_datetime_standard", default = "default_datetime")]
t: DateTime,
#[serde(default = "default_format")]
f: FormatSpecifier,
#[serde(default = "default_degrees")]
u: UnitSpecifier,
}
async fn cadre_get_solar_azel(
State(sl_mutex): State<Arc<Mutex<spice::SpiceLock>>>,
Query(CADREQuerySolarAzel{t, f, u}): Query<CADREQuerySolarAzel>
) -> Result<String, ()>
{
let p = Position::cadre();
println!("time: {:?}", t);
println!("format: {:?}", f);
println!("units: {:?}", u);
println!("pos: {:?}", p);
let res = moontime::solar_azel(sl_mutex, t, p);
let res = moontime::translate_to(res, u);
let res = moontime::format_as(res, f, None);
Ok(res)
}