I run a pretty extensive Home Assistant setup, and one thing that always bothered me was not having a glanceable way to know whether I need to grab an umbrella before stepping outside. The Buienradar integration gives you a raw rain forecast sensor, but turning that into something useful takes a bit of work. Here’s how I did it using three template sensors and a Bubble Card that changes colour depending on how hard it’s going to rain.
What Buienradar Gives You
The Buienradar integration exposes sensor.buienradar_rain_raw, which contains raw precipitation data as a multi-line string. The data is fetched from an endpoint based on your coordinates (latitude and longitude), and each line consists of a three-digit precipitation value followed by a pipe character and a five-character timestamp in 24-hour format. A typical response looks like this:
000|12:00
077|12:05
120|12:10
The data is updated every 5 minutes, covering the next two hours in 5-minute intervals. A value of 0 means no precipitation (dry), and a value of 255 indicates heavy precipitation.
The Conversion Formula
The raw values don’t map linearly to rainfall — Buienradar uses a logarithmic scale, and the official formula to convert a raw value to millimetres per hour is: mm/h = 10 ^ ((value - 109) / 32). As a sanity check: a raw value of 77 should work out to exactly 0.1 mm/h.
This logarithmic scale means the numbers escalate quickly. A value of 77 is a light drizzle, but by the time you reach 150 or above you’re looking at seriously heavy rainfall. That’s why bucketing the result into human-readable labels — Light, Average, Hard, Violent — makes much more practical sense for a dashboard card than displaying a raw mm/h figure.
To actually do something useful with this data, you need to parse the raw string yourself — and that’s where template sensors come in.
Three Template Sensors
I created three template sensors in my configuration.yaml (under template: sensor:). Together they give me everything I need to drive the card.
1. Rain Expected (Boolean)
This sensor answers a simple yes/no question: is any rain forecast in the next two hours?
- name: "Rain Expected"
unique_id: rain_expected
icon: mdi:weather-rainy
state: >
{% set ns = namespace(found=false) %}
{% set data = states('sensor.buienradar_rain_raw').split('n') %}
{% for line in data %}
{% set parts = line.split('|') %}
{% if parts|length == 2 and parts[0]|int(0) > 0 %}
{% set ns.found = true %}
{% break %}
{% endif %}
{% endfor %}
{{ ns.found }}
It loops through each line, checks whether the intensity value is above zero, and returns True as soon as it finds one. This is what controls the card’s visibility condition later.
2. First Rain Time
This sensor finds the timestamp of the first rain entry:
- name: "First Rain Time"
unique_id: first_rain_time
icon: mdi:clock-start
state: >
{% set data = states('sensor.buienradar_rain_raw').split('n') %}
{% for line in data %}
{% set parts = line.split('|') %}
{% if parts|length == 2 and parts[0]|int(0) > 0 %}
{{ parts[1] }}
{% break %}
{% endif %}
{% endfor %}
It uses the same loop logic but returns parts[1] — the time string — instead of a boolean. This shows up as a sub-button on the card so I can see at a glance when the rain starts.
3. Rain Intensity
This one takes a bit more math. Buienradar’s raw values use a logarithmic scale, so converting them to mm/h requires this formula:
mm/h = 10 ^ ((raw_value - 109) / 32)
I then bucket the result into four human-readable labels:
- name: "Rain Intensity"
unique_id: rain_intensity
state: >
{% set lines = states('sensor.buienradar_rain_raw').split('n') %}
{% set ns = namespace(max_val=0) %}
{% for line in lines %}
{% set parts = line.split('|') %}
{% if parts | length == 2 %}
{% set val = parts[0] | int(0) %}
{% if val > ns.max_val %}
{% set ns.max_val = val %}
{% endif %}
{% endif %}
{% endfor %}
{% if ns.max_val == 0 %}
None
{% else %}
{% set mmph = 10 ** ((ns.max_val - 109) / 32) %}
{% if mmph == 0 %}
None
{% elif mmph < 3 %}
Light
{% elif mmph < 10 %}
Average
{% elif mmph < 20 %}
Hard
{% else %}
Violent
{% endif %}
{% endif %}
The four labels — Light, Average, Hard, and Violent — map to the colour coding on the card.
The Bubble Card
With the three sensors in place, I built a Bubble Card button to display everything together. The main entity is sensor.rain_expected, and two sub-buttons show the first rain time and the intensity label.
type: custom:bubble-card
card_type: button
button_type: slider
force_icon: false
show_state: false
show_last_changed: false
show_attribute: false
attribute: friendly_name
sub_button:
- show_name: false
show_last_changed: false
show_attribute: false
show_state: true
show_icon: false
show_background: true
entity: sensor.first_rain_time
- entity: sensor.rain_intensity
show_background: true
show_icon: false
show_state: true
show_name: true
tap_action:
action: none
name: Rain expected
icon: ""
entity: sensor.rain_expected
slider_live_update: false
Colour-Coded Background
The part I enjoy most is the dynamic background colour. Bubble Card’s styles block gives you access to the live hass object, so you can write inline JavaScript to set CSS variables based on sensor state:
styles: |-
ha-card {
--bubble-main-background-color:
${hass.states['sensor.rain_intensity'].state === 'Light' ? 'green' :
hass.states['sensor.rain_intensity'].state === 'Average' ? 'yellow' :
hass.states['sensor.rain_intensity'].state === 'Hard' ? 'orange' :
hass.states['sensor.rain_intensity'].state === 'Violent' ? 'red' :
'gray'} !important;
color: ${
['Average', 'Hard', 'Violent'].includes(hass.states['sensor.rain_intensity'].state) ? 'black' : 'inherit'
} !important;
}
Green for light drizzle, yellow for moderate rain, orange for heavy rain, and red for a downpour. The text colour also flips to black for the brighter backgrounds to keep things readable.
Visibility Condition
The card only appears when rain is actually expected, keeping the dashboard clean when the sky is clear:
visibility:
- condition: state
entity: sensor.rain_expected
state: "True"
The Result
When Buienradar forecasts rain, the card pops up on my dashboard with a colour-coded background, the start time on the left sub-button, and the intensity label on the right — exactly like the screenshot at the top of this post. When no rain is expected, the card is completely hidden.
It’s a small quality-of-life addition, but it’s one of those things that earns its place on the dashboard every single rainy morning.
Related Posts
May 30, 2026
Monitor QNAP Updates in Home Assistant
May 28, 2026





