Skip to main content

Pegelonline (Water Levels)

Heimdall integrates with the German federal Pegelonline REST API (WSV) to provide near-real-time water level data for gauging stations near the current GPS position.

How It Works

  1. The heimdall-pegelonline crate runs a background task (every 5 minutes) that queries the WSV API.
  2. It uses the latest GPS position from TimescaleDB to determine the search center.
  3. Stations are filtered by a whitelist (specific station shortnames) or by radius (default 30 km).
  4. Results are cached in memory, sorted by distance (nearest first).
  5. The cache is served via the REST and GraphQL endpoints below.

Configuration

Add to platform/api/config/default.toml:

[pegelonline]
enabled = false
base_url = "https://pegelonline.wsv.de/webservices/rest-api/v2"
radius_km = 30.0
stations = [
# Whitelist mode: specific station shortnames
"MANNHEIM", "KÖLN", "DUISBURG-RUHRORT",
"HEIDELBERG UP", "FRANKFURT OSTHAFEN",
# Empty list = radius mode
]

Environment override: HEIMDALL__PEGELONLINE__ENABLED=true

Whitelist mode (non-empty stations): searches with a 200 km radius, filters by shortname, and then drops any whitelisted station farther than radius_km from the current position (radius_km acts as a max distance).
Radius mode (stations = []): uses radius_km around current position.

REST Endpoints

MethodPathPermissionDescription
GET/v1/pegel/nearestpegel:readNearest gauging station
GET/v1/pegel/stationspegel:readAll cached stations

Query params: water (waterway name filter), radius (override radius in km).

GraphQL

  • pegelNearest(water: String, radius: Float)GqlPegelStation
  • pegelStations(water: String)[GqlPegelStation]

Response Fields

FieldTypeDescription
station_idstringStation UUID (WSV)
shortnamestringStation shortname (e.g. "MANNHEIM")
longnamestringStation full name
water_shortnamestringWaterway shortname (e.g. "RHEIN")
water_longnamestringWaterway full name
latitudefloatStation latitude
longitudefloatStation longitude
kmfloat?River kilometer
agencystringResponsible WSV agency
level_cmfloat?Current water level in cm (null if unavailable)
trendint?Level trend: -1 falling, 0 stable, 1 rising (null if unavailable)
distance_kmfloatDistance from current GPS position

Example

GET /v1/pegel/nearest?water=RHEIN
{
"station_id": "a26e57c8-d8c9-4d0c-a3ad-2974e7c0e31e",
"shortname": "MANNHEIM",
"longname": "MANNHEIM",
"water_shortname": "RHEIN",
"water_longname": "RHEIN",
"latitude": 49.4875,
"longitude": 8.4660,
"km": 424.0,
"agency": "WSA Mannheim",
"level_cm": 312,
"trend": 0,
"distance_km": 0.3
}

RBAC Permissions

PermissionDescription
pegel:readView water level data

Assigned to: role_admin (wildcard) and role_api_read_only. (Removed from role_developer in migration 20260624 — the developer role is for external API/OAuth management only.)

Frontend Hook

Use the usePegel hook from @elcto/ui:

import { usePegel } from '@elcto/ui';

const { data, loading } = usePegel({ water: 'RHEIN' });
// data: PegelData | null

The hook polls every 5 minutes and retries after 10 seconds on a 404 (no data yet).