Files
PolyWeather/tests/test_amsc_awos_sources.py
T
2026-06-05 14:38:58 +08:00

171 lines
6.2 KiB
Python

from src.data_collection.amsc_awos_sources import (
AmscAwosSourceMixin,
_amsc_parse_wind_plate_payload,
_amsc_supported_city_codes,
)
ZBAA_SAMPLE = {
"code": 200,
"msg": "操作成功",
"data": {
"18R/36L": {
"RNO": "18R/36L",
"OTIME": "2026-05-14 17:19:00",
"TDZ_TEMP": "20.8",
"MID_TEMP": "-",
"END_TEMP": "20.8",
"TDZ_HUMID": "67",
"END_HUMID": "67",
"METAR": "METAR ZBAA 141700Z 12003MPS 050V170 7000 NSC 21/15 Q1014 NOSIG=",
},
"18L/36R": {
"RNO": "18L/36R",
"OTIME": "2026-05-14 17:19:00",
"TDZ_TEMP": "21.0",
"MID_TEMP": "-",
"END_TEMP": "20.4",
"METAR": "METAR ZBAA 141700Z 12003MPS 050V170 7000 NSC 21/15 Q1014 NOSIG=",
},
"19/01": {
"RNO": "19/01",
"OTIME": "2026-05-14 17:19:00",
"TDZ_TEMP": "20.2",
"MID_TEMP": "-",
"END_TEMP": "20.2",
"METAR": "METAR ZBAA 141700Z 12003MPS 050V170 7000 NSC 21/15 Q1014 NOSIG=",
},
},
}
def test_parse_wind_plate_payload_normalizes_runway_point_temperatures():
parsed = _amsc_parse_wind_plate_payload(ZBAA_SAMPLE, city_key="beijing", icao="ZBAA")
assert parsed["source"] == "amsc_awos"
assert parsed["source_label"] == "AMSC AWOS Beijing Capital (ZBAA)"
assert parsed["observation_source_zh"] == "AMSC AWOS 跑道观测气温"
assert parsed["icao"] == "ZBAA"
assert parsed["temp_c"] == 20.2
assert parsed["temp_source"] == "settlement_runway_endpoint"
assert parsed["settlement_runway"] == "01"
assert parsed["settlement_runway_pair"] == "19/01"
assert parsed["settlement_runway_position"] == "end"
assert parsed["runway_temp_range"] == (20.2, 21.0)
assert parsed["observation_time"] == "2026-05-14T17:19:00+00:00"
assert parsed["observation_time_local"] == "2026-05-15 01:19:00"
assert parsed["raw_metar"].startswith("METAR ZBAA 141700Z")
runway_obs = parsed["runway_obs"]
assert runway_obs["runway_pairs"] == [("18R", "36L"), ("18L", "36R"), ("19", "01")]
assert runway_obs["temperatures"] == [(20.8, None), (21.0, None), (20.2, None)]
pt0 = runway_obs["point_temperatures"][0]
assert pt0["runway"] == "18R/36L"
assert pt0["tdz_temp"] == 20.8
assert pt0["mid_temp"] is None
assert pt0["end_temp"] == 20.8
assert pt0["target_runway_max"] == 20.8
assert pt0["wind_dir"] is None
assert pt0["wind_speed"] is None
assert pt0["rvr"] is None
assert pt0["mor"] is None
assert pt0["humidity"] == 67.0
settlement_pt = runway_obs["point_temperatures"][2]
assert settlement_pt["runway"] == "19/01"
assert settlement_pt["is_settlement"] is True
assert settlement_pt["target_runway_max"] == 20.2
def test_parse_wind_plate_payload_uses_settlement_runway_endpoint_temperature():
payload = {
"code": 200,
"data": {
"04/22": {
"RNO": "04/22",
"OTIME": "2026-05-14 17:19:00",
"TDZ_TEMP": "31.2",
"MID_TEMP": "33.4",
"END_TEMP": "32.6",
},
"05/23": {
"RNO": "05/23",
"OTIME": "2026-05-14 17:19:00",
"TDZ_TEMP": "34.8",
"MID_TEMP": "35.1",
"END_TEMP": "34.2",
},
},
}
parsed = _amsc_parse_wind_plate_payload(payload, city_key="wuhan", icao="ZHHH")
assert parsed is not None
assert parsed["temp_c"] == 31.2
assert parsed["temp_source"] == "settlement_runway_endpoint"
assert parsed["settlement_runway"] == "04"
assert parsed["settlement_runway_pair"] == "04/22"
assert parsed["settlement_runway_position"] == "tdz"
settlement_point = parsed["runway_obs"]["point_temperatures"][0]
assert settlement_point["is_settlement"] is True
assert settlement_point["settlement_runway"] == "04"
assert settlement_point["target_runway_max"] == 31.2
def test_parse_wind_plate_payload_uses_end_temperature_when_target_is_second_runway():
payload = {
"code": 200,
"data": {
"20R/02L": {
"RNO": "20R/02L",
"OTIME": "2026-05-14 17:19:00",
"TDZ_TEMP": "34.4",
"MID_TEMP": "35.2",
"END_TEMP": "33.7",
},
},
}
parsed = _amsc_parse_wind_plate_payload(payload, city_key="chongqing", icao="ZUCK")
assert parsed is not None
assert parsed["temp_c"] == 33.7
assert parsed["settlement_runway"] == "02L"
assert parsed["settlement_runway_pair"] == "20R/02L"
assert parsed["settlement_runway_position"] == "end"
assert parsed["runway_obs"]["point_temperatures"][0]["target_runway_max"] == 33.7
def test_parse_wind_plate_payload_rejects_unauthorized_or_empty_payloads():
assert _amsc_parse_wind_plate_payload(
{"errCode": -12010, "errMsg": "无权访问此接口"},
city_key="beijing",
icao="ZBAA",
) is None
assert _amsc_parse_wind_plate_payload({"code": 200, "data": {}}, city_key="beijing", icao="ZBAA") is None
def test_fetch_amsc_official_current_uses_domestic_city_whitelist(monkeypatch):
import src.data_collection.amsc_awos_sources as _amsc
from src.data_collection.observation_source_gate import reset_observation_source_gate_for_tests
monkeypatch.setenv("POLYWEATHER_OBSERVATION_SOURCE_DB_LOCK_ENABLED", "false")
reset_observation_source_gate_for_tests()
monkeypatch.setattr(_amsc, "AMSC_AWOS_BASE_URL", "https://www.amsc.net.cn/gateway/api/saas/rest/amc/AwosController/getWindPlate")
assert _amsc_supported_city_codes()["beijing"] == "ZBAA"
assert "new york" not in _amsc_supported_city_codes()
class FakeCollector(AmscAwosSourceMixin):
timeout = 1.0
def _amsc_http_get_json(self, url, *, headers=None):
assert "getWindPlate?cccc=ZBAA" in url
return ZBAA_SAMPLE
data = FakeCollector().fetch_amsc_awos_current("beijing")
assert data is not None
assert data["icao"] == "ZBAA"
assert data["temp_c"] == 20.2
assert data["runway_temp_range"] == (20.2, 21.0)
assert FakeCollector().fetch_amsc_awos_current("new york") is None