67 lines
3.0 KiB
Python
67 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from app.cache import cache_get as redis_get, cache_set as redis_set
|
|
from app.config import (
|
|
BRIGHTSKY_BASE_URL,
|
|
CACHE_TTL_FORECAST,
|
|
CACHE_TTL_OBSERVATIONS,
|
|
OPEN_METEO_BASE_URL,
|
|
)
|
|
from app.database import get_cached_json, set_cached_json
|
|
from app.http_client import fetch_json
|
|
|
|
FORECAST_PARAMS = {
|
|
"timezone": "Europe/Berlin",
|
|
"current": "temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,rain,showers,snowfall,weather_code,cloud_cover,pressure_msl,wind_speed_10m,wind_direction_10m,wind_gusts_10m",
|
|
"hourly": "temperature_2m,relative_humidity_2m,precipitation_probability,precipitation,weather_code,cloud_cover,pressure_msl,wind_speed_10m,wind_direction_10m,wind_gusts_10m,visibility",
|
|
"daily": "weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset",
|
|
"forecast_days": 7,
|
|
}
|
|
|
|
|
|
def _coord_key(lat: float, lon: float) -> tuple[float, float]:
|
|
return round(lat, 4), round(lon, 4)
|
|
|
|
|
|
async def get_forecast(lat: float, lon: float) -> dict[str, Any]:
|
|
lat_k, lon_k = _coord_key(lat, lon)
|
|
redis_key = f"forecast:{lat_k}:{lon_k}"
|
|
|
|
cached = await redis_get(redis_key)
|
|
if cached:
|
|
return {"source": OPEN_METEO_BASE_URL, "lat": lat, "lon": lon, "data": cached, "cached": True}
|
|
|
|
cached = await get_cached_json("forecast_cache", {"lat": lat_k, "lon": lon_k}, CACHE_TTL_FORECAST)
|
|
if cached:
|
|
await redis_set(redis_key, cached, CACHE_TTL_FORECAST)
|
|
return {"source": OPEN_METEO_BASE_URL, "lat": lat, "lon": lon, "data": cached, "cached": True}
|
|
|
|
data = await fetch_json(
|
|
f"{OPEN_METEO_BASE_URL}/forecast",
|
|
params={"latitude": lat, "longitude": lon, **FORECAST_PARAMS},
|
|
)
|
|
await set_cached_json("forecast_cache", {"lat": lat_k, "lon": lon_k}, data)
|
|
await redis_set(redis_key, data, CACHE_TTL_FORECAST)
|
|
return {"source": OPEN_METEO_BASE_URL, "lat": lat, "lon": lon, "data": data, "cached": False}
|
|
|
|
|
|
async def get_observations(lat: float, lon: float) -> dict[str, Any]:
|
|
lat_k, lon_k = _coord_key(lat, lon)
|
|
redis_key = f"observations:{lat_k}:{lon_k}"
|
|
|
|
cached = await redis_get(redis_key)
|
|
if cached:
|
|
return {"source": BRIGHTSKY_BASE_URL, "lat": lat, "lon": lon, "data": cached, "cached": True}
|
|
|
|
cached = await get_cached_json("observations_cache", {"lat": lat_k, "lon": lon_k}, CACHE_TTL_OBSERVATIONS)
|
|
if cached:
|
|
await redis_set(redis_key, cached, CACHE_TTL_OBSERVATIONS)
|
|
return {"source": BRIGHTSKY_BASE_URL, "lat": lat, "lon": lon, "data": cached, "cached": True}
|
|
|
|
data = await fetch_json(f"{BRIGHTSKY_BASE_URL}/current_weather", params={"lat": lat, "lon": lon})
|
|
await set_cached_json("observations_cache", {"lat": lat_k, "lon": lon_k}, data)
|
|
await redis_set(redis_key, data, CACHE_TTL_OBSERVATIONS)
|
|
return {"source": BRIGHTSKY_BASE_URL, "lat": lat, "lon": lon, "data": data, "cached": False}
|