Backend Monitorink: serveur PNG (Claude usage + météo + HA)

This commit is contained in:
2026-06-15 10:49:31 +02:00
commit bc4cf89a4b
16 changed files with 792 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
"""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, emoji). Suffisant pour un dashboard e-ink.
WMO = {
0: ("Dégagé", ""),
1: ("Peu nuageux", "🌤"),
2: ("Nuageux", ""),
3: ("Couvert", ""),
45: ("Brouillard", "🌫"),
48: ("Brouillard givrant", "🌫"),
51: ("Bruine légère", "🌦"),
53: ("Bruine", "🌦"),
55: ("Bruine forte", "🌦"),
61: ("Pluie faible", "🌧"),
63: ("Pluie", "🌧"),
65: ("Pluie forte", "🌧"),
71: ("Neige faible", "🌨"),
73: ("Neige", "🌨"),
75: ("Neige forte", "🌨"),
80: ("Averses", "🌦"),
81: ("Averses", "🌧"),
82: ("Fortes averses", ""),
95: ("Orage", ""),
96: ("Orage + grêle", ""),
99: ("Orage + grêle", ""),
}
@dataclass
class Weather:
ok: bool
error: str | None = None
temp: float | None = None
feels_like: float | None = None
label: str = ""
icon: 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, icon = WMO.get(code, ("", "·"))
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,
icon=icon,
temp_min=_first("temperature_2m_min"),
temp_max=_first("temperature_2m_max"),
precip_prob=_first("precipitation_probability_max"),
)