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
- The
heimdall-pegelonlinecrate runs a background task (every 5 minutes) that queries the WSV API. - It uses the latest GPS position from TimescaleDB to determine the search center.
- Stations are filtered by a whitelist (specific station shortnames) or by radius (default 30 km).
- Results are cached in memory, sorted by distance (nearest first).
- 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 and filters by shortname.
Radius mode (stations = []): uses radius_km around current position.
REST Endpoints
| Method | Path | Permission | Description |
|---|---|---|---|
| GET | /v1/pegel/nearest | pegel:read | Nearest gauging station |
| GET | /v1/pegel/stations | pegel:read | All cached stations |
Query params: water (waterway name filter), radius (override radius in km).
GraphQL
pegelNearest(water: String, radius: Float)→GqlPegelStationpegelStations(water: String)→[GqlPegelStation]
Response Fields
| Field | Type | Description |
|---|---|---|
station_name | string | Station shortname (e.g. "MANNHEIM") |
water_name | string | Waterway name (e.g. "RHEIN") |
km | float | River kilometer |
latitude | float | Station latitude |
longitude | float | Station longitude |
value | float? | Current measurement value |
unit | string | Measurement unit (e.g. "cm") |
timestamp | string | Measurement timestamp (ISO 8601) |
state | string? | low, normal, high, unknown, commented, out-dated |
distance_km | float | Distance from current GPS position |
Example
GET /v1/pegel/nearest?water=RHEIN
{
"station_name": "MANNHEIM",
"water_name": "RHEIN",
"km": 424.0,
"latitude": 49.4875,
"longitude": 8.4660,
"value": 312,
"unit": "cm",
"timestamp": "2026-06-22T10:00:00Z",
"state": "normal",
"distance_km": 0.3
}
RBAC Permissions
| Permission | Description |
|---|---|
pegel:read | View water level data |
Assigned to: role_admin, role_developer, role_api_read_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).