banyaro/docs/DWD_RAIN_FORECAST_PLAN.md
rene 72ee339860 Docs: DWD-Regen-Vorhersage-Pipeline gescoppt (Datenformat verifiziert)
DWD RV (composite/rv, kostenlos, alle 5 Min, 25 Frames 0-120min). Format
verifiziert: 194-Byte-ASCII-Header + 1200×1100 uint16 LE, Wert=&0x0FFF×0.01mm,
&0x2000=kein-Daten (PoC: Decode trivial, kein wradlib nötig). Pipeline:
fetch→decode→kolorieren→reprojizieren(DE1200→3857)→Kacheln→PMTiles/Cron 5min;
Frontend hängt Forecast-Frames rechts von 'jetzt' in die Timeline. Knackpunkt:
Georeferenzierung (PoC nötig).
2026-06-05 20:53:51 +02:00

56 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DWD Regen-Vorhersage (Radar-Nowcast) — Scoping-Plan
**Status:** gescoppt + Datenformat verifiziert (2026-06-05). Umsetzung offen.
**Ziel:** Verlässliche, längere Regen-**Vorhersage** als animiertes Karten-Overlay (bis +2 h) statt RainViewers
unzuverlässigem 30-Min-Nowcast (der oft leer ist). Self-hosted wie die Basemap — passt zur Tile-Server-Philosophie.
## Quelle: DWD RV (Composite RV) — kostenlos, kein API-Key
- `https://opendata.dwd.de/weather/radar/composite/rv/DE1200_RV<YYMMDDHHMM>.tar.bz2`
- **Alle 5 Min** publiziert. Jedes Archiv = ein Vorhersage-Lauf mit **25 Frames** `_000``_120`
(**0 bis +120 Min**, 5-Min-Schritte), je ~2,5 MB unkomprimiert (~1 MB als .tar.bz2).
- **Format (verifiziert):** RADOLAN-Binär. 194-Byte-ASCII-Header bis `ETX (0x03)`, dann **1200×1100 uint16
little-endian** (= 2.640.000 Byte). Header-Felder: `PR E-02` (0,01 mm), `INT 5` (5-Min-Summe),
`GP1200x1100`, `VV<lead>` (Lead-Time). **Wert = `raw & 0x0FFF` × 0,01 mm/5min; `raw & 0x2000` = kein Daten.**
→ Decode trivial, **kein wradlib nötig** (PoC: 1,32 Mio Zellen geparst, Regen korrekt erkannt).
- **Gitter/Projektion:** DE1200 (1 km), polar-stereografisch, fest georeferenziert (Eckkoordinaten dokumentiert;
wradlib `get_radolan_grid` ODER GDAL mit dem bekannten RADOLAN-PROJ-String).
- **Abdeckung:** Deutschland + Randbereiche (reicht etwas nach AT/CH/Nachbarn, aber DE-zentriert).
Voll-AT/CH bräuchte ACG/MeteoSwiss → out of scope.
## Pipeline (Server-seitig, Cron alle 5 Min — analog zum OSM-POI-Job)
1. **Fetch** neueste `DE1200_RV<time>.tar.bz2` (Verzeichnis-Listing → letzte Datei).
2. **Entpacken** → 25 RADOLAN-Grids.
3. **Decode** je Grid → 2D-Niederschlags-Array (eigener ~15-Z.-Parser, PoC-bewiesen).
4. **Kolorieren** → RGBA (transparent bei 0/kein-Regen; Radar-Farbskala wie das aktuelle Overlay).
5. **Reprojektion** DE1200 → EPSG:3857 + **Kacheln z09** (Radar ist grob 1 km → höher zoomen bringt nichts).
Tooling: **GDAL** (gdalwarp + gdal2tiles) oder rasterio/rio-tiler.
6. **Output:** 25 Frame-Tilesets — je eine kleine **PMTiles** pro Lead-Time (`rv_000.pmtiles``rv_120.pmtiles`)
ODER XYZ-PNG. Nur neuesten Lauf behalten (atomarer Swap wie dach.pmtiles). Plus **`rv_manifest.json`**
(Lauf-Zeit, Lead-Times, Tile-URL-Muster).
7. **Ausliefern** von der DS (wie `/tiles`).
## Frontend (bestehende Radar-Timeline erweitern, map.js)
- Manifest laden → DWD-Vorhersage-Frames (0…+120 Min) **rechts von „jetzt"** in die Timeline einhängen
(die Forecast-Markierung `is-forecast` + Scrub/Play gibt es schon).
- **Vergangenheit:** weiter RainViewer (einfach) ODER DWD RADOLAN-RY (5-Min-Analyse) für all-DWD-Konsistenz.
- Quelle pro Frame: Vergangenheit = RainViewer-Tiles, Vorhersage = DWD-PMTiles (byt-/raster-Source).
## Aufwand & offene Entscheidungen
- **Decode:** trivial (verifiziert). **Projektion:** der einzige Knackpunkt — DE1200-Georeferenzierung korrekt
nach 3857 (wradlib nimmt's ab, oder bekannter PROJ-String + Eckkoordinaten). **PoC nötig:** 1 Frame →
Tiles → über MapLibre rendern und gegen RainViewer/echten Regen gegenchecken (Passgenauigkeit).
- **Tiling alle 5 Min × 25 Frames:** z09 für DE ist schnell (Sekunden~1 Min auf der DS). Last beachten
(läuft neben Immich & Co.); ggf. nur jeden 2. Lead-Time tilen (10-Min-Schritte) zum Sparen.
- **Speicher:** Radar-Tiles sind dünn/transparent → wenige MB pro Lauf.
- **Cron alle 5 Min:** neuer Container/Job (analog `docker-compose.osm.yml`); ⚠️ `--remove-orphans`-Falle.
- **Entscheidungen:** (a) Vergangenheit RainViewer vs. DWD-RY; (b) PMTiles-pro-Frame vs. XYZ; (c) Farbskala;
(d) Zoom-Range (z09) + Lead-Schrittweite (5 vs 10 Min); (e) Container-Stack (GDAL/Python) auf der DS.
- **Abhängigkeit:** Docker auf der DS.
## Nächste Schritte
1. **PoC**: 1 RV-Archiv → 1 Frame decode → kolorieren → reprojizieren → 1 PMTiles → headless über MapLibre
rendern. **Kernfrage: stimmt die Georeferenzierung?** (Wenn ja, ist der Rest Fleißarbeit.)
2. Pipeline-Skript (fetch→decode→tile→deploy) + Cron-Job + Manifest.
3. Frontend: Manifest in die Timeline einhängen (Vorhersage-Frames rechts von „jetzt").
Siehe `docs/TILE_SERVER_HANDOVER.md` (Tile-Infra), Memory `project_tile_server_maintenance`.