巴黎推送按新口径重构:当前实况始终为 AEROWEB,AROME 仅为模型参考

This commit is contained in:
2569718930@qq.com
2026-05-25 21:48:20 +08:00
parent c5e80a56b4
commit 10dcf20077
+71 -26
View File
@@ -882,6 +882,9 @@ def _fetch_arome_temp() -> Optional[float]:
return _AROME_CACHE.get("value")
_LAST_AEROWEB: Dict[str, Any] = {} # {"temp": 31.0, "max_so_far": 31.0, "max_time": "14:00", "ts": epoch}
def _build_narrative(
current_temp: Optional[float],
max_so_far: Optional[float],
@@ -949,6 +952,7 @@ def _build_airport_status_message(
state: str = "",
source_label: str = "",
arome_temp: Optional[float] = None,
aeroweb_available: bool = False,
) -> str:
_AIRPORT_EN = {"seoul": "Incheon", "singapore": "Changi", "busan": "Gimhae", "tokyo": "Haneda",
"ankara": "Esenboğa", "helsinki": "Vantaa", "amsterdam": "Schiphol",
@@ -1067,28 +1071,27 @@ def _build_airport_status_message(
cur_str = f"{display_temp:.1f}{temp_symbol}" if display_temp is not None else "--"
if city == "paris":
# Paris: show both AEROWEB and AROME explicitly
airport_primary = city_weather.get("airport_primary") or {}
if airport_primary.get("source_code") == "aeroweb" and display_temp is not None:
lines.append(f"AEROWEB 实况:{cur_str}")
if aeroweb_available and display_temp is not None:
lines.append(f"当前实况:{cur_str}")
else:
lines.append("AEROWEB 实况:--")
if arome_temp is not None:
diff_str = ""
if display_temp is not None and airport_primary.get("source_code") == "aeroweb":
d = arome_temp - display_temp
sign = "+" if d >= 0 else ""
diff_str = f"{'偏高' if d > 0 else '偏低'}{sign}{d:.1f}°)"
lines.append(f"AROME HD 临近预报:{arome_temp:.1f}{temp_symbol}{diff_str}")
else:
lines.append("AROME HD 临近预报:--")
lines.append("当前实况:暂无")
else:
if has_runway:
lines.append(f"结算跑道当前:{cur_str}")
else:
lines.append(f"当前:{cur_str}")
if max_so_far is not None:
if city == "paris":
if aeroweb_available and max_so_far is not None:
time_str = f"{max_temp_time}" if max_temp_time else ""
lines.append(f"日高实况:{max_so_far:.1f}{temp_symbol}{time_str}")
elif not aeroweb_available:
last_temp = _LAST_AEROWEB.get("temp")
if last_temp is not None:
last_time = _LAST_AEROWEB.get("max_time", "")
time_str = f"{last_time}" if last_time else ""
lines.append(f"最近实况:{last_temp:.1f}{temp_symbol}{time_str}")
elif max_so_far is not None:
time_str = f"{max_temp_time}" if max_temp_time else ""
if has_runway:
lines.append(f"今日跑道高点:{max_so_far:.1f}{temp_symbol}{time_str}")
@@ -1134,12 +1137,45 @@ def _build_airport_status_message(
bits.append(metar_time)
lines.append(f"报文: {' '.join(bits)}")
if deb_pred is not None:
if display_temp is not None and display_temp > deb_pred:
if city == "paris":
if aeroweb_available and display_temp is not None:
diff = display_temp - deb_pred
sign = "+" if diff >= 0 else ""
lines.append(f"DEB{deb_pred:.1f}{temp_symbol}(距实况 {sign}{diff:.1f}°)")
elif not aeroweb_available:
last_temp = _LAST_AEROWEB.get("temp")
if last_temp is not None:
diff = last_temp - deb_pred
sign = "+" if diff >= 0 else ""
lines.append(f"DEB{deb_pred:.1f}{temp_symbol}(距最近实况 {sign}{diff:.1f}°)")
else:
lines.append(f"DEB{deb_pred:.1f}{temp_symbol}")
else:
lines.append(f"DEB{deb_pred:.1f}{temp_symbol}")
elif display_temp is not None and display_temp > deb_pred:
lines.append(f"DEB{deb_pred:.1f}{temp_symbol}(已突破 +{display_temp - deb_pred:.1f}°)")
else:
lines.append(f"DEB{deb_pred:.1f}{temp_symbol}")
if source_label and city != "paris":
if city == "paris":
lines.append("")
if aeroweb_available and display_temp is not None:
lines.append(f"📡 AEROWEB 机场实况:{display_temp:.1f}{temp_symbol} · Météo-France")
else:
lines.append("📡 AEROWEB 机场实况:暂不可用")
if arome_temp is not None:
if aeroweb_available and display_temp is not None:
d = arome_temp - display_temp
sign = "+" if d >= 0 else ""
lines.append(f"🕐 AROME HD 15分钟临近预报:{arome_temp:.1f}{temp_symbol}(较实况 {sign}{d:.1f}°)")
else:
lines.append(f"🕐 AROME HD 15分钟临近预报:{arome_temp:.1f}{temp_symbol}")
else:
lines.append("🕐 AROME HD 15分钟临近预报:--")
if not aeroweb_available:
lines.append("")
lines.append("提示:当前仅显示模型参考,不更新实况日高。")
elif source_label:
lines.append("")
lines.append(f"📡 {source_label}")
@@ -1326,18 +1362,27 @@ def _process_airport_city(
current_obs_time = str(airport_primary.get("obs_time") or "")
source_label = "" # human-readable data source for Paris messages
arome_temp_val = None # AROME HD temperature for display (always fetched for comparison)
aeroweb_available = False
if city == "paris":
arome_temp_val = _fetch_arome_temp()
airport_primary = city_weather.get("airport_primary") or {}
if airport_primary.get("source_code") == "aeroweb":
# Detect AEROWEB availability
if airport_primary.get("source_code") == "aeroweb" and airport_primary.get("temp") is not None:
aeroweb_available = True
source_label = "AEROWEB 机场实况 · Météo-France"
elif arome_temp_val is not None:
current_temp = arome_temp_val
city_weather.setdefault("current", {})["temp"] = arome_temp_val
source_label = "AROME HD 15分钟临近预报 · Météo-France"
if not current_obs_time:
current_obs_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")
if current_temp is None or deb_pred is None:
# Update last known AEROWEB cache
_LAST_AEROWEB["temp"] = float(airport_primary["temp"])
_LAST_AEROWEB["ts"] = time.time()
# Get daily high from airport data
aero_max = (city_weather.get("airport_current") or {}).get("max_so_far")
aero_max_time = (city_weather.get("airport_current") or {}).get("max_temp_time")
if aero_max is not None:
_LAST_AEROWEB["max_so_far"] = float(aero_max)
_LAST_AEROWEB["max_time"] = str(aero_max_time or "")[11:16] if aero_max_time else ""
# Allow Paris pushes even when AEROWEB is down (show cached/last-known data)
if city == "paris" and not aeroweb_available and deb_pred is not None:
pass
elif current_temp is None or deb_pred is None:
return None
# Dedup: same observation → skip (with delayed retry for HK / LFS)
@@ -1380,7 +1425,7 @@ def _process_airport_city(
or city_weather.get("local_time")
or ""
)
message = _build_airport_status_message(city, city_weather, deb_pred, obs_local, state="", source_label=source_label, arome_temp=arome_temp_val)
message = _build_airport_status_message(city, city_weather, deb_pred, obs_local, state="", source_label=source_label, arome_temp=arome_temp_val, aeroweb_available=aeroweb_available)
# Send to all target chats
sent = False