Wanneer moet de groene bak weer aan de weg? Bij ons was het antwoord altijd: even de ROVA-app openen. Met de ROVA-integratie in Home Assistant staat het nu gewoon op het dashboard, en hoeft mijn vrouw de app er niet meer bij te pakken. In dit artikel: de installatie, een privacytip die je niet wilt missen, en de kaart die ik ervoor gebruik.
Wat de integratie doet
ROVA haalt het afval op in het midden en oosten van Nederland. De ROVA-integratie zit standaard in Home Assistant: je hoeft niets te downloaden en ook niets via HACS te installeren. Hij gebruikt een onofficiële API van ROVA, dus je hebt geen account nodig; alleen je adres. De officiële uitleg staat op de integratiepagina van Home Assistant.
Je krijgt vier sensoren, één per bak:
- GFT
- Papier
- Plastic (PMD)
- Restafval
Elke sensor is een datumsensor: de toestand is de eerstvolgende ophaaldatum. Is er voor een bak nog geen datum bekend, dan staat hij op unknown.
Installeren
De snelste weg: klik op ROVA toevoegen aan Home Assistant. Die link opent het installatiescherm in je eigen Home Assistant. De eerste keer vraagt hij het adres van je installatie, bijvoorbeeld http://homeassistant.local:8123. Liever met de hand? Dan zo:
- Ga naar Instellingen → Apparaten & diensten.
- Klik rechtsonder op Integratie toevoegen en kies ROVA.
- Vul je postcode, huisnummer en eventueel een toevoeging in.
- Klaar. De vier sensoren verschijnen onder een dienst met je adres als naam.
Krijg je de melding dat ROVA op dit adres niet ophaalt, dan valt je adres buiten het gebied van ROVA. Verhuis je, of stopt ROVA met ophalen op je adres, dan meldt Home Assistant dat bij de reparaties en kun je de integratie verwijderen.
Privacytip: hernoem je entiteiten
De integratie gebruikt je adres als naam. Daardoor krijgen de sensoren entiteit-ID’s met je postcode en huisnummer erin, zoals sensor.1234ab_1_gft. Dat merk je pas als je een screenshot, een stuk YAML of een vraag op een forum deelt: dan deel je ongemerkt je adres.
Hernoem ze daarom meteen. Ga naar Instellingen → Apparaten & diensten → Entiteiten, open de sensor, klik op het tandwiel en verander de entiteit-ID, bijvoorbeeld in sensor.kliko_gft. Doe hetzelfde met de naam van de dienst. Dat is ook handig als je je configuratie door Claude laat nakijken.
Het ontwerp: de eerstvolgende kliko in één oogopslag

De kaart beantwoordt één vraag: welke bak moet er als eerste aan de weg, en wanneer?
- Bovenaan staat de eerstvolgende bak, in zijn eigen kleur, met de dag en “Vandaag!”, “Morgen”, “Overmorgen” of “Over 5 dagen”. Is het vandaag of morgen, dan kleurt dat woord oranje.
- Eronder staan alle bakken als tegels, op volgorde van ophaaldatum.
- Een bak zonder datum staat achteraan, half doorzichtig en met een streepje.
- Foutwaarden zoals
unknownenunavailable, en datums in het verleden, slaat de kaart over. Er komt dus nooit “Invalid Date” op je scherm.
Wat je nodig hebt
De kaart gebruikt custom:button-card. Die installeer je via HACS: zoek op “button-card”, installeer hem en ververs je browser. Uitleg en alle opties staan op de GitHub-pagina van button-card. Daarna voeg je op je dashboard een kaart toe via Kaart toevoegen → Handmatig en plak je de code hieronder. Werk je met dashboards in YAML-modus, dan plak je hem in je dashboardbestand.
De code
type: custom:button-card
show_icon: false
show_name: false
show_label: false
custom_fields:
inhoud: |
[[[
// Vervang de vier entiteit-ID's door die van jou.
const bakken = [
{ id: 'sensor.1234ab_1_gft', naam: 'GFT', kleur: '#00c853', rgb: '0,200,83', icoon: 'mdi:leaf' },
{ id: 'sensor.1234ab_1_papier', naam: 'Papier', kleur: '#2979ff', rgb: '41,121,255', icoon: 'mdi:file-outline' },
{ id: 'sensor.1234ab_1_plastic', naam: 'PMD', kleur: '#ff4081', rgb: '255,64,129', icoon: 'mdi:recycle' },
{ id: 'sensor.1234ab_1_rest', naam: 'Rest', kleur: '#b0bec5', rgb: '176,190,197', icoon: 'mdi:trash-can-outline' },
];
const vandaag = new Date(); vandaag.setHours(0,0,0,0);
const dagen = ['zo','ma','di','wo','do','vr','za'];
const dagenLang = ['Zondag','Maandag','Dinsdag','Woensdag','Donderdag','Vrijdag','Zaterdag'];
const maanden = ['jan','feb','mrt','apr','mei','jun','jul','aug','sep','okt','nov','dec'];
const lijst = [];
for (const b of bakken) {
const s = states[b.id];
let datum = null;
if (s && !['unknown','unavailable',''].includes(s.state)) {
const d = new Date(s.state);
if (!isNaN(d)) { d.setHours(0,0,0,0); if (d >= vandaag) datum = d; }
}
const dagenTot = datum ? Math.round((datum - vandaag) / 86400000) : null;
lijst.push({ ...b, datum, dagenTot });
}
const bekend = lijst.filter(b => b.datum).sort((a, b) => a.datum - b.datum);
const eerst = bekend[0];
const wanneer = (n) => n === null ? 'onbekend' : n === 0 ? 'Vandaag!' : n === 1 ? 'Morgen'
: n === 2 ? 'Overmorgen' : `Over ${n} dagen`;
const kort = (b) => b.datum ? `${dagen[b.datum.getDay()]} ${b.datum.getDate()} ${maanden[b.datum.getMonth()]}` : '—';
// kop: eerstvolgende bak
let kop;
if (!eerst) {
kop = `<div style="padding:14px 16px;color:rgba(255,255,255,0.55);font-size:13px;">Geen ophaaldatum bekend</div>`;
} else {
const accent = eerst.dagenTot <= 1 ? '#ff9800' : 'rgba(255,255,255,0.6)';
kop = `
<div style="display:flex;align-items:center;gap:16px;padding:14px 16px 12px;
border-radius:12px;background:rgba(${eerst.rgb},0.15);border:2px solid ${eerst.kleur};">
<div style="width:44px;height:44px;border-radius:12px;flex:none;display:flex;align-items:center;justify-content:center;
background:rgba(${eerst.rgb},0.25);">
<ha-icon icon="${eerst.icoon}" style="--mdc-icon-size:28px;color:${eerst.kleur};"></ha-icon>
</div>
<div style="text-align:left;line-height:1.2;min-width:0;">
<div style="font-size:11px;letter-spacing:.12em;color:rgba(255,255,255,0.55);">EERSTVOLGENDE KLIKO</div>
<div style="font-size:22px;font-weight:600;color:${eerst.kleur};margin:2px 0;">${eerst.naam}</div>
<div style="font-size:13px;color:#fff;">${dagenLang[eerst.datum.getDay()]} ${eerst.datum.getDate()} ${maanden[eerst.datum.getMonth()]}
<span style="font-weight:600;color:${accent};margin-left:6px;">${wanneer(eerst.dagenTot)}</span></div>
</div>
</div>`;
}
// tegels: alle bakken op volgorde
const tegels = bekend.concat(lijst.filter(b => !b.datum)).map(b => `
<div style="flex:1;min-width:0;padding:10px 6px;border-radius:12px;text-align:center;
background:rgba(255,255,255,0.05);border:1px solid rgba(255,255,255,0.1);
opacity:${b.datum ? 1 : 0.45};">
<ha-icon icon="${b.icoon}" style="--mdc-icon-size:22px;color:${b.kleur};"></ha-icon>
<div style="font-size:13px;font-weight:600;color:#fff;margin-top:4px;">${b.naam}</div>
<div style="font-size:11px;color:rgba(255,255,255,0.6);">${kort(b)}</div>
</div>`).join('');
return `<div style="display:flex;flex-direction:column;gap:10px;padding:10px;">
${kop}
<div style="display:flex;gap:8px;">${tegels}</div>
</div>`;
]]]
styles:
card:
- background: rgba(255,255,255,0.05)
- border-radius: 12px
- border: 1px solid rgba(255,255,255,0.1)
- padding: 0
- box-shadow: none
grid:
- grid-template-areas: '"inhoud"'
custom_fields:
inhoud:
- justify-self: stretch
tap_action:
action: none
Aanpassen
- Je eigen sensoren: vervang de vier entiteit-ID’s bovenaan in
bakken. - Minder bakken: haal de regel weg van een bak die je niet hebt.
- Kleuren en iconen: elke bak heeft een
kleur, dezelfde kleur alsrgb-waarde voor de doorschijnende achtergrond, en eenicoonuit Material Design Icons. - Lichte achtergrond: de kaart is gemaakt voor een donker thema. Gebruik je een licht thema, vervang dan de witte teksten (
#fffenrgba(255,255,255,…)) door donkere.
Extra: een melding de avond ervoor
Het dashboard helpt alleen als je erlangs loopt. Deze automatisering stuurt om 19:00 een melding naar je telefoon als er de volgende dag een bak wordt opgehaald. Zijn het er twee, dan staan ze allebei in de melding.
automation:
- id: kliko_melding_avond_ervoor
alias: "Kliko - melding de avond ervoor"
triggers:
- trigger: time
at: "19:00:00"
variables:
morgen: >
{% set bakken = {
'GFT': 'sensor.1234ab_1_gft',
'Papier': 'sensor.1234ab_1_papier',
'PMD': 'sensor.1234ab_1_plastic',
'Restafval': 'sensor.1234ab_1_rest'} %}
{% set ns = namespace(lijst=[]) %}
{% set datum_morgen = (now() + timedelta(days=1)).date() %}
{% for naam, entiteit in bakken.items() %}
{% set d = as_datetime(states(entiteit), none) %}
{% if d is not none and as_local(d).date() == datum_morgen %}
{% set ns.lijst = ns.lijst + [naam] %}
{% endif %}
{% endfor %}
{{ ns.lijst | join(' en ') }}
conditions:
- condition: template
value_template: "{{ morgen | length > 0 }}"
actions:
- action: notify.mobile_app_telefoon
data:
title: "Kliko aan de weg"
message: "Morgen ophalen: {{ morgen }}. Zet de bak vanavond buiten."
Drie dingen om op te letten:
- Gebruik
as_local. ROVA geeft de ophaaldag door als een tijdstip in UTC. Maandag 00:00 bij ons is dan zondag 22:00 UTC. Vergelijk je zonderas_local, dan denkt de automatisering dat de bak vandaag al was, en krijg je nooit een melding. - Een sensor zonder datum (
unknownofunavailable) slaat de template over, dankzij de standaardwaardenoneinas_datetime. - Je eigen telefoon: vervang
notify.mobile_app_telefoondoor je eigen meldingsdienst. Wil je dat meerdere mensen de melding krijgen, maak dan een notify-groep.
De template is los getest met Jinja2 in Python: een bak morgen, twee bakken op dezelfde dag, een bak vandaag, een sensor zonder datum en de overgang naar wintertijd. Hoe je dat zelf doet, staat in Zo gebruik ik Claude voor Home Assistant.
Waarom op het dashboard
Het is een kleine automatisering, maar wel een die het hele huis gebruikt. Wie langs het dashboard loopt, ziet meteen welke bak eraan komt, zonder app en zonder in te loggen. En voor wie er niet langsloopt, is er de melding van de avond ervoor.
Links op een rij
- ROVA-integratie: officiële documentatie
- ROVA direct toevoegen aan je Home Assistant (via My Home Assistant)
- button-card op GitHub (te installeren via HACS)
Dit werkt in mijn situatie: ROVA als afvalinzamelaar en custom:button-card op een donker dashboard. De integratie gebruikt een onofficiële API en kan stoppen met werken als ROVA iets verandert. Controleer het tegen je eigen documentatie. Stand: oktober 2026.





Geef een reactie