High-precision rain radar integration for Home Assistant. Uses DWD (Deutscher Wetterdienst) radar data to provide hyperlocal precipitation nowcasting with 1.1 km spatial and 5-minute temporal resolution.
- Real-time precipitation β Current rain intensity at your exact location from radar data
- 2-hour nowcast β 5-minute resolution precipitation forecast using DWD RADVOR extrapolation
- Custom 6-hour optical-flow extension β Multi-pair TREC motion estimation with sub-pixel refinement extends the forecast beyond DWD's 2 h horizon
- Smart rain end estimate β Tracks rain field movement to predict when rain stops
- Hyperlocal β 1.1 km grid resolution via polar stereographic projection, not just the nearest weather station
- Precipitation type detection β Distinguishes rain, sleet, freezing rain, snow and likely hail using temperature
- Alert sensors β Rain imminent, severe weather, winter weather, and extended dry spell binary sensors for automations and push notifications
- Persistent statistics β Today/yesterday rainfall, dry streak, last rain timestamp and a 30-day history ring buffer
- Camera entity β Native HA camera showing a rendered radar crop around your location with motion arrow overlay
- Interactive radar map β Leaflet-based dark map with DWD WMS radar overlay, geo-scaled motion arrow showing 6 h rain field trajectory with hour ticks
- Custom Lovelace card β Vanilla-JS card with bar chart, status banner and 6 h tail
- Multiple sensors β Current rate, intensity class, type, rain start/end timing, totals, maximums, daily aggregates
- Four data sources β Auto (default), DWD raw radar, Bright Sky API, or Open-Meteo (global)
- No API key needed β All backends are free; DWD Open Data is unlimited
- No external dependencies β Pure Python stdlib parsing (no numpy/h5py/pysteps required)
- Robust motion tracking β Multi-pair averaged TREC estimation with parabolic sub-pixel interpolation and temporal EMA smoothing β the arrow doesn't jitter between updates
| Sensor | Type | Description |
|---|---|---|
| Current precipitation | sensor |
Current precipitation rate (mm/h) |
| Precipitation intensity | sensor |
Classification: none / light / moderate / heavy / violent |
| Precipitation type | sensor |
rain / sleet / freezing_rain / snow / hail_likely / unknown |
| Rain starts in | sensor |
Minutes until rain begins (null if dry forecast) |
| Rain ends in | sensor |
Minutes until rain stops β extrapolates beyond 2h via movement tracking |
| Rain starts at | sensor |
Absolute clock time when rain is expected to start (timestamp) |
| Rain ends at | sensor |
Absolute clock time when rain is expected to stop (timestamp) |
| Max precipitation (1h) | sensor |
Peak precipitation rate in next 60 minutes |
| Max precipitation (2h) | sensor |
Peak precipitation rate in next 120 minutes |
| Total precipitation (1h) | sensor |
Accumulated precipitation in next 60 minutes (mm) |
| Total precipitation (2h) | sensor |
Accumulated precipitation in next 120 minutes (mm) |
| Precipitation today | sensor |
Accumulated precipitation since UTC midnight (mm) |
| Precipitation yesterday | sensor |
Total precipitation on the previous UTC day (mm) |
| Dry streak | sensor |
Hours since the last rain >= 0.1 mm/h |
| Last rain at | sensor |
Timestamp of the most recent rainy update |
| Raining | binary_sensor |
Whether it's currently raining |
| Rain expected | binary_sensor |
Whether rain is expected in the next 2 hours |
| Rain imminent | binary_sensor |
Rain expected within 30 minutes (alert trigger) |
| Severe weather | binary_sensor |
Heavy/violent rain or hail expected |
| Winter weather | binary_sensor |
Snow, sleet, or freezing rain detected |
| Extended dry spell | binary_sensor |
No rain for 7+ days |
| Radar image | camera |
Rendered radar crop with motion arrow overlay |
The four alert binary sensors are designed for wall display notifications and push automations. Each carries relevant attributes (e.g., rain_starts_in_minutes, max_precipitation_mm_h, precipitation_type) so notification templates stay self-contained. Reference notification card YAML is included in dashboard/notification-cards.yaml.
The "Rain ends in" sensor uses a multi-tier approach:
| Situation | Display | Source |
|---|---|---|
| Rain stops within 2h | 45 min |
RADVOR nowcast (exact) |
| Rain stops soon after 2h | 150 min |
Extrapolated (confidence: medium) |
| Large front (>4h) | 320 min |
Extrapolated (confidence: low) |
| Massive front (>6h) | >6h |
Capped estimate |
| Stationary / can't estimate | >120 |
Fallback |
| Not raining | β | Sensor shows unknown |
Extrapolation works by:
- Tracking the rain field centroid across 25 radar frames to determine speed and direction
- Measuring the trailing edge distance behind your location (opposite to movement direction)
- Dividing distance by speed to estimate remaining duration
The integration ships an interactive Leaflet map (dashboard/rain-warner-map.html) that renders inside an iframe card on any HA dashboard:
- Dark basemap (CartoDB Dark Matter) optimized for radar overlay visibility
- DWD WMS radar layer served through a same-origin proxy (no CORS issues, no API key)
- Geo-scaled motion arrow β a polyline placed on real geographic coordinates showing the rain field's 6-hour trajectory with:
- Hour tick marks at the actual distance the front travels per hour
- Timestamp labels showing when rain at that distance reaches you
- Speed indicator positioned off to the side
- Automatic label hiding at low zoom levels to prevent overlap
- Redraws on zoom so it always matches the map scale
- Location marker at your configured coordinates
- Auto-refresh every 5 minutes + on tab focus
The motion arrow reads its data from the camera.radarbild entity attributes (motion_dr_per_min, motion_dc_per_min, motion_speed_kmh), which the coordinator populates from the multi-pair TREC estimator.
The camera.radarbild entity provides a rendered PNG of the local radar field:
- Cropped to a configurable radius around your location
- Color-coded precipitation intensity (blue β green β yellow β red β purple)
- Motion arrow overlay showing rain field direction
- 300-second frame interval (matches the radar update cadence)
- Attributes expose motion vector data for the interactive map
- Open HACS in your Home Assistant
- Click "Integrations"
- Click the three dots menu β "Custom repositories"
- Add
https://github.com/nodomain/ha-rain-warnerwith category "Integration" - Search for "Rain Warner" and install
- Restart Home Assistant
- Go to Settings β Integrations β Add Integration β "Rain Warner"
- Copy
custom_components/rain_warnerto yourconfig/custom_components/directory - Restart Home Assistant
- Go to Settings β Integrations β Add Integration β "Rain Warner"
During setup you can configure:
- Location β Defaults to your HA home coordinates
- Data Source β Auto (recommended), DWD Radar, Bright Sky, or Open-Meteo
- Radius β Monitoring area around your location (1-50 km)
- Nowcast Engine β Simple (default, stdlib) or pysteps (advanced, opt-in)
The integration ships four data source modes; pick one in the config flow.
Picks DWD Radar when your location is inside the DE1200 coverage box (Germany + ~150 km of border regions) and Open-Meteo elsewhere. The recommended default for most users.
Uses raw DWD RADOLAN/RADVOR radar composites:
- Resolution: 1.1 km Γ 1.1 km grid (polar stereographic projection)
- Update interval: Every 5 minutes
- Forecast: 2 hours from RADVOR + up to 6 h from custom optical-flow extension
- Coverage: Germany + border regions (~150 km beyond borders)
- Cost: Free (DWD Open Data, no API key)
- Format: Binary RADOLAN (parsed with stdlib, no external deps)
JSON wrapper around DWD data:
- Resolution: ~1 km (same underlying DWD data)
- Update interval: Every 5 minutes
- Forecast: Current weather + precipitation
- Coverage: Germany
- Cost: Free
Fulfills the "RainViewer fallback" use case for non-German locations:
- Resolution: 15-minute precipitation forecast (resampled to 5-min buckets)
- Update interval: Every 5 minutes
- Forecast: 6 hours
- Coverage: Worldwide
- Cost: Free, no API key
automation:
- alias: "Close awning before rain"
triggers:
- trigger: state
entity_id: binary_sensor.rain_warner_rain_imminent
to: "on"
actions:
- action: cover.close_cover
target:
entity_id: cover.awningautomation:
- alias: "Rain notification"
triggers:
- trigger: state
entity_id: binary_sensor.rain_warner_raining
to: "on"
actions:
- action: notify.mobile_app
data:
title: "π§οΈ It's raining!"
message: >
Precipitation: {{ states('sensor.rain_warner_current_precipitation') }} mm/h
({{ states('sensor.rain_warner_precipitation_intensity') }})automation:
- alias: "Severe weather alert"
triggers:
- trigger: state
entity_id: binary_sensor.rain_warner_severe_weather
to: "on"
actions:
- action: notify.mobile_app
data:
title: "βοΈ Severe weather!"
message: >
{% set rate = state_attr('binary_sensor.rain_warner_severe_weather', 'max_precipitation_mm_h') %}
{% set ptype = state_attr('binary_sensor.rain_warner_severe_weather', 'precipitation_type') %}
Expected: {{ rate }} mm/h ({{ ptype }})
data:
priority: highautomation:
- alias: "Smart irrigation"
triggers:
- trigger: time
at: "06:00:00"
conditions:
- condition: numeric_state
entity_id: sensor.rain_warner_total_precipitation_2h
below: 2
actions:
- action: switch.turn_on
target:
entity_id: switch.irrigationThe forecast extension beyond DWD's 2 h RADVOR horizon (up to 6 h) is produced by one of two engines, selectable in the config flow:
Multi-pair TREC cross-correlation + semi-Lagrangian advection. No extra dependencies, runs comfortably on a Raspberry Pi 4.
The motion estimator:
- Computes TREC vectors across several ~30 min frame pairs (not just one pair)
- Applies parabolic sub-pixel refinement to get continuous direction
- Rejects vectors that rail at the search boundary (unreliable)
- Averages surviving pairs with outlier rejection (median-magnitude filter)
- Smooths the result across updates with an EMA (Ξ±=0.4) for temporal continuity
Best for frontal weather; less accurate for rotating convective storms.
Wraps the pysteps library for state-of-the-art radar nowcasting:
- Lucas-Kanade per-pixel optical flow β captures rotation, divergence and locally varying winds instead of one global vector.
- Cascade decomposition β separates large-scale fronts from small-scale cells and predicts them with different decay rates, staying accurate at 1β3 h where simple advection has degraded.
- S-PROG lifecycle modelling β AR(2) autoregression so cells can grow, intensify, weaken and dissipate.
Hardware requirement. pysteps pulls in numpy + scipy and is heavyweight on Pi-class hardware. Recommended for x86 / Intel NUC class HA hosts.
Installation. pysteps is not listed as a manifest requirement to keep the integration lightweight by default. The integration installs it on demand the first time you pick "pysteps" in the config flow:
- HA OS / Supervised / Container: nothing to do. When you select
the pysteps engine, the integration calls Home Assistant's built-in
async_process_requirementsAPI and HA installs pysteps into its managed Python environment automatically. The first install takes 30β60 s on x86 (numpy + scipy + opencv wheels download). Subsequent restarts reuse the installed package. - HA Core (manual venv): the auto-install also works, or you can
pre-install:
source /srv/homeassistant/bin/activate && pip install pysteps
If the auto-install fails (e.g. missing wheel for an unusual
architecture), the wrapper falls back to the simple engine and logs a
warning β your sensors keep working. Check
Settings β System β Logs and filter for rain_warner to see what
happened.
Known incompatibility. As of mid-2026 pysteps does not ship
musllinux wheels for Python 3.14 (the interpreter used by current HA
OS releases), and HA OS mounts /tmp with noexec so source builds
fail when Cython tries to load its compiled .so files. If your HA OS
host runs Python 3.14, the auto-install will fail until pysteps
publishes 3.14 musllinux wheels β stick with the simple engine on this
platform. The integration remembers a failed install and skips the
30 s retry on every subsequent boot; re-submit the Configure dialog to
ask it to try again (e.g. after a HA OS or pysteps update).
To switch engines later: Settings β Devices & Services β Rain Warner β Configure and pick a different engine.
The DWD publishes 5-minute radar composites as DE1200_RV_LATEST.tar.bz2:
- Archive contents: 25 RADOLAN binary files (
_000to_120in 5-min steps) - Grid: 1200 rows Γ 1100 columns = 1,320,000 pixels
- Cell size: 1.1 km Γ 1.1 km
- File format: ASCII header (~195 bytes, ending with ETX
0x03) + uint16 LE binary data - Value encoding: Bits 0-11 = precipitation, Bit 13 = clutter flag, Bit 14 = no-data flag
- Precision: Header field
PR E-02β values in 0.01 mm/5min β multiply by 12 for mm/h
The DE1200 grid uses a polar stereographic projection with these parameters:
- Earth radius: 6370.04 km (DWD-specific)
- Standard parallel: 60Β°N
- Central meridian: 10Β°E
- Grid origin (lower-left corner of cell [0,0]): x=-523.462 km, y=-4808.645 km
This gives sub-km accuracy when mapping GPS coordinates to grid cells.
The simple engine uses a TREC-based (Tracking Radar Echoes by Correlation) approach:
- Multi-pair estimation β Instead of one frame pair, estimates motion from many overlapping ~30 min pairs across the full 2 h window
- L1 block matching β Brute-force minimum-L1 search over Β±15 cell shifts on a decimated 300Γ300 sub-window
- Railing rejection β Discards vectors where the minimum sits at the search boundary (the true shift exceeds the search range)
- Sub-pixel refinement β Parabolic interpolation around the cost minimum yields continuous direction (not quantized to integer cells)
- Outlier rejection β Pairs with magnitude >2.5Γ the median are dropped
- Temporal EMA β A running exponential moving average (Ξ±=0.4) across 5-min updates smooths jitter while tracking genuine direction changes within ~15 min
| Intensity | Rate (mm/h) |
|---|---|
| None | 0.0 |
| Light | 0.1 β 2.5 |
| Moderate | 2.5 β 7.6 |
| Heavy | 7.6 β 50.0 |
| Violent | > 50.0 |
# All tests (requires network for live DWD download)
uv run pytest tests/ -v -s
# Unit tests only (no network required)
uv run pytest tests/ -v -k "not network"./deploy.sh # Sync code + map + card to HA config mount
./deploy.sh --restart # Sync + restart HA (~60s downtime)
./deploy.sh --force # Force restart even if unchanged- Full DWD RADOLAN binary radar composite parsing
- RADVOR nowcast integration (2h forecast in 5-min steps)
- Area averaging (configurable radius)
- Polar stereographic coordinate projection
- Dashboard with interactive radar map
- Rain end extrapolation beyond 2h via movement tracking
- Custom nowcasting with optical flow (stdlib, pysteps-inspired)
- Optional pysteps engine for advanced 2β6 h nowcasting (Lucas-Kanade + S-PROG)
- RainViewer / Open-Meteo fallback for non-German locations
- Precipitation type detection (rain vs snow vs sleet vs hail)
- Historical data / statistics (today, yesterday, dry streak, 30-day history)
- Custom Lovelace card with precipitation graph
- Native camera entity with rendered radar crop
- Interactive Leaflet map with geo-scaled motion arrow (6 h projection)
- DWD WMS proxy and XYZ tile server (same-origin, no CORS)
- Alert binary sensors (imminent rain, severe weather, winter weather, dry spell)
- Multi-pair TREC estimation with sub-pixel refinement and EMA smoothing
- Walldisplay notification card templates
Contributions are welcome! Please open an issue first to discuss what you'd like to change.
MIT License β see LICENSE for details.
- DWD Open Data for free radar data
- Bright Sky for the excellent DWD API wrapper
- RainViewer for the embedded radar map tiles
- Leaflet for the interactive map framework
- CartoDB for the dark basemap tiles
- Home Assistant community for inspiration and existing weather integrations