修正市场监控温度数据源:接入 NOAA MADIS 5分钟高频数据并优化展示

- 首尔/釜山:隐藏大号跑道温度值,改为"跑道温度"标签(跑道表面温度 ≠ 空气温度)
- US 城市:MADIS HFMETAR 5分钟小数温度接入 airport_primary,前端优先读取
- 其他城市:整数值不再强制 toFixed(1) 追加虚假 .0 精度
- 后端:weather_sources.py 注入 madis_hfmetar_current 到 results
- 后端:country_networks.py 的 _airport_primary_from_raw 新增 MADIS 优先分支
- 文档:更新 AIRPORT_REALTIME_SOURCES.md 新增 11 个 US 城市
- 文档:更新 CLAUDE.md 补充市场监控、高频数据管道、Country Network Provider 架构

Tested: npx tsc --noEmit ✓  ruff check . ✓
This commit is contained in:
2569718930@qq.com
2026-05-14 16:00:55 +08:00
parent c9d03fd3e1
commit 96676e7097
7 changed files with 83 additions and 9 deletions
+31
View File
@@ -242,6 +242,37 @@ def _airport_primary_from_raw(city: str, raw: Dict[str, Any]) -> Dict[str, Any]:
meta = _city_meta(city)
metar = raw.get("metar") or {}
current = metar.get("current") or {}
# High-frequency realtime sources take priority over plain METAR.
madis = raw.get("madis_hfmetar_current") or {}
if madis.get("temp_c") is not None:
return _normalize_station_row(
station_code=meta.get("icao") or madis.get("icao"),
station_label=meta.get("airport_name") or meta.get("icao"),
temp=madis["temp_c"],
obs_time=madis.get("obs_time") or metar.get("observation_time"),
source_code="madis_hfmetar",
source_label="NOAA MADIS",
is_official=True,
is_airport_station=True,
is_settlement_anchor=False,
extra={
"max_so_far": _safe_float(current.get("max_temp_so_far")),
"max_temp_time": current.get("max_temp_time"),
"obs_age_min": None,
"report_time": metar.get("report_time"),
"receipt_time": metar.get("receipt_time"),
"obs_time_epoch": metar.get("obs_time_epoch"),
"obs_time_utc_offset_seconds": 0,
"wind_speed_kt": _safe_float(madis.get("wind_kt")) or _safe_float(current.get("wind_speed_kt")),
"wind_dir": _safe_float(current.get("wind_dir")),
"humidity": _safe_float(current.get("humidity")),
"visibility_mi": _safe_float(current.get("visibility_mi")),
"wx_desc": current.get("wx_desc"),
"raw_metar": current.get("raw_metar"),
},
)
return _normalize_station_row(
station_code=meta.get("icao") or metar.get("icao"),
station_label=meta.get("airport_name") or metar.get("station_name") or metar.get("icao"),
+2
View File
@@ -1084,6 +1084,8 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour
# Find this city's station in the MADIS results
for obs in obs_list:
if obs["icao"] == icao:
# Inject into results so it flows through to airport_primary
results["madis_hfmetar_current"] = obs
try:
DBManager().append_airport_obs(
icao=icao,