首尔/釜山跑道数据:Python 存 RKSI_RWY_0/1,Rust 查询展示
- weather_sources: AMOS 采集时每条跑道单独写 airport_obs_log - Rust: 按 RKSI_RWY_0、RKSI_RWY_1 等 icao 查询跑道温度 - 跑道标签 18L/36R、18R/36L 写死在 config 中
This commit is contained in:
+36
-16
@@ -17,19 +17,25 @@ use tower_http::services::ServeDir;
|
|||||||
use tracing_subscriber;
|
use tracing_subscriber;
|
||||||
|
|
||||||
// ── city config ──
|
// ── city config ──
|
||||||
// (key, zh_name, en_name, icao, airport_en, utc_offset_hours, threshold, tz_abbr)
|
// (key, zh_name, en_name, icao, airport_en, utc_offset_hours, threshold, tz_abbr, runway_count)
|
||||||
const CITIES: &[(&str, &str, &str, &str, &str, i32, f64, &str)] = &[
|
const CITIES: &[(&str, &str, &str, &str, &str, i32, f64, &str, usize)] = &[
|
||||||
("seoul", "首尔", "Seoul", "RKSI", "Incheon", 9, 3.0, "KST"),
|
("seoul", "首尔", "Seoul", "RKSI", "Incheon", 9, 3.0, "KST", 2),
|
||||||
("busan", "釜山", "Busan", "RKPK", "Gimhae", 9, 2.0, "KST"),
|
("busan", "釜山", "Busan", "RKPK", "Gimhae", 9, 2.0, "KST", 2),
|
||||||
("tokyo", "东京", "Tokyo", "44166", "Haneda", 9, 2.0, "JST"),
|
("tokyo", "东京", "Tokyo", "44166", "Haneda", 9, 2.0, "JST", 0),
|
||||||
("ankara", "安卡拉", "Ankara", "17128", "Esenboğa", 3, 3.0, "TRT"),
|
("ankara", "安卡拉", "Ankara", "17128", "Esenboğa", 3, 3.0, "TRT", 0),
|
||||||
("helsinki", "赫尔辛基", "Helsinki", "EFHK", "Vantaa", 3, 2.0, "EEST"),
|
("helsinki", "赫尔辛基", "Helsinki", "EFHK", "Vantaa", 3, 2.0, "EEST", 0),
|
||||||
("amsterdam","阿姆斯特丹","Amsterdam","EHAM","Schiphol",2,2.0,"CEST"),
|
("amsterdam","阿姆斯特丹","Amsterdam","EHAM","Schiphol",2,2.0,"CEST", 0),
|
||||||
("istanbul","伊斯坦布尔","Istanbul","17058","Airport",3,3.0,"TRT"),
|
("istanbul","伊斯坦布尔","Istanbul","17058","Airport",3,3.0,"TRT", 0),
|
||||||
("paris", "巴黎", "Paris", "LFPB", "Le Bourget", 2, 3.0, "CEST"),
|
("paris", "巴黎", "Paris", "LFPB", "Le Bourget", 2, 3.0, "CEST", 0),
|
||||||
("hong kong","香港","Hong Kong","HKO","Observatory",8,1.5,"HKT"),
|
("hong kong","香港","Hong Kong","HKO","Observatory",8,1.5,"HKT", 0),
|
||||||
("lau fau shan","流浮山","Lau Fau Shan","LFS","Lau Fau Shan",8,1.5,"HKT"),
|
("lau fau shan","流浮山","Lau Fau Shan","LFS","Lau Fau Shan",8,1.5,"HKT", 0),
|
||||||
("taipei", "台北", "Taipei", "466920", "Songshan", 8, 1.5, "TST"),
|
("taipei", "台北", "Taipei", "466920", "Songshan", 8, 1.5, "TST", 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 跑道标签(与 AMOS scrape 返回的一致)
|
||||||
|
const RUNWAY_LABELS: &[&[&str]] = &[
|
||||||
|
&["18L/36R", "18R/36L"], // seoul
|
||||||
|
&["18L/36R", "18R/36L"], // busan
|
||||||
];
|
];
|
||||||
|
|
||||||
// ── app state ──
|
// ── app state ──
|
||||||
@@ -49,7 +55,7 @@ struct MonitorTemplate {
|
|||||||
|
|
||||||
// ── data loading ──
|
// ── data loading ──
|
||||||
|
|
||||||
fn load_city_snapshot(db_path: &str, (key, _zh, en, icao, airport, tz, thresh, tz_abbr): &(&str, &str, &str, &str, &str, i32, f64, &str)) -> CitySnapshot {
|
fn load_city_snapshot(db_path: &str, idx: usize, (key, _zh, en, icao, airport, tz, thresh, tz_abbr, rw_count): &(&str, &str, &str, &str, &str, i32, f64, &str, usize)) -> CitySnapshot {
|
||||||
let now_utc = Utc::now();
|
let now_utc = Utc::now();
|
||||||
let local = now_utc + chrono::Duration::hours(*tz as i64);
|
let local = now_utc + chrono::Duration::hours(*tz as i64);
|
||||||
let local_time = format!("{} {}", local.format("%H:%M"), tz_abbr);
|
let local_time = format!("{} {}", local.format("%H:%M"), tz_abbr);
|
||||||
@@ -84,6 +90,19 @@ fn load_city_snapshot(db_path: &str, (key, _zh, en, icao, airport, tz, thresh, t
|
|||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Runway data: query each runway ICAO
|
||||||
|
let mut runway_pairs: Vec<(String, f64)> = vec![];
|
||||||
|
if *rw_count > 0 && idx < RUNWAY_LABELS.len() {
|
||||||
|
for i in 0..*rw_count {
|
||||||
|
let rw_icao = format!("{}_RWY_{}", icao, i);
|
||||||
|
let rw_obs = db::get_recent_obs(db_path, &rw_icao, 120, 1);
|
||||||
|
if let Some(rw_temp) = rw_obs.first().and_then(|o| o.temp_c) {
|
||||||
|
let label = RUNWAY_LABELS[idx].get(i).unwrap_or(&"?").to_string();
|
||||||
|
runway_pairs.push((label, rw_temp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CitySnapshot {
|
CitySnapshot {
|
||||||
name: key.to_string(),
|
name: key.to_string(),
|
||||||
en_name: en.to_string(),
|
en_name: en.to_string(),
|
||||||
@@ -95,7 +114,7 @@ fn load_city_snapshot(db_path: &str, (key, _zh, en, icao, airport, tz, thresh, t
|
|||||||
max_time: None,
|
max_time: None,
|
||||||
trend,
|
trend,
|
||||||
new_high,
|
new_high,
|
||||||
runway_pairs: vec![],
|
runway_pairs,
|
||||||
gap: None,
|
gap: None,
|
||||||
threshold: *thresh,
|
threshold: *thresh,
|
||||||
time_ok: false,
|
time_ok: false,
|
||||||
@@ -110,7 +129,8 @@ fn load_city_snapshot(db_path: &str, (key, _zh, en, icao, airport, tz, thresh, t
|
|||||||
fn load_all_cities(db_path: &str) -> Vec<CitySnapshot> {
|
fn load_all_cities(db_path: &str) -> Vec<CitySnapshot> {
|
||||||
CITIES
|
CITIES
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| load_city_snapshot(db_path, c))
|
.enumerate()
|
||||||
|
.map(|(i, c)| load_city_snapshot(db_path, i, c))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1033,6 +1033,18 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour
|
|||||||
pressure_hpa=amos_data.get("pressure_hpa"),
|
pressure_hpa=amos_data.get("pressure_hpa"),
|
||||||
obs_time=amos_data.get("observation_time") or datetime.now().isoformat(),
|
obs_time=amos_data.get("observation_time") or datetime.now().isoformat(),
|
||||||
)
|
)
|
||||||
|
# 也存每条跑道的数据,用 RKSI_RWY_0 / RKSI_RWY_1 做 icao
|
||||||
|
runway_obs = amos_data.get("runway_obs") or {}
|
||||||
|
rw_pairs = runway_obs.get("runway_pairs") or []
|
||||||
|
rw_temps = runway_obs.get("temperatures") or []
|
||||||
|
for i, (pair, (t, _d)) in enumerate(zip(rw_pairs, rw_temps)):
|
||||||
|
if t is not None and i < 4:
|
||||||
|
DBManager().append_airport_obs(
|
||||||
|
icao=f"{amos_data.get('icao', '')}_RWY_{i}",
|
||||||
|
city=city_lower,
|
||||||
|
temp_c=t,
|
||||||
|
obs_time=amos_data.get("observation_time") or datetime.now().isoformat(),
|
||||||
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("airport_obs_log append failed for amos city={}", city_lower)
|
logger.exception("airport_obs_log append failed for amos city={}", city_lower)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user