"""Météo via Open-Meteo (gratuit, sans clé API).""" from __future__ import annotations from dataclasses import dataclass import httpx from config import config API_URL = "https://api.open-meteo.com/v1/forecast" # Codes WMO -> (libellé court FR, kind). `kind` pilote le glyphe 1-bit dessiné côté # template (clear/partly/cloudy/fog/rain/snow/storm) : pas d'emoji couleur sur e-ink. WMO = { 0: ("Dégagé", "clear"), 1: ("Peu nuageux", "partly"), 2: ("Nuageux", "partly"), 3: ("Couvert", "cloudy"), 45: ("Brouillard", "fog"), 48: ("Brouillard givrant", "fog"), 51: ("Bruine légère", "rain"), 53: ("Bruine", "rain"), 55: ("Bruine forte", "rain"), 61: ("Pluie faible", "rain"), 63: ("Pluie", "rain"), 65: ("Pluie forte", "rain"), 71: ("Neige faible", "snow"), 73: ("Neige", "snow"), 75: ("Neige forte", "snow"), 80: ("Averses", "rain"), 81: ("Averses", "rain"), 82: ("Fortes averses", "storm"), 95: ("Orage", "storm"), 96: ("Orage + grêle", "storm"), 99: ("Orage + grêle", "storm"), } @dataclass class Weather: ok: bool error: str | None = None temp: float | None = None feels_like: float | None = None label: str = "" kind: str = "" temp_min: float | None = None temp_max: float | None = None precip_prob: int | None = None async def fetch_weather() -> Weather: params = { "latitude": config.weather_lat, "longitude": config.weather_lon, "current": "temperature_2m,apparent_temperature,weather_code", "daily": "temperature_2m_max,temperature_2m_min,precipitation_probability_max", "timezone": config.timezone, "forecast_days": 1, } try: async with httpx.AsyncClient(timeout=15) as client: resp = await client.get(API_URL, params=params) resp.raise_for_status() data = resp.json() except httpx.HTTPError as exc: return Weather(ok=False, error=f"réseau: {exc}") cur = data.get("current", {}) daily = data.get("daily", {}) code = int(cur.get("weather_code", -1)) label, kind = WMO.get(code, ("—", "cloudy")) def _first(key: str): vals = daily.get(key) or [] return vals[0] if vals else None return Weather( ok=True, temp=cur.get("temperature_2m"), feels_like=cur.get("apparent_temperature"), label=label, kind=kind, temp_min=_first("temperature_2m_min"), temp_max=_first("temperature_2m_max"), precip_prob=_first("precipitation_probability_max"), )