接入香港天文台 HKO + 流浮山 LFS 1分钟实时温度

HKO 公共天气 API 免费无注册,提供 1 分钟温度 CSV。
两个站点加入高频推送,与首尔/釜山同级。

Station: HK Observatory (HKO) 27.0°C, Lau Fau Shan (LFS) 25.9°C
Interval: 60s

Tested: pytest 176 passed, HKO API 实测通过
This commit is contained in:
2569718930@qq.com
2026-05-13 00:33:56 +08:00
parent 7084bdf1ec
commit fe9bf61ad6
5 changed files with 193 additions and 7 deletions
+36 -1
View File
@@ -17,10 +17,11 @@ from src.data_collection.nws_open_meteo_sources import NwsOpenMeteoSourceMixin
from src.data_collection.amos_station_sources import AmosStationSourceMixin
from src.data_collection.fmi_sources import FmiSourceMixin
from src.data_collection.knmi_sources import KnmiSourceMixin
from src.data_collection.hko_obs_sources import HkoObsSourceMixin
from src.database.db_manager import DBManager
class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSourceMixin, MgmSourceMixin, JmaAmedasSourceMixin, RussiaStationSourceMixin, NmcSourceMixin, NwsOpenMeteoSourceMixin, AmosStationSourceMixin, FmiSourceMixin, KnmiSourceMixin):
class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSourceMixin, MgmSourceMixin, JmaAmedasSourceMixin, RussiaStationSourceMixin, NmcSourceMixin, NwsOpenMeteoSourceMixin, AmosStationSourceMixin, FmiSourceMixin, KnmiSourceMixin, HkoObsSourceMixin):
"""
Multi-source weather data collector
@@ -233,6 +234,11 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour
)
self._knmi_cache: Dict[str, Dict] = {}
self._knmi_cache_lock = threading.Lock()
self.hko_obs_cache_ttl_sec = int(
os.getenv("HKO_OBS_CACHE_TTL_SEC", "60")
)
self._hko_obs_cache: Dict[str, Dict] = {}
self._hko_obs_cache_lock = threading.Lock()
self.cwa_open_data_auth = (
os.getenv("CWA_OPEN_DATA_AUTH")
or os.getenv("CWA_OPEN_DATA_API_KEY")
@@ -745,6 +751,8 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour
self._fmi_cache.pop(f"fmi:{normalized}:{use_fahrenheit}", None)
with self._knmi_cache_lock:
self._knmi_cache.pop(f"knmi:{normalized}:{use_fahrenheit}", None)
with self._hko_obs_cache_lock:
self._hko_obs_cache.pop(f"hko_obs:{normalized}:{use_fahrenheit}", None)
with self._nmc_cache_lock:
self._nmc_cache.pop(f"{normalized}:{use_fahrenheit}", None)
with self._ru_station_cache_lock:
@@ -958,6 +966,31 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour
except Exception:
logger.exception("airport_obs_log append failed for fmi city={}", city_lower)
def _attach_hko_obs_official_nearby(
self, results: Dict, city_lower: str, use_fahrenheit: bool
) -> None:
if city_lower not in ("hong kong", "lau fau shan"):
return
rows = self.fetch_hko_obs_official_nearby(
city_lower, use_fahrenheit=use_fahrenheit
)
if not rows:
return
results["hko_obs_nearby"] = rows
if "mgm_nearby" not in results:
results["mgm_nearby"] = rows
results["nearby_source"] = "hko_obs"
try:
row = rows[0] if rows else {}
DBManager().append_airport_obs(
icao=str(row.get("icao") or "HKO"),
city=city_lower,
temp_c=row.get("temp"),
obs_time=str(row.get("obs_time") or datetime.now().isoformat()),
)
except Exception:
logger.exception("airport_obs_log append failed for hko_obs city={}", city_lower)
def _attach_korean_amos_data(
self, results: Dict, city_lower: str, use_fahrenheit: bool
) -> None:
@@ -1120,6 +1153,7 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour
self._attach_japan_official_nearby(results, city_lower, use_fahrenheit)
self._attach_fmi_official_nearby(results, city_lower, use_fahrenheit)
self._attach_knmi_official_nearby(results, city_lower, use_fahrenheit)
self._attach_hko_obs_official_nearby(results, city_lower, use_fahrenheit)
self._attach_russia_official_nearby(results, city_lower, use_fahrenheit)
if city_lower == "warsaw":
self._attach_warsaw_official_nearby(results, use_fahrenheit)
@@ -1164,6 +1198,7 @@ class WeatherDataCollector(OpenMeteoCacheMixin, SettlementSourceMixin, MetarSour
self._attach_japan_official_nearby(results, city_lower, use_fahrenheit)
self._attach_fmi_official_nearby(results, city_lower, use_fahrenheit)
self._attach_knmi_official_nearby(results, city_lower, use_fahrenheit)
self._attach_hko_obs_official_nearby(results, city_lower, use_fahrenheit)
self._attach_russia_official_nearby(results, city_lower, use_fahrenheit)
if city_lower == "warsaw":
self._attach_warsaw_official_nearby(results, use_fahrenheit)