Das Home Assistant Zisternen-Dashboard für Verbrauch und Regenprognose mit dem Senvolon Füllstandmesser
Dieses How-To baut auf dem Trockenlaufschutz-Artikel auf und geht einen Schritt weiter: Statt nur vor dem Leerlaufen zu schützen, machen wir den Wasserverbrauch sichtbar und beantworten drei Fragen automatisch:
- Wie viel Wasser habe ich diese Woche verbraucht?
- Wie lange reicht die Zisterne bei aktuellem Verbrauch noch?
- Wie viel Regen bekomme ich in den nächsten 7 Tagen – und wie viele Liter sind das für meine Zisterne?
Besonders spannend ist der dritte Punkt. Hier lernt das System den individuellen Ertragsfaktor Ihrer Zisterne komplett selbstständig an. Es vergleicht dazu einfach den gemessenen Regenzufluss mit der lokalen Wettervorhersage.
Voraussetzungen
- Senvolon Füllstandmesser, per MQTT in Home Assistant integriert, mit aktivierter „Home Assistant"-Option (MQTT Discovery)
- Home Assistant OS, Zugriff auf die
/config-Dateien über ein Add-on wie File Editor oder Studio Code Server - Eine konfigurierte Wetter-Integration mit Vorhersage-Unterstützung (hier: Met.no)
- Folgende Entitäten aus der MQTT-Discovery des Sensors:
| Entität | Bedeutung |
|---|---|
sensor.level_sensor_fluid |
Füllstand in Litern |
sensor.level_sensor_level |
Absoluter Füllstand in cm |
sensor.level_sensor_distance |
Abstand zur Oberfläche |
sensor.level_sensor_temperature |
Gehäusetemperatur |
sensor.level_sensor_alert |
MIN/MAX-Alarm |
sensor.level_sensor_rssi |
WLAN-Signalstärke |
sensor.level_sensor_ip |
IP-Adresse |
Architektur im Überblick
Vier Bausteine, die aufeinander aufbauen:
-
Verbrauchszähler – der Füllstand ist kein Zähler, sondern schwankt in beide Richtungen (sinkt bei Verbrauch, steigt bei Regen/Nachfüllen). Ein
utility_meterdirekt auf dem Füllstand würde bei jedem Regenschauer negative Deltas verrechnen. Deshalb: ein Hilfszähler, der nur Abfälle aufsummiert. - Regenzufluss – spiegelbildlich dazu ein zweiter Hilfszähler, der nur Anstiege aufsummiert.
- Reichweite – Füllstand geteilt durch den Wochendurchschnitt des Verbrauchs.
- Selbstkalibrierender Regenertrag – der Vergleich aus gemessenem Regenzufluss (Baustein 2) und der für den Tag vorhergesagten Regenmenge in mm ergibt über die Zeit einen empirischen Liter-pro-mm-Faktor für die eigene Zisterne, ganz ohne Annahmen zu Dachfläche oder Material.
Zugriff auf die Config-Dateien bei HAOS
Bei Home Assistant OS läuft der Zugriff z.B. über ein Add-on:
- Einstellungen → Add-ons → Add-on Store
- File Editor für einfache Textbearbeitung, oder
- Studio Code Server für einen vollwertigen VS-Code-artigen Editor mit Syntax-Highlighting (empfohlen, wenn mehrere YAML-Dateien parallel bearbeitet werden)
Nach der Installation erscheint links in der Sidebar das jeweilige Editor-Icon, darüber gelangt man in den /config-Ordner.
Baustein 1: Verbrauchszähler
In eigener Sache: Diese Anleitung mischt Oberfläche und YAML. Was wäre Ihnen lieber, alles zum Klicken oder alles in einer Datei zum Kopieren? Kurze Mail an support@senvolon.de, wir bauen die nächsten How-tos danach.
1.1 Hilfszähler anlegen
Einstellungen → Geräte & Dienste → Helfer → + Helfer erstellen → Zahlenwert-Eingabe
- Name:
Zisterne Wasserverbrauch (kumuliert) - Minimum:
0, Maximum:1000000, Schrittweite:0.1 - Maßeinheit:
L
Entity-ID (automatisch generiert): input_number.zisterne_wasserverbrauch_kumuliert
1.2 Automation zum Aufsummieren
Einstellungen → Automationen → Automation erstellen → In YAML bearbeiten
alias: Zisterne Verbrauch tracken
description: >
Addiert jeden Füllstandsabfall zum kumulierten Verbrauchszähler.
Anstiege (Regen, Nachfüllen) werden bewusst ignoriert.
triggers:
- trigger: state
entity_id: sensor.level_sensor_fluid
conditions:
- condition: template
value_template: >
{{ trigger.from_state is not none and trigger.to_state is not none
and trigger.from_state.state not in ['unknown', 'unavailable']
and trigger.to_state.state not in ['unknown', 'unavailable']
and trigger.to_state.state | float(0) < trigger.from_state.state | float(0) }}
actions:
- action: input_number.set_value
target:
entity_id: input_number.zisterne_wasserverbrauch_kumuliert
data:
value: >
{{ states('input_number.zisterne_wasserverbrauch_kumuliert') | float(0)
+ (trigger.from_state.state | float(0) - trigger.to_state.state | float(0)) }}
mode: queued
1.3 Template-Sensor spiegeln
Der utility_meter braucht einen Sensor mit state_class: total_increasing als Quelle – ein input_number alleine reicht nicht. Deshalb wird der Wert gespiegelt:
Helfer → + Helfer erstellen → „Template" suchen → Sensor-Template
- Name:
Zisterne Wasserverbrauch - Zustand:
{{ states('input_number.zisterne_wasserverbrauch_kumuliert') }} - Maßeinheit:
L - Geräteklasse:
Wasser - Zustandsklasse:
Total Increasing
Stolperstein: Der Vorlage-Helfer-Typ heißt in der Suche schlicht „Template", nicht „Sensor" – eine Suche nach „sensor" findet ihn nicht, da sie nur nach Helfer-Typen mit „sensor" im Namen filtert (z. B. Ableitungssensor, Integralsensor).
1.4 Utility Meter (nur per YAML möglich)
Neue Datei utility_meter.yaml im /config-Wurzelverzeichnis anlegen:
zisterne_verbrauch_taeglich:
source: sensor.zisterne_wasserverbrauch
cycle: daily
zisterne_verbrauch_woechentlich:
source: sensor.zisterne_wasserverbrauch
cycle: weekly
In configuration.yaml einbinden:
utility_meter: !include utility_meter.yaml
Wichtig: In der ausgelagerten Datei fehlt das Top-Level-Wort (utility_meter:), das wird bereits durch den!includegesetzt. Die Datei startet direkt mit den Sensor-Namen bei Einrückungstiefe 0.
Danach: Einstellungen → System → Neu starten. Utility Meter registriert sich beim Boot – ein reines Config-Reload reicht dafür nicht aus, anders als bei Templates ohne Trigger.
Nach dem Neustart in Entwicklertools → Zustände prüfen: sensor.zisterne_verbrauch_taeglich und sensor.zisterne_verbrauch_woechentlich sollten existieren. Das Attribut last_period (Wert des zuletzt abgeschlossenen Zyklus) steht zu diesem Zeitpunkt noch auf 0 – das befüllt sich erst nach dem ersten vollständig durchlaufenen Zyklus.
Baustein 2: Regenzufluss
Exakt spiegelbildlich zu Baustein 1, nur mit umgedrehter Vergleichsrichtung.
2.1 Hilfszähler
input_number.zisterne_regenzufluss_kumuliert (gleiche Konfiguration wie oben).
2.2 Automation
alias: Zisterne Regenzufluss tracken
description: >
Addiert jeden Füllstandsanstieg zum kumulierten Regenzufluss-Zähler.
Setzt voraus, dass Anstiege ausschließlich durch Regen entstehen
(keine aktive Nachfüllung/Pumpenbefüllung im Setup).
triggers:
- trigger: state
entity_id: sensor.level_sensor_fluid
conditions:
- condition: template
value_template: >
{{ trigger.from_state is not none and trigger.to_state is not none
and trigger.from_state.state not in ['unknown', 'unavailable']
and trigger.to_state.state not in ['unknown', 'unavailable']
and trigger.to_state.state | float(0) > trigger.from_state.state | float(0) }}
actions:
- action: input_number.set_value
target:
entity_id: input_number.zisterne_regenzufluss_kumuliert
data:
value: >
{{ states('input_number.zisterne_regenzufluss_kumuliert') | float(0)
+ (trigger.to_state.state | float(0) - trigger.from_state.state | float(0)) }}
mode: queued
2.3 Template-Sensor & Utility Meter
Analog zu 1.3: Sensor-Template Zisterne Regenzufluss (Zustand: {{ states('input_number.zisterne_regenzufluss_kumuliert') }}, Einheit L, Geräteklasse Wasser, Zustandsklasse Total Increasing).
utility_meter.yaml erweitern:
zisterne_verbrauch_taeglich:
source: sensor.zisterne_wasserverbrauch
cycle: daily
zisterne_verbrauch_woechentlich:
source: sensor.zisterne_wasserverbrauch
cycle: weekly
zisterne_regenzufluss_taeglich:
source: sensor.zisterne_regenzufluss
cycle: daily
Neustart erneut nötig.
Achtung: Dieser Ansatz setzt voraus, dass Füllstandsanstiege ausschließlich durch Regen entstehen. Wer in seinem Setup eine aktive Nachfüllung (z. B. Trinkwasser-Topup bei Trockenheit) betreibt, würde das fälschlich als Regen zählen – für dieses Szenario (reine Zisterne ohne Nachspeisung) ist das unkritisch.
Baustein 3: Reichweite
Reine State-Template-Logik, geht komplett über die UI.
Helfer → Vorlage → Sensor-Template
- Name:
Zisterne Reichweite - Zustand:
{% set wochenverbrauch = state_attr('sensor.zisterne_verbrauch_woechentlich', 'last_period') | float(0) %}
{% if wochenverbrauch > 0 %}
{{ (states('sensor.level_sensor_fluid') | float(0) / (wochenverbrauch / 7)) | round(1) }}
{% else %}
{{ none }}
{% endif %}
- Maßeinheit:
d - Geräteklasse und Zustandsklasse: leer lassen
Stolperstein: Eine naive Formel ohne Schutzabfrage (fluid / (last_period / 7)) wirft einenZeroDivisionErrorin der Live-Vorschau, solangelast_periodnoch0ist – also in der ersten Woche nach dem Einrichten. Die{% if %}-Abfrage mit{{ none }}im Else-Zweig sorgt stattdessen für einen sauberenunknown-Zustand, bis der erste Wochenzyklus durchgelaufen ist.
Baustein 4: Selbstkalibrierender Regenertrag
4.1 Kalibrierungs-Helfer
Zwei input_number-Helfer:
-
Zisterne Kalibrierung mm gesamt(Einheitmm, Minimum 0, Maximum 100000, Schrittweite 0.1) -
Zisterne Kalibrierung Liter gesamt(EinheitL, Minimum 0, Maximum 1000000, Schrittweite 0.1)
Die Maßeinheiten sind fürs Rechnen nicht zwingend nötig (die Templates casten ohnehin mit | float(0)), machen die Helfer aber in der Übersicht und auf Dashboards sofort verständlich.
4.2 Kalibrierungs-Automation
Vergleicht täglich um 23:50 Uhr den gemessenen Regenzufluss des Tages mit der für den Tag vorhergesagten Regenmenge:
alias: Zisterne Regenkalibrierung täglich
description: >
Vergleicht den gemessenen Regenzufluss mit der für heute prognostizierten
Regenmenge und aktualisiert den empirischen Liter-pro-mm-Faktor.
triggers:
- trigger: time
at: "23:50:00"
actions:
- action: weather.get_forecasts
target:
entity_id: weather.forecast_home
data:
type: hourly
response_variable: forecast_data
- variables:
heute: "{{ now().strftime('%Y-%m-%d') }}"
mm_heute: >
{% set forecast = forecast_data['weather.forecast_home'].forecast %}
{{ forecast
| selectattr('datetime', 'match', heute)
| map(attribute='precipitation')
| map('float', 0)
| sum
| round(1) }}
liter_heute: "{{ states('sensor.zisterne_regenzufluss_taeglich') | float(0) }}"
- condition: template
value_template: "{{ mm_heute | float(0) > 0.5 }}"
- action: input_number.set_value
target:
entity_id: input_number.zisterne_kalibrierung_mm_gesamt
data:
value: "{{ states('input_number.zisterne_kalibrierung_mm_gesamt') | float(0) + mm_heute }}"
- action: input_number.set_value
target:
entity_id: input_number.zisterne_kalibrierung_liter_gesamt
data:
value: "{{ states('input_number.zisterne_kalibrierung_liter_gesamt') | float(0) + liter_heute }}"
mode: single
weather.forecast_homedurch die eigene Wetter-Entity-ID ersetzen (Entwicklertools → Zustände → nachweather.filtern).
Wichtige Einschränkung:weather.get_forecastsliefert typischerweise nur zukünftige Stunden ab dem Abrufzeitpunkt, nicht die bereits vergangenen Stunden des Tages. Regnet es also z. B. morgens kräftig, bleibt der Rest des Tages aber trocken, sieht die 23:50-Uhr-Abfrage davon nichts mehr – dieser Zeitraum liegt zu diesem Zeitpunkt bereits in der Vergangenheit.mm_heutebildet damit eher ab, was für den Rest des Tages ab dem Abrufzeitpunkt noch erwartet wurde, als was tatsächlich den ganzen Tag über gefallen ist. Bei einem über mehrere Stunden andauernden Regentag ist der Unterschied meist klein, bei kurzen Vormittagsschauern kann die Kalibrierung dadurch systematisch zu niedrige mm-Werte gegen die tatsächlich gemessenen Liter zählen – was den Ertragsfaktor künstlich nach oben verzerrt. Über viele Regentage gemittelt gleicht sich das größtenteils aus, ist aber kein exakter Messwert, sondern eine Annäherung.
Stolperstein: Met.no liefert das Vorhersage-Datum je nach HA-Version mit oder ohne Uhrzeit im ISO-Format. Fallsselectattr('datetime', 'match', heute)keine Treffer liefert,match(matcht nur ab Zeichenkettenanfang) gegensearchtauschen.
4.3 Ertragsfaktor-Sensor
Reine State-Template-Logik, geht über die UI:
Helfer → Vorlage → Sensor-Template
- Name:
Zisterne Ertrag pro mm - Zustand:
{% set mm = states('input_number.zisterne_kalibrierung_mm_gesamt') | float(0) %}
{% set liter = states('input_number.zisterne_kalibrierung_liter_gesamt') | float(0) %}
{% if mm > 5 %}
{{ (liter / mm) | round(2) }}
{% else %}
{{ 30 }}
{% endif %}
- Maßeinheit:
L/mm(als benutzerdefiniertes Element hinzufügen, da HA diese Einheit nicht kennt – unproblematisch, da keine Geräteklasse gesetzt ist und HA die Einheit somit nicht validiert)
Bis mehr als 5 mm kalibrierter Regen vorliegt, liefert der Sensor einen groben Platzhalterwert (30 L/mm), danach den empirisch gelernten Wert.
Wichtig zu verstehen:mm_gesamtundliter_gesamtwerden niemals automatisch zurückgesetzt – der Ertragsfaktor ist also ein Lebenszeit-Durchschnitt seit dem allerersten Kalibrierungstag, kein gleitender Durchschnitt der letzten Tage oder Wochen. Das macht den Wert sehr stabil und ausreißerresistent (ein einzelner ungewöhnlicher Regentag verändert ihn nach vielen kalibrierten Tagen kaum noch), hat aber einen blinden Fleck: Ändert sich die reale Abflusscharakteristik mit der Zeit (Dach wird bemoost, Regenrinne setzt sich zu, Laubfall im Herbst), reagiert der Lebenszeit-Durchschnitt nur sehr träge darauf, weil die frühen, eventuell saubereren Jahre weiterhin mitgewichtet werden. Für den Einstieg ist der einfache Ansatz die pragmatischste Lösung – wer später merkt, dass sich der Wert über Jahre spürbar verschiebt, kann auf einen gleitenden Durchschnitt umstellen (z. B. nur die letzten 90 Kalibrierungstage berücksichtigen).
4.4 Regenertrag-Prognose (7 Tage)
Dieser Sensor braucht die trigger-basierte Template-Syntax mit weather.get_forecasts und response_variable – das kann kein UI-Helfer abbilden, nur ein YAML-Template mit eigenem trigger:-Block.
Neue Datei templates.yaml anlegen:
- trigger:
- trigger: time_pattern
hours: "/1"
action:
- action: weather.get_forecasts
target:
entity_id: weather.forecast_home
data:
type: daily
response_variable: forecast_data
sensor:
- name: "Zisterne Regenertrag 7d"
unique_id: zisterne_regenertrag_7d
unit_of_measurement: L
icon: mdi:weather-pouring
state: >
{% set forecast = forecast_data['weather.forecast_home'].forecast %}
{% set regen_mm = forecast[:7] | map(attribute='precipitation') | map('float', 0) | sum %}
{% set ertrag_pro_mm = states('sensor.zisterne_ertrag_pro_mm') | float(30) %}
{{ (regen_mm * ertrag_pro_mm) | round(0) }}
attributes:
regen_mm_7d: >
{% set forecast = forecast_data['weather.forecast_home'].forecast %}
{{ (forecast[:7] | map(attribute='precipitation') | map('float', 0) | sum) | round(1) }}
In configuration.yaml einbinden:
template: !include templates.yaml
Neustart (auch trigger-basierte Templates brauchen einen echten Neustart, kein Hot-Reload).
Stolperstein: Der trigger-basierte Sensor feuert nicht sofort nach dem Neustart, sondern erst beim nächsten Intervall-Tick des
time_pattern-Triggers (hier: zur nächsten vollen Stunde). Wer direkt nach dem Einrichten nachschaut undsensor.zisterne_regenertrag_7dnoch bei0 Lbzw.unknownsieht, hat keinen Fehler gemacht – das System hat schlicht noch nicht ausgelöst. Zum schnellen Testen kann der Trigger kurzzeitig aufminutes: "/2"verkürzt werden (danach nicht vergessen, wieder aufhours: "/1"zurückzustellen und erneut neu zu starten, sonst ruft das System die Wetter-API unnötig oft auf).
Dashboard
Damit man bei der Anzahl an Entitäten nicht die Übersicht verliert, empfiehlt sich ein eigenes Dashboard mit dem neueren sections-View-Typ statt der klassischen Masonry-Ansicht – bei Masonry rutschen Karten je nach Höhe automatisch in beliebige Spalten, bei sections bleibt die Platzierung exakt so, wie man sie definiert.
Einstellungen → Dashboards → + Dashboard hinzufügen → Leeres Dashboard, dann über die drei Punkte oben rechts „In YAML bearbeiten":
title: Zisterne
views:
- title: Übersicht
path: zisterne
icon: mdi:water-pump
type: sections
sections:
- type: grid
cards:
- type: heading
heading: Live-Messwerte
heading_style: title
- type: entities
title: Füllstandmesser
entities:
- entity: sensor.level_sensor_fluid
name: Füllstand
- entity: sensor.level_sensor_level
name: Absoluter Füllstand
- entity: sensor.level_sensor_distance
name: Abstand zur Oberfläche
- entity: sensor.level_sensor_temperature
name: Gehäusetemperatur
- entity: sensor.level_sensor_alert
name: Alarm
- type: grid
cards:
- type: heading
heading: Verbrauch & Reichweite
heading_style: title
- type: entities
title: Verbrauchszähler
entities:
- entity: sensor.zisterne_verbrauch_taeglich
name: Verbrauch heute
- entity: sensor.zisterne_verbrauch_woechentlich
name: Verbrauch diese Woche
- type: attribute
entity: sensor.zisterne_verbrauch_woechentlich
attribute: last_period
name: Verbrauch letzte Woche
suffix: " L"
- entity: sensor.zisterne_reichweite
name: Wasser für
- type: grid
cards:
- type: heading
heading: Regenzufluss & Kalibrierung
heading_style: title
- type: entities
title: Regen
entities:
- entity: sensor.zisterne_regenzufluss_taeglich
name: Regenzufluss heute
- entity: sensor.zisterne_ertrag_pro_mm
name: Ertragsfaktor (gelernt)
- entity: sensor.zisterne_regenertrag_7d
name: Erwarteter Ertrag (7 Tage)
- entity: input_number.zisterne_kalibrierung_mm_gesamt
name: Kalibrierbasis mm
- entity: input_number.zisterne_kalibrierung_liter_gesamt
name: Kalibrierbasis Liter
- type: grid
cards:
- type: heading
heading: System & Rohzähler
heading_style: title
- type: entities
title: Diagnose
entities:
- entity: sensor.level_sensor_rssi
name: WLAN-Signal
- entity: sensor.level_sensor_ip
name: IP-Adresse
- entity: input_number.zisterne_wasserverbrauch_kumuliert
name: Verbrauch (Rohzähler)
- entity: input_number.zisterne_regenzufluss_kumuliert
name: Regenzufluss (Rohzähler)

Zudem lassen sich einzelnen Entitäten in das zuvor erstellte Pumpenschutz-Dashboard integrieren.

Einlaufphase einplanen
Nach dem Neustart ist das System technisch fertig, liefert aber noch keine vollständig aussagekräftigen Werte:
-
Reichweite: valide erst nach dem ersten kompletten Wochenzyklus (
cycle: weeklystartet standardmäßig Montag 00:00 Uhr) - Ertragsfaktor: valide erst nach kumuliert mehr als 5 mm kalibriertem Regen, also nach den ersten ein bis zwei nennenswerten Regentagen
- Verbrauch/Regenzufluss heute/diese Woche: sofort korrekt, da direkt aus Live-Messwerten abgeleitet
Anhang: Alle Entitäten auf einen Blick
Kurzreferenz zum Nachschlagen – die vollständige Erklärung und der zugehörige YAML-Code stehen jeweils im entsprechenden Abschnitt oben.
Grund-Helfer (Zahlenwert-Eingaben):
-
input_number.zisterne_wasserverbrauch_kumuliert– läuft nur hoch, addiert jeden Füllstandsabfall -
input_number.zisterne_regenzufluss_kumuliert– läuft nur hoch, addiert jeden Füllstandsanstieg -
input_number.zisterne_kalibrierung_mm_gesamt– Summe aller kalibrierten Regen-Millimeter seit Start -
input_number.zisterne_kalibrierung_liter_gesamt– Summe der an diesen Regentagen tatsächlich gemessenen Liter
Gespiegelte Sensoren:
-
sensor.zisterne_wasserverbrauch– Verbrauchszähler mittotal_increasing, macht ihn für Utility Meter nutzbar -
sensor.zisterne_regenzufluss– dasselbe für den Regenzufluss
Utility Meter:
-
sensor.zisterne_verbrauch_taeglich– Verbrauch seit Mitternacht, resettet täglich -
sensor.zisterne_verbrauch_woechentlich– Verbrauch seit Montag, resettet wöchentlich, liefertlast_period -
sensor.zisterne_regenzufluss_taeglich– Regenzufluss seit Mitternacht, wird von der Kalibrierung abgefragt
Berechnete Sensoren:
-
sensor.zisterne_reichweite(„Wasser für") – Füllstand geteilt durch Wochendurchschnitt, in Tagen -
sensor.zisterne_ertrag_pro_mm– gelernter Liter-pro-mm-Faktor, Lebenszeit-Durchschnitt -
sensor.zisterne_regenertrag_7d– 7-Tage-Regenprognose in Litern, stündlich aktualisiert
Automationen:
- Zisterne Verbrauch tracken – erkennt Füllstandsabfälle, füttert den Verbrauchszähler
- Zisterne Regenzufluss tracken – erkennt Füllstandsanstiege, füttert den Regenzufluss-Zähler
- Zisterne Regenkalibrierung täglich – vergleicht täglich 23:50 Uhr Vorhersage mit Messwert, füttert den Ertragsfaktor