Datenpipeline & Datenquellen
← zurück zum Hub
Datenquelle¶
PEGELONLINE der Wasserstraßen- und Schifffahrtsverwaltung des Bundes (WSV): https://www.pegelonline.wsv.de
Zwei Schnittstellen werden genutzt:
1. Live-API (/webservices/rest-api/v2/...) — letzte 30 Tage als JSON
2. Historisches Archiv (/gast/historische-zeitreihen/prepare-download) — Daten seit 01.01.2000 als ZIP-CSV
Stationen und UUIDs¶
7 Stationen werden gepollt — 6 am Rhein-Hauptlauf zwischen Speyer und Mainz, plus die Mündungspegel von Neckar und Main:
| Tag | UUID | Gewässer | km | Pegelnr | Betreiber | Q? |
|---|---|---|---|---|---|---|
SPEYER |
2cb8ae5b-c5c9-4fa8-bac0-bb724f2754f4 |
RHEIN | 400.61 | 23700600 | WSA Mannheim | ✓ |
MANNHEIM |
57090802-c51a-4d09-8340-b4453cd0e1f5 |
RHEIN | 424.733 | 23700700 | WSA Mannheim | ✗ |
MANNHEIM_NECKAR |
25582d3f-dc5f-4c70-bd08-e84fd13201ca |
NECKAR | 3.1 | 23800900 | WSA Mannheim | ✗ |
WORMS |
844a620f-f3b8-4b6b-8e3c-783ae2aa232a |
RHEIN | 443.37 | 23900200 | WSA Mannheim | ✓ |
NIERSTEIN |
d28e7ed1-3317-41c5-bec6-725369ed1171 |
RHEIN | 480.606 | 23900600 | WSA Mannheim | ✗ |
MAINZ |
a37a9aa3-45e9-4d90-9df6-109f3a28a5af |
RHEIN | 498.27 | 25100100 | WSA Bingen | ✓ |
RAUNHEIM |
db1684c1-7ffc-4e8a-b8cf-8240a0d03519 |
MAIN | 12.213 | 24900108 | HLNUG/Aschaffenburg | ✓ |
PNP-Werte (Pegelnullpunkt, m über NHN)¶
| Station | PNP | Gültig ab |
|---|---|---|
| Worms | 84.112 | 2017-07-18 |
| Nierstein | 80.167 | 2017-07-18 |
| Mainz | 78.373 | 2019-11-01 ⚠ Sprung — älterer PNP nicht dokumentiert |
| Speyer / Mannheim / Mannheim-Neckar / Raunheim | unbekannt | TODO: BfG-Anfrage |
Stammdaten sind im InfluxDB-Bucket rhein_meta als Measurement station_meta abgelegt.
Live-Poller¶
Pfad: /opt/rhein/poller/poller.py
# vereinfachte Logik
while True:
for uuid, station_tag, params in STATIONS:
for param in params: # 'W' oder 'Q'
url = f'{API}/stations/{uuid}/{param}/currentmeasurement.json'
data = http.get(url).json()
ts_utc = parse_iso(data['timestamp']).astimezone(UTC)
value = float(data['value'])
influx.write(Point('pegel')
.tag('station', station_tag)
.tag('parameter', param)
.tag('source', 'pegelonline')
.field('value', value)
.time(ts_utc, ns=True))
sleep(900) # 15 Minuten
Pro Cycle: 11 Datenpunkte (7 W + 4 Q-fähige Stationen).
Pegelonline-Archiv-Endpoint (Reverse-Engineered)¶
Die offizielle API liefert nur die letzten 30 Tage. Das Archiv seit 01.01.2000 wird über ein anderes (nicht im API-Swagger dokumentiertes) Endpoint angeboten:
Schritt 1: POST → 303 Redirect mit Token-URL¶
curl -i -X POST "https://www.pegelonline.wsv.de/gast/historische-zeitreihen/prepare-download" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Referer: https://www.pegelonline.wsv.de/gast/stammdaten?pegelnr=23900200" \
--data-urlencode "uuid=844a620f-f3b8-4b6b-8e3c-783ae2aa232a" \
--data-urlencode "parameter=WASSERSTAND ROHDATEN" \
--data-urlencode "start=2024-01-01T00:00:00.000Z" \
--data-urlencode "end=2024-12-31T23:59:59.000Z" \
--data-urlencode "format=csv"
Antwort: HTTP 303 mit Header
Location: /gast/historische-zeitreihen/download?filename=pegelonline-worms-W-20240101-20240101.zip-<token>
Schritt 2: GET der Location-URL → ZIP¶
curl -O "https://www.pegelonline.wsv.de/gast/historische-zeitreihen/download?filename=pegelonline-worms-W-20240101-20240101.zip-<token>"
Liefert eine ZIP-Datei mit:
- pegelonline-<station>-<W|Q>-<startYYYYMMDD>-<endYYYYMMDD>.csv — die Daten (timestamp;value, MEZ ganzjährig, 15-min-Auflösung)
- nutzungsbedingungen.txt
- zeitreiheninformation.txt
Wichtige Quirks¶
-X POSTmit curl mit-Lschlägt fehl (405) — curl folgt 303 mit POST. Stattdessen den Redirect manuell holen oder ohne-X.- Keine Cookies/Sessions nötig — der Token in der URL authentisiert.
- Server braucht ~5-15 sek für die Datei-Erstellung. Bei 404 noch mal versuchen.
parameter-String je Behörde unterschiedlich:- WSA-Stationen (Worms, Nierstein, Mainz, Speyer, Mannheim, Mannheim-Neckar):
WASSERSTAND ROHDATEN(mit Leerzeichen!) undABFLUSS_ROHDATEN - HLNUG-Stationen (Raunheim):
WASSERSTAND ROHDATEN, aber Q istABFLUSS(ohne ROHDATEN)
InfluxDB-Buckets¶
| Bucket | Retention | Inhalt |
|---|---|---|
rhein_raw |
∞ | Rohdaten W, Q (Live + Archiv-Backfill) |
rhein_meta |
∞ | Stationsstammdaten (UUIDs, PNP, km, Lat/Lon) |
rhein_derived |
10 Jahre | Abgeleitete Größen (NHN, Gefälle, CCF, ACF, Spektrum, Muskingum/ARX-Vorhersagen) |
rhein_forecast |
2 Jahre | reservoirt für Live-Vorhersage-Cron (noch nicht aktiv) |
Schema rhein_raw¶
pegel,station=WORMS,parameter=W,source=pegelonline value=99.0 1714745452000000000
pegel,station=WORMS,parameter=Q,source=pegelonline value=786.0,state_mnw_mhw="normal" 1714745452000000000
sourceunterscheidetpegelonline(Live-Poller) vspegelonline_archive(Backfill).- Timestamp in UTC ns, vor dem Schreiben aus Lokalzeit konvertiert.
Backfill¶
Pfad: /opt/rhein/poller/backfill.py
Lädt für alle 7 Stationen × verfügbare Parameter den gewünschten Zeitraum:
docker exec \
-e BACKFILL_START="2000-01-01T00:00:00.000Z" \
-e BACKFILL_END="2026-05-03T23:59:59.000Z" \
-e INFLUXDB_URL=http://influxdb:8086 \
-e INFLUXDB_TOKEN=$TOKEN \
-e INFLUXDB_ORG=$ORG \
-e INFLUXDB_BUCKET=rhein_raw \
rhein-poller python /app/backfill.py
Bisherige Backfill-Stände:
- 2016–2026 (10 Jahre): 3 986 516 Punkte
- 2000–2016 (16 Jahre): 4 634 316 Punkte
- Gesamt: ~8,6 Mio Datenpunkte in rhein_raw (96 MB Influx-Disk)
Datenverfügbarkeits-Auffälligkeiten¶
- MANNHEIM (Rhein) hat erst ab ~2010 Daten — ein 2000–2016-Backfill ergab dort nur 146k Punkte (≈ 4 Jahre × 35040), nicht die erwarteten 561k. Davor gibt es entweder keine 15-min-Werte oder andere Speicherform.
- MAINZ-W-Backfill 2000–2016 schlug zunächst fehl wegen InfluxDB-Read-Timeout — wurde manuell nachgeholt.
- RAUNHEIM/Q schlug zunächst mit
ABFLUSS_ROHDATENfehl, geht mitABFLUSS(HLNUG-Quirk).
Bekannte TODOs¶
- PNP-Werte für 4 Stationen bei BfG erfragen (
Datenstelle-M1@bafg.de) - Mainz-PNP vor 2019-11-01 für lückenlose NHN-Reihe (gleiche Quelle)
- Mannheim-Neckar Q: entweder Rockenau (Neckar km 60.7, UUID
4c00a166-...) zusätzlich aufnehmen oder Q via DGJ-Abflusskurve aus W ableiten - Live-Vorhersage-Cron, der täglich 12-h-Mainz-Prognose ins
rhein_forecast-Bucket schreibt
Phase 6c — Erweiterung auf 11 Pegel (2026-05-05)¶
Vier zusätzliche Oberlauf-Pegel wurden integriert, um den Vorhersage-Horizont auf 24 h zu erweitern und die Karte-Visualisierung von Maxau bis Mainz auszudehnen:
| Station | UUID | km | hat Q? |
|---|---|---|---|
| Iffezheim | b02be240-1364-4c97-8bb6-675d7d842332 |
336.20 | ✓ |
| Plittersdorf | 6b774802-fcb5-49ae-8ecb-ecaf1a278b1c |
340.20 | ✓ |
| Maxau | b6c6d5c8-e2d5-4469-8dd8-fa972ef7eaea |
362.33 | ✓ — wichtigster Vorhersage-Pegel |
| Philippsburg | 88e972e1-88a0-4eb9-847c-0925e5999a46 |
389.33 | – |
Backfill 2018-2024 für die 4 neuen Pegel: ~2 Mio. zusätzliche Punkte. Live-Polling alle 15 min wie bisher.
Achtung Philippsburg-Latenz: Pegelonline-Q für Philippsburg wird nur einmal täglich aktualisiert (~12 h Latenz). Daher wurde Philippsburg aus den ARX-Vorhersage-Features entfernt — die anderen 6 Pegel reichen für 24-h-Skill.
charvalues + PNP (Phase 6d, 2026-05-06)¶
Skript /opt/rhein/poller/charvalues.py holt einmalig pro Pegel:
- MNW Mittleres Niedrigwasser
- MW Mittelwasser
- MHW Mittleres Hochwasser
- NW, HW, HSW (sehr hoch), GlW (Gleichwertige Wasserstand) wenn verfügbar
- PNP in m NHN (Pegelnullpunkt aus
gaugeZero-Property der Pegelonline-Stations-API)
Alle Werte werden in rhein_meta.station_meta als Felder gespeichert und von propagate_v3.py für die lokale MNW/MHW-Skala (Karten-Färbung) sowie fit_muskingum.py für die MW-Anomalie-Korrektur verwendet.
PNP-Tabelle (alle 11 Pegel)¶
| Station | PNP [m NHN] | gültig ab |
|---|---|---|
| Iffezheim | 110.019 | 2018-11-01 |
| Plittersdorf | 106.71 | 2018-11-01 |
| Maxau | 97.721 | 2017-07-18 |
| Philippsburg | 90.561 | 2017-07-18 |
| Speyer | 88.467 | 2017-07-18 |
| Mannheim Neckar | 84.787 | 2017-07-18 |
| Mannheim | 85.117 | 2017-07-18 |
| Worms | 84.112 | 2017-07-18 |
| Nierstein | 80.167 | 2017-07-18 |
| Mainz | 78.373 | 2019-11-01 |
| Raunheim | 82.879 | 2017-07-18 |
Damit ist das BfG-PNP-TODO aus der ursprünglichen Liste entfallen — Pegelonline liefert PNP direkt.
InfluxDB-Buckets (Stand 2026-05-06)¶
| Bucket | Retention | Inhalt |
|---|---|---|
rhein_raw |
∞ | Beobachtungen aller 11 Pegel × W/Q × 15-min-Auflösung |
rhein_meta |
∞ | Stammdaten: lat/lon/km/PNP/MNW/MW/MHW/HW/HSW pro Pegel + Segment-Metadaten |
rhein_derived |
10 y | Phase-2-Resultate (NHN, Gefälle, CCF, ACF), Muskingum-Parameter, Multi-Event-Rückblickende Validierung-Summary, propagate_v3-Output |
rhein_forecast |
2 y | ARX-v2-Vorhersagen pro Lead 1/4/8/12/16/20/24 h, rhein_segment_forecast |
Cron-Jobs (Hetzner-Server)¶
/etc/cron.d/rhein-phase6c:
*/15 * * * * propagate_v3.py # Hauptrhein + Altrhein Karten-State
*/15 * * * * animation_state.py # Time-Slider-Snapshots
*/15 * * * * propagate.py --since-h 1 # Legacy Phase-6-Karte (Backup)
*/15 * * * * hw_alert.py # Pushover-HW-Warner
5 * * * * forecast_cron_v2.py # ARX-v2 7-Lead-Forecast
5 * * * * forecast_cron.py # Legacy Phase-6b-Forecast
/etc/cron.d/duckdns-rhein aktualisiert IP alle 5 min.
Phase-7-Roadmap (Datenpipeline)¶
7.1 — DWD-Niederschlag-Vorhersage als ARX-Feature¶
API: Brightsky (DWD-Wrapper, JSON, precipitation mm/h, precipitation_probability_6h %)
Stations-Auswahl (für Schwarzwald-Einzugsgebiet): - Karlsruhe (zentrales Oberrhein-Wetter) - Freudenstadt (Schwarzwald-Höhe) - Triberg (Schwarzwald-Niederschlag)
Geplante Pipeline:
1. poller_brightsky.py — alle 60 min Niederschlag-Beobachtung + 0-48h-Vorhersage holen
2. Bucket rhein_weather (neu) für 1h-Niederschlag-Reihen
3. ARX-v4-Training mit zusätzlichen Features PRECIP_KARLSRUHE_lagX, PRECIP_FORECAST_LEAD_6h
4. Erwartung: Lead 48 h NSE > 0.8
7.2 — Saint-Venant-Routing (Phase 7.2)¶
Querschnittsdaten für die 8 Reaches bei der Wasserstraßen- und Schifffahrtsverwaltung (WSV) anfragen — ggf. auch DGM (Digitales Geländemodell) verfügbar.
7.3 — BfG-WaVo-Vergleich¶
Keine öffentliche API. Skip oder akademische Anfrage.