From 603546f2f99c902a996623b443a7ac1637badf41 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Thu, 2 Apr 2026 21:46:41 +0800 Subject: [PATCH] Align Taipei and Shenzhen settlement sources with Wunderground --- frontend/lib/dashboard-official-sources.ts | 37 ++++++++++++----- src/analysis/city_query_service.py | 2 +- src/data_collection/city_registry.py | 47 ++++++++++++++++------ src/data_collection/weather_sources.py | 4 +- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/frontend/lib/dashboard-official-sources.ts b/frontend/lib/dashboard-official-sources.ts index bb7c13da..12adbdb3 100644 --- a/frontend/lib/dashboard-official-sources.ts +++ b/frontend/lib/dashboard-official-sources.ts @@ -57,21 +57,38 @@ const CITY_SPECIFIC_SOURCES: Record = { href: "https://aviationweather.gov/data/metar/?id=VHHH&decoded=1&taf=1", kind: "metar", }, - ], - taipei: [ { - label: "NOAA RCTP Timeseries", - href: "https://www.weather.gov/wrh/timeseries?site=RCTP", + label: "流浮山站(HKO)", + href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm", + kind: "agency", + }, + ], + "lau fau shan": [ + { + label: "香港天文台", + href: "https://www.hko.gov.hk/en/index.html", kind: "agency", }, { - label: "桃园机场", - href: "https://www.taoyuan-airport.com/", + label: "流浮山站(HKO)", + href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm", + kind: "airport", + }, + ], + taipei: [ + { + label: "Wunderground RCSS", + href: "https://www.wunderground.com/history/daily/tw/taipei/RCSS", + kind: "agency", + }, + { + label: "台北松山机场", + href: "https://www.tsa.gov.tw/?lang=en", kind: "airport", }, { - label: "RCTP METAR", - href: "https://aviationweather.gov/data/metar/?id=RCTP&decoded=1&taf=1", + label: "RCSS METAR", + href: "https://aviationweather.gov/data/metar/?id=RCSS&decoded=1&taf=1", kind: "metar", }, ], @@ -494,8 +511,8 @@ const CITY_SPECIFIC_SOURCES: Record = { ], shenzhen: [ { - label: "NOAA ZGSZ Timeseries", - href: "https://www.weather.gov/wrh/timeseries?site=ZGSZ", + label: "Wunderground ZGSZ", + href: "https://www.wunderground.com/history/daily/cn/shenzhen/ZGSZ", kind: "agency", }, { diff --git a/src/analysis/city_query_service.py b/src/analysis/city_query_service.py index 3cddf5d1..ce9d0772 100644 --- a/src/analysis/city_query_service.py +++ b/src/analysis/city_query_service.py @@ -335,7 +335,7 @@ def build_city_query_report( sc_current = {} city_meta = CITY_REGISTRY.get(city_name.lower(), {}) settlement_source, settlement_source_label = _resolve_settlement_source(city_meta) - use_settlement_current = settlement_source in {"hko", "cwa", "noaa"} and bool(sc_current) + use_settlement_current = settlement_source in {"hko", "cwa", "noaa", "wunderground"} and bool(sc_current) fallback_utc_offset = int(city_meta.get("tz_offset", 0)) nws_periods = ((weather_data.get("nws") or {}).get("forecast_periods") or []) if nws_periods: diff --git a/src/data_collection/city_registry.py b/src/data_collection/city_registry.py index 8c52e9c4..c308003e 100644 --- a/src/data_collection/city_registry.py +++ b/src/data_collection/city_registry.py @@ -110,22 +110,42 @@ CITY_REGISTRY = { "distance_km": 2.0, "warning": "海风与地形共同作用,午后对流触发后温度回落可能偏快。", }, + "lau fau shan": { + "name": "Lau Fau Shan", + "lat": 22.4686, + "lon": 113.9970, + "icao": "LFS", + "settlement_source": "hko", + "settlement_station_code": "LFS", + "settlement_station_label": "Lau Fau Shan", + "settlement_station_candidates": ["Lau Fau Shan"], + "disable_aviationweather": True, + "tz_offset": 28800, + "use_fahrenheit": False, + "is_major": False, + "risk_level": "medium", + "risk_emoji": "🟡", + "airport_name": "流浮山站", + "distance_km": 0.0, + "warning": "HKO 结算取流浮山站分钟级观测;该站不是机场 METAR,不能与 VHHH/VHSK 报文混用。", + }, "taipei": { "name": "Taipei", - "lat": 25.0777, - "lon": 121.2330, - "icao": "RCTP", - "settlement_source": "noaa", - "settlement_station_code": "RCTP", - "settlement_station_label": "Taiwan Taoyuan International Airport", + "lat": 25.0670, + "lon": 121.5525, + "icao": "RCSS", + "settlement_source": "wunderground", + "settlement_station_code": "RCSS", + "settlement_station_label": "Taipei Songshan Airport Station", + "settlement_url": "https://www.wunderground.com/history/daily/tw/taipei/RCSS", "tz_offset": 28800, "use_fahrenheit": False, "is_major": True, "risk_level": "low", "risk_emoji": "🟢", - "airport_name": "台湾桃园国际机场", - "distance_km": 28.1, - "warning": "市场现按 NOAA RCTP 整度°C口径结算,机场与台北市区温度不可混用。", + "airport_name": "台北松山机场", + "distance_km": 4.1, + "warning": "市场现按 Wunderground 台北松山机场站整度°C口径结算;以历史页当日最终完成后的最高整度摄氏值为准。", }, "shanghai": { "name": "Shanghai", @@ -514,9 +534,10 @@ CITY_REGISTRY = { "lat": 22.6393, "lon": 113.8107, "icao": "ZGSZ", - "settlement_source": "noaa", + "settlement_source": "wunderground", "settlement_station_code": "ZGSZ", - "settlement_station_label": "Shenzhen Baoan International Airport", + "settlement_station_label": "Shenzhen Bao'an International Airport Station", + "settlement_url": "https://www.wunderground.com/history/daily/cn/shenzhen/ZGSZ", "tz_offset": 28800, "use_fahrenheit": False, "is_major": True, @@ -524,7 +545,7 @@ CITY_REGISTRY = { "risk_emoji": "🟡", "airport_name": "深圳宝安国际机场", "distance_km": 32.0, - "warning": "市场现按 NOAA ZGSZ 整度°C口径结算;以 weather.gov Temp 列在当日全部小时最终完成后的最高整度摄氏值为准。", + "warning": "市场现按 Wunderground 深圳宝安国际机场站整度°C口径结算;以历史页当日最终完成后的最高整度摄氏值为准。", }, "beijing": { "name": "Beijing", @@ -569,6 +590,7 @@ ALIASES = { "dal": "dallas", "mia": "miami", "atl": "atlanta", "sea": "seattle", "tor": "toronto", "sel": "seoul", "seo": "seoul", "hkg": "hong kong", "hk": "hong kong", + "lfs": "lau fau shan", "laufaushan": "lau fau shan", "tpe": "taipei", "tp": "taipei", "taipei": "taipei", "sha": "shanghai", "sh": "shanghai", "sin": "singapore", "sg": "singapore", "tok": "tokyo", "tyo": "tokyo", @@ -600,6 +622,7 @@ ALIASES = { "多伦多": "toronto", "首尔": "seoul", "香港": "hong kong", + "流浮山": "lau fau shan", "台北": "taipei", "臺北": "taipei", "上海": "shanghai", diff --git a/src/data_collection/weather_sources.py b/src/data_collection/weather_sources.py index e28718fa..27d110ab 100644 --- a/src/data_collection/weather_sources.py +++ b/src/data_collection/weather_sources.py @@ -601,7 +601,9 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour if settlement_current: results["settlement_current"] = settlement_current - if city_lower in ["hong_kong", "hong kong", "香港", "hk"]: + city_meta = self.CITY_REGISTRY.get(str(city_lower or "").strip().lower()) or {} + settlement_source = str(city_meta.get("settlement_source") or "").strip().lower() + if settlement_source == "hko" or city_lower in ["hong_kong", "hong kong", "香港", "hk"]: hko_forecast = self.fetch_hko_forecast() if hko_forecast: results["hko_forecast"] = hko_forecast