217 lines
6.0 KiB
Markdown
217 lines
6.0 KiB
Markdown
# Consigne — Collecte météo Open‑Meteo (Prévisions + Historique)
|
||
|
||
## 1. Objectif
|
||
|
||
Mettre en place une collecte automatique des données Open‑Meteo pour alimenter :
|
||
- une vue calendrier météo (agrégat journalier),
|
||
- une vue détail horaire.
|
||
|
||
Le système doit :
|
||
- récupérer les prévisions sur horizon configurable (`7`, `10`, `16` jours),
|
||
- stocker un cache JSON brut (debug/audit),
|
||
- upserter en SQLite sans duplication,
|
||
- gérer `Europe/Paris` sans décalage de date,
|
||
- permettre un mode historique (`archive`) optionnel.
|
||
|
||
---
|
||
|
||
## 2. Source de données
|
||
|
||
- API prévisions : `https://api.open-meteo.com/v1/forecast`
|
||
- API historique : `https://api.open-meteo.com/v1/archive`
|
||
- Doc : `https://open-meteo.com/en/docs`
|
||
|
||
Toujours envoyer :
|
||
- `timezone=Europe/Paris`
|
||
- `timeformat=iso8601`
|
||
|
||
---
|
||
|
||
## 3. Configuration
|
||
|
||
Créer `config.yml` (et `config.yml.example`) :
|
||
|
||
```yaml
|
||
open_meteo:
|
||
latitude: 45.05
|
||
longitude: 3.48
|
||
timezone: Europe/Paris
|
||
forecast_days: 14
|
||
cache_dir: data/cache
|
||
db_path: data/jardin.db
|
||
wind_strong_kmh: 40
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Requête prévisions (obligatoire)
|
||
|
||
Variables demandées :
|
||
- `hourly`: `temperature_2m,precipitation_probability,precipitation,relative_humidity_2m,wind_speed_10m,wind_direction_10m,cloud_cover,weather_code`
|
||
- `daily`: `temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,wind_speed_10m_max,sunrise,sunset,weather_code`
|
||
|
||
Exemple :
|
||
|
||
```bash
|
||
curl -s "https://api.open-meteo.com/v1/forecast?latitude=45.05&longitude=3.48&hourly=temperature_2m,precipitation_probability,precipitation,relative_humidity_2m,wind_speed_10m,wind_direction_10m,cloud_cover,weather_code&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,wind_speed_10m_max,sunrise,sunset,weather_code&timezone=Europe/Paris&timeformat=iso8601&forecast_days=14"
|
||
```
|
||
|
||
Règles :
|
||
- `forecast_days` doit toujours être explicite.
|
||
- Lire et logger `hourly_units` et `daily_units`.
|
||
|
||
---
|
||
|
||
## 5. Requête archive (optionnelle)
|
||
|
||
Exemple :
|
||
|
||
```bash
|
||
curl -s "https://api.open-meteo.com/v1/archive?latitude=45.05&longitude=3.48&start_date=2026-01-01&end_date=2026-01-31&daily=temperature_2m_max,temperature_2m_min,precipitation_sum&hourly=temperature_2m,precipitation,weather_code&timezone=Europe/Paris&timeformat=iso8601"
|
||
```
|
||
|
||
Règles :
|
||
- exécuter par tranche (mensuelle recommandée),
|
||
- source marquée `archive`.
|
||
|
||
---
|
||
|
||
## 6. Stockage
|
||
|
||
### 6.1 Cache JSON brut
|
||
|
||
Fichiers à écrire à chaque run :
|
||
- `data/cache/openmeteo_forecast_<YYYY-MM-DDTHHMMSS>.json`
|
||
- `data/cache/openmeteo_archive_<YYYY-MM-DDTHHMMSS>.json` (si archive)
|
||
|
||
Purge :
|
||
- conserver les `30` derniers fichiers par type.
|
||
|
||
### 6.2 SQLite normalisée
|
||
|
||
Table `meteo_daily` :
|
||
- `date TEXT NOT NULL`
|
||
- `source TEXT NOT NULL` (`forecast` | `archive`)
|
||
- `tmin_c REAL`
|
||
- `tmax_c REAL`
|
||
- `precip_mm REAL`
|
||
- `precip_prob_max_pct REAL`
|
||
- `wind_max_kmh REAL`
|
||
- `sunrise_local TEXT`
|
||
- `sunset_local TEXT`
|
||
- `weather_code INTEGER`
|
||
- `fetched_at TEXT NOT NULL`
|
||
- `lat REAL NOT NULL`
|
||
- `lon REAL NOT NULL`
|
||
- `elevation REAL`
|
||
- `PRIMARY KEY (date, source)`
|
||
|
||
Table `meteo_hourly` :
|
||
- `datetime_local TEXT NOT NULL` (`YYYY-MM-DDTHH:MM`)
|
||
- `source TEXT NOT NULL` (`forecast` | `archive`)
|
||
- `temp_c REAL`
|
||
- `precip_mm REAL`
|
||
- `precip_prob_pct REAL`
|
||
- `humidity_pct REAL`
|
||
- `wind_kmh REAL`
|
||
- `wind_dir_deg REAL`
|
||
- `cloud_pct REAL`
|
||
- `weather_code INTEGER`
|
||
- `fetched_at TEXT NOT NULL`
|
||
- `lat REAL NOT NULL`
|
||
- `lon REAL NOT NULL`
|
||
- `elevation REAL`
|
||
- `PRIMARY KEY (datetime_local, source)`
|
||
|
||
Index recommandés :
|
||
- `idx_meteo_daily_date ON meteo_daily(date)`
|
||
- `idx_meteo_hourly_dt ON meteo_hourly(datetime_local)`
|
||
|
||
---
|
||
|
||
## 7. Règles d’upsert
|
||
|
||
- `forecast` : `INSERT ... ON CONFLICT (...) DO UPDATE` (les prévisions évoluent).
|
||
- `archive` : `INSERT ... ON CONFLICT (...) DO NOTHING` (on fige l’observé).
|
||
|
||
Conflits :
|
||
- `meteo_daily` : `(date, source)`
|
||
- `meteo_hourly` : `(datetime_local, source)`
|
||
|
||
---
|
||
|
||
## 8. Contrôles qualité obligatoires
|
||
|
||
Après récupération JSON :
|
||
- `daily.time` contient au moins `7` jours,
|
||
- longueurs cohérentes des tableaux `hourly`,
|
||
- pour chaque jour : `tmin_c <= tmax_c`,
|
||
- présence de `timezone == Europe/Paris`.
|
||
|
||
En cas d’échec :
|
||
- logger erreur explicite,
|
||
- conserver le JSON brut,
|
||
- sortie non fatale avec code d’erreur contrôlé.
|
||
|
||
---
|
||
|
||
## 9. Champs attendus pour l’UI
|
||
|
||
### Vue calendrier (jour)
|
||
- `date`
|
||
- `tmin_c`, `tmax_c`
|
||
- `precip_mm`
|
||
- `precip_prob_max_pct`
|
||
- `weather_code`
|
||
- `sunrise_local`, `sunset_local`
|
||
- badges calculés :
|
||
- `gel` si `tmin_c <= 0`
|
||
- `pluie` si `precip_mm > 0`
|
||
- `vent_fort` si `wind_max_kmh >= wind_strong_kmh`
|
||
|
||
### Vue détail (horaire)
|
||
- `datetime_local`
|
||
- `temp_c`
|
||
- `precip_prob_pct`
|
||
- `precip_mm`
|
||
- `wind_kmh`, `wind_dir_deg`
|
||
- `humidity_pct`
|
||
- `cloud_pct`
|
||
- `weather_code`
|
||
|
||
---
|
||
|
||
## 10. Livrables
|
||
|
||
- `prevision meteo/scripts/fetch_openmeteo_forecast.py`
|
||
- `prevision meteo/scripts/fetch_openmeteo_archive.py` (optionnel)
|
||
- `prevision meteo/db/schema.sql`
|
||
- `prevision meteo/config.yml.example`
|
||
|
||
---
|
||
|
||
## 11. Exécution planifiée
|
||
|
||
- Prévisions : tous les jours à `06:10` Europe/Paris.
|
||
- Archive (optionnel) : tous les jours à `06:20` pour `J-1`.
|
||
|
||
Exemple cron :
|
||
|
||
```cron
|
||
10 6 * * * /usr/bin/python3 /path/prevision\ meteo/scripts/fetch_openmeteo_forecast.py
|
||
20 6 * * * /usr/bin/python3 /path/prevision\ meteo/scripts/fetch_openmeteo_archive.py --yesterday
|
||
```
|
||
|
||
---
|
||
|
||
## 12. Critères d’acceptation
|
||
|
||
- Une exécution quotidienne met à jour `forecast` sans duplication.
|
||
- Le calendrier UI affiche au minimum : Tmin/Tmax, pluie, probabilité pluie, weather code.
|
||
- Le détail horaire est consultable pour un jour donné.
|
||
- Les dates/heures sont correctes en `Europe/Paris`.
|
||
- Les caches JSON sont présents et exploitables pour debug.
|
||
|
||
|
||
|
||
https://api.open-meteo.com/v1/forecast?latitude=45.1412&longitude=4.0736&hourly=temperature_2m,weather_code,cloud_cover,evapotranspiration,precipitation,precipitation_probability,rain,snowfall,wind_speed_10m,relative_humidity_2m,wind_direction_10m,soil_temperature_0cm,soil_temperature_6cm,soil_moisture_1_to_3cm,soil_moisture_3_to_9cm,sunshine_duration&forecast_days=14 |