Use latest AMSC runway timestamp for overlays

This commit is contained in:
2569718930@qq.com
2026-06-15 00:43:07 +08:00
parent 8bf7cdd687
commit 59f19407cb
4 changed files with 58 additions and 8 deletions
+17 -2
View File
@@ -164,6 +164,7 @@ def _amsc_parse_wind_plate_payload(
valid_values = []
observation_time = None
observation_time_local = None
observation_time_epoch = None
raw_metar = None
for key, raw_row in data.items():
@@ -179,8 +180,22 @@ def _amsc_parse_wind_plate_payload(
if not points:
continue
if observation_time is None:
observation_time, observation_time_local = _amsc_parse_utc_time(raw_row.get("OTIME"))
row_observation_time, row_observation_time_local = _amsc_parse_utc_time(raw_row.get("OTIME"))
row_observation_epoch = None
if row_observation_time:
try:
row_observation_epoch = datetime.fromisoformat(row_observation_time).timestamp()
except ValueError:
row_observation_epoch = None
if row_observation_epoch is not None and (
observation_time_epoch is None or row_observation_epoch > observation_time_epoch
):
observation_time = row_observation_time
observation_time_local = row_observation_time_local
observation_time_epoch = row_observation_epoch
elif observation_time is None and row_observation_time:
observation_time = row_observation_time
observation_time_local = row_observation_time_local
if raw_metar is None and raw_row.get("METAR"):
raw_metar = str(raw_row.get("METAR"))
+30
View File
@@ -135,6 +135,36 @@ def test_parse_wind_plate_payload_uses_end_temperature_when_target_is_second_run
assert parsed["runway_obs"]["point_temperatures"][0]["target_runway_max"] == 33.7
def test_parse_wind_plate_payload_uses_latest_runway_observation_time():
payload = {
"code": 200,
"data": {
"16L/34R": {
"RNO": "16L/34R",
"OTIME": "2026-06-14 10:44:00",
"TDZ_TEMP": "22.0",
"MID_TEMP": "22.1",
"END_TEMP": "22.2",
},
"17L/35R": {
"RNO": "17L/35R",
"OTIME": "2026-06-14 15:43:00",
"TDZ_TEMP": "24.9",
"MID_TEMP": "25.1",
"END_TEMP": "25.4",
},
},
}
parsed = _amsc_parse_wind_plate_payload(payload, city_key="shanghai", icao="ZSPD")
assert parsed is not None
assert parsed["settlement_runway"] == "35R"
assert parsed["temp_c"] == 25.4
assert parsed["observation_time"] == "2026-06-14T15:43:00+00:00"
assert parsed["observation_time_local"] == "2026-06-14 23:43:00"
def test_parse_wind_plate_payload_rejects_unauthorized_or_empty_payloads():
assert _amsc_parse_wind_plate_payload(
{"errCode": -12010, "errMsg": "无权访问此接口"},
+2 -2
View File
@@ -129,7 +129,7 @@ def test_scan_terminal_response_includes_backend_server_timing(monkeypatch):
monkeypatch.setattr(
scan_api.legacy_routes,
"build_scan_terminal_payload",
lambda filters, force_refresh=False, timing_recorder=None: {
lambda filters, force_refresh=False, timing_recorder=None, **_kwargs: {
"rows": [],
"filters": filters,
"status": "ready",
@@ -155,7 +155,7 @@ def test_scan_terminal_stale_response_is_not_cached(monkeypatch):
monkeypatch.setattr(
scan_api.legacy_routes,
"build_scan_terminal_payload",
lambda filters, force_refresh=False, timing_recorder=None: {
lambda filters, force_refresh=False, timing_recorder=None, **_kwargs: {
"rows": [],
"filters": filters,
"status": "ready",
+9 -4
View File
@@ -58,13 +58,18 @@ def _block_epoch(block: Any) -> Optional[int]:
def _raw_amsc_epoch(row: dict[str, Any], raw_payload: dict[str, Any]) -> Optional[int]:
values = (
payload_values = (
raw_payload.get("observation_time"),
raw_payload.get("observed_at"),
row.get("observed_at"),
)
parsed = [epoch for epoch in (parse_observation_epoch(value) for value in values) if epoch is not None]
return max(parsed) if parsed else None
parsed = [
epoch
for epoch in (parse_observation_epoch(value) for value in payload_values)
if epoch is not None
]
if parsed:
return max(parsed)
return parse_observation_epoch(row.get("observed_at"))
def _to_float(value: Any) -> Optional[float]: