Working on metars, updating ui drawer
This commit is contained in:
@@ -134,7 +134,7 @@ async fn validate_session(req: HttpRequest) -> HttpResponse {
|
||||
let session_id = cookie.value().to_string();
|
||||
let session = match Session::replace(&session_id, &ip_address).await {
|
||||
Ok(session) => session,
|
||||
Err(err) => {
|
||||
Err(_) => {
|
||||
log::error!(
|
||||
"Invalid session validate attempt [Session: {}] [IP Address: {}]",
|
||||
session_id,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use crate::error::ApiResult;
|
||||
use redis::{Client as RedisClient, aio::MultiplexedConnection as RedisConnection, RedisResult};
|
||||
use redis::{
|
||||
Client as RedisClient, aio::MultiplexedConnection as RedisConnection, RedisResult,
|
||||
};
|
||||
use s3::{Bucket, Region, creds::Credentials, BucketConfiguration, request::ResponseData};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::OnceLock;
|
||||
@@ -129,10 +131,10 @@ fn redis() -> &'static RedisClient {
|
||||
REDIS.get().unwrap()
|
||||
}
|
||||
|
||||
pub fn redis_connection() -> RedisResult<redis::Connection> {
|
||||
let conn = redis().get_connection()?;
|
||||
Ok(conn)
|
||||
}
|
||||
// pub fn redis_connection() -> RedisResult<redis::Connection> {
|
||||
// let conn = redis().get_connection()?;
|
||||
// Ok(conn)
|
||||
// }
|
||||
|
||||
pub async fn redis_async_connection() -> RedisResult<RedisConnection> {
|
||||
let conn = redis().get_multiplexed_async_connection().await?;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::error::Error;
|
||||
use crate::{error::ApiResult, db};
|
||||
use chrono::{DateTime, Datelike, Utc};
|
||||
use chrono::{DateTime, Datelike, NaiveDate, Utc};
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fmt::Display;
|
||||
@@ -338,49 +338,7 @@ impl Metar {
|
||||
// Date/Time
|
||||
let observation_time = metar_parts[0];
|
||||
metar_parts.remove(0);
|
||||
if observation_time.len() != 7 {
|
||||
return Err(Error::new(
|
||||
500,
|
||||
format!(
|
||||
"Unable to parse observation time in {}: {}",
|
||||
observation_time, metar_string
|
||||
),
|
||||
));
|
||||
}
|
||||
let observation_time_day = match observation_time[0..2].parse::<u32>() {
|
||||
Ok(day) => day,
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
let observation_time_hour = match observation_time[2..4].parse::<u32>() {
|
||||
Ok(hour) => hour,
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
let observation_time_minute = match observation_time[4..6].parse::<u32>() {
|
||||
Ok(minute) => minute,
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
let current_time = Utc::now().naive_utc();
|
||||
|
||||
// Check if the observation time is from the previous month
|
||||
let observation_time_month = if current_time.day() > observation_time_day {
|
||||
current_time.month() - 1
|
||||
} else {
|
||||
current_time.month()
|
||||
};
|
||||
// Check if the observation time is from the previous year
|
||||
let observation_time_year = if current_time.month() > observation_time_month {
|
||||
current_time.year() - 1
|
||||
} else {
|
||||
current_time.year()
|
||||
};
|
||||
let observation_time = format!(
|
||||
"{:04}-{:02}-{:02}T{:02}:{:02}:00Z",
|
||||
observation_time_year,
|
||||
observation_time_month,
|
||||
observation_time_day,
|
||||
observation_time_hour,
|
||||
observation_time_minute
|
||||
);
|
||||
let observation_time = Self::parse_time(observation_time)?;
|
||||
metar.observation_time = match chrono::DateTime::parse_from_rfc3339(&observation_time) {
|
||||
Ok(datetime) => datetime.with_timezone(&Utc),
|
||||
Err(err) => return Err(err.into()),
|
||||
@@ -928,6 +886,49 @@ impl Metar {
|
||||
Ok(metar)
|
||||
}
|
||||
|
||||
fn parse_time(observation_time: &str) -> ApiResult<String> {
|
||||
if observation_time.len() != 7 {
|
||||
return Err(Error::new(
|
||||
500,
|
||||
format!("Unable to parse observation time in {}", observation_time),
|
||||
));
|
||||
}
|
||||
let observation_day = match observation_time[0..2].parse::<u32>() {
|
||||
Ok(day) => day,
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
let observation_hour = match observation_time[2..4].parse::<u32>() {
|
||||
Ok(hour) => hour,
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
let observation_minute = match observation_time[4..6].parse::<u32>() {
|
||||
Ok(minute) => minute,
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
let current_time = Utc::now().naive_utc();
|
||||
let current_year = current_time.year();
|
||||
let current_month = current_time.month();
|
||||
let candidate_date = NaiveDate::from_ymd_opt(current_year, current_month, observation_day)
|
||||
.ok_or_else(|| Error::new(500, format!("Invalid date with day {} for current month", observation_day)))?
|
||||
.and_hms_opt(observation_hour, observation_minute, 0).unwrap();
|
||||
|
||||
let obs_datetime = if candidate_date > current_time {
|
||||
// Subtract one month. (Handle year rollover carefully.)
|
||||
let (month, year) = if current_month == 1 {
|
||||
(12, current_year - 1)
|
||||
} else {
|
||||
(current_month - 1, current_year)
|
||||
};
|
||||
|
||||
let adjusted_date = NaiveDate::from_ymd_opt(year, month, observation_day)
|
||||
.ok_or_else(|| Error::new(500, format!("Invalid date with day {} for month {}", observation_day, month)))?;
|
||||
adjusted_date.and_hms(observation_hour, observation_minute, 0)
|
||||
} else {
|
||||
candidate_date
|
||||
};
|
||||
Ok(obs_datetime.format("%Y-%m-%dT%H:%M:00Z").to_string())
|
||||
}
|
||||
|
||||
async fn get_missing_metar_icaos(
|
||||
db_metars: &Vec<Self>,
|
||||
station_icaos: &Vec<String>,
|
||||
@@ -961,7 +962,7 @@ impl Metar {
|
||||
.collect::<Vec<String>>();
|
||||
let mut metars: Vec<Metar> = vec![];
|
||||
for icao_chunk in icao_chunks {
|
||||
let url = format!("{}/metar?ids={}&order=id", base_url, icao_chunk);
|
||||
let url = format!("{}/metar?ids={}&hours=0&order=id,-obs", base_url, icao_chunk);
|
||||
let mut m = match client.get(url).send().await {
|
||||
Ok(r) => {
|
||||
// Check if the status code is 200
|
||||
@@ -1049,7 +1050,6 @@ impl Metar {
|
||||
let result: RedisResult<Option<bool>> = conn.get(icao).await;
|
||||
match result {
|
||||
Ok(Some(value)) => {
|
||||
log::info!("{}: {}", icao, value);
|
||||
if value {
|
||||
updated_missing_icao_list.push(icao);
|
||||
}
|
||||
@@ -1105,6 +1105,7 @@ impl Metar {
|
||||
}
|
||||
|
||||
pub async fn insert(&self) -> ApiResult<()> {
|
||||
log::trace!("Inserting metar {} with observation time {}", self.icao, self.observation_time);
|
||||
let metar: MetarRow = self.to_db()?;
|
||||
metar.insert().await?;
|
||||
Ok(())
|
||||
@@ -1113,26 +1114,68 @@ impl Metar {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::NaiveDateTime;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_metar() {
|
||||
fn test_parse_time() {
|
||||
for day in 1..=31 {
|
||||
for hour in 0..24 {
|
||||
for minute in 0..60 {
|
||||
// METAR form "DDHHMMZ"
|
||||
let obs_time = format!("{:02}{:02}{:02}Z", day, hour, minute);
|
||||
let result = Metar::parse_time(&obs_time);
|
||||
match result {
|
||||
Ok(datetime_str) => {
|
||||
// "YYYY-MM-DDTHH:MM:00Z"
|
||||
assert_eq!(
|
||||
datetime_str.len(),
|
||||
20,
|
||||
"Unexpected length for input {} yielded {}",
|
||||
obs_time,
|
||||
datetime_str
|
||||
);
|
||||
// Remove the trailing 'Z' and parse
|
||||
let trimmed = &datetime_str[..19];
|
||||
NaiveDateTime::parse_from_str(trimmed, "%Y-%m-%dT%H:%M:%S")
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Parsing '{}' from input {} failed: {}",
|
||||
trimmed, obs_time, e
|
||||
)
|
||||
});
|
||||
}
|
||||
Err(_err) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_metar() {
|
||||
let mut metar_string = "METAR KABC 121755Z AUTO 21016G24KT 180V240 1SM R11/P6000FT -RA BR BKN015 OVC025 06/04 A2990
|
||||
RMK AO2 PK WND 20032/25 WSHFT 1715 VIS 3/4V1 1/2 VIS 3/4 RWY11 RAB07 CIG 013V017 CIG 017 RWY11 PRESFR
|
||||
SLP125 P0003 60009 T00640036 10066 21012 58033 TSNO $".to_string();
|
||||
let metar = Metar::parse(&metar_string).unwrap();
|
||||
// dbg!(&metar);
|
||||
dbg!(&metar.observation_time);
|
||||
|
||||
metar_string = "KMIA 090053Z 33004KT 10SM FEW015 FEW024 SCT075 SCT250 25/22 A2990 RMK AO2 SLP126 T02500217 $".to_string();
|
||||
let metar = Metar::parse(&metar_string).unwrap();
|
||||
// dbg!(&metar);
|
||||
dbg!(&metar.observation_time);
|
||||
|
||||
metar_string =
|
||||
"KMRB 082253Z 30014G23KT 10SM CLR 05/M12 A3002 RMK AO2 PK WND 30028/2157 SLP168 T00501117"
|
||||
.to_string();
|
||||
let metar = Metar::parse(&metar_string).unwrap();
|
||||
// dbg!(&metar);
|
||||
dbg!(&metar.observation_time);
|
||||
|
||||
// metar_string = "KHEF 092356Z 13009KT 10SM CLR 08/M03 A3022 RMK AO2 SLP239 6//// T00831033 10133 20078 53002 PNO $".to_string();
|
||||
metar_string = "KHEF 092356Z 13009KT 10SM CLR 08/M03 A3022 RMK AO2 SLP239 6//// T00831033 10133 20078 53002 PNO $".to_string();
|
||||
let metar = Metar::parse(&metar_string).unwrap();
|
||||
dbg!(&metar.observation_time);
|
||||
|
||||
metar_string = "KSLK 162351Z AUTO VRB03KT 1SM -SN BR FEW007 OVC014 00/M02 A2974 RMK AO2 SLP090 P0001 60004 T00001017 10000 21011 53026".to_string();
|
||||
let metar = Metar::parse(&metar_string).unwrap();
|
||||
dbg!(&metar.observation_time);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user