OpenHAB Stromverbräuche berechnen

Möchte man in openHAB anhand aufgezeichneter Stromverbräuche (in Watt) Tages, Monats, Jahres Gesamtverbräuche berechnen, so kann man dies mithilfe der persistierten Daten in der InfluxDB machen. Ebenfalls ist es somit möglich auch einen Tagesdurchschnittsverbrauch zu berechnen. Voraussetzung dafür ist, das die aktuellen Stromverbräuche in Watt persistent abgespeichert werden. Meine Beispiele hier beziehen sich auf meinen Hausgesamtverbrauch, den ich anhand meiner PV Anlagen Komponenten berechne. Ich habe selbst lange gesucht und getestet, bis ich diese sehr einfach Lösung gefunden habe. Alles basiert auf dem DBQuery Binding von openHAB und einfachen influxDB Abfragen.
Voraussetzung
- openHAB mit InfluxDB als Persistenz
- Installiertes DBQuery Binding aus dem openHAB Add-on Store
- persistierter Stromverbrauch in Watt
Anlegen der DB Query Things
Als erstes müssen wir eine DBQuery Bridge für unsere InfluxDB Verbindung anlegen. Dafür generiert ihr am besten einen neuen READ ONLY Token im Webinterface der InfluxDB. Das Ergebnis sollte dann so aussehen.
Nun können wir für alle Abfragen, die wir gerne hätten, wie zum Beispiel dem Tagesverbrauch ein eigenes Thing anlegen, das wir folgt konfiguriert sein sollte:
Nun kopiert ihr noch bei Edit Script das geeignete Script Beispiel von unten ein und euer Thing ist konfiguriert. Achtet auf den Intervall. Bei Monats und Jahresverbräuchen kann hier eine deutlich höhere Zahl in Sekunden genutzt werden, vor allem auch weil hier die Abfragen deutlich länger dauern.
Ich nutze folgende Werte in Sekunden:
- Strom Tagesverbrauch: 300s (möchte das dieser immer sehr zeitnah berechnet wird und somit aktuell ist)
- Strom Monatsverbrauch: 3600s
- Strom Jahresverbrauch: 7200s
- Strom Durchschnitt Tagesverbrauch: 14400s (da hier der aktuelle Tag nicht eingerechnet wird, reicht es wenn der Wert nur alle 4h berechnet wird)
Habt ihr das Thing soweit konfiguriert und angelegt dann müsst ihr nur noch ein Item dem Number Channel zuordnen, oder direkt ein neues Item erstellen.
InfluxDB Scripts
Strom Tagesverbrauch
Diese InfluxDB Abfrage berechnet den aktuellen, an diesem Tag bisher verbrauchten Strom in kWh. Dafür nutzt es das Measurement TotalPowerConsumption. Hier müsst ihr euere gewünschtes Measurement eintragen.
import "timezone"
option location = timezone.location(name: "Europe/Berlin")
from(bucket: "openhab_db")
|> range(start: today())
|> filter(fn: (r) => r["_measurement"] == "TotalPowerConsumption")
|> filter(fn: (r) => r["_field"] == "value")
|> aggregateWindow(every: 10s, fn: mean, createEmpty: false)
|> integral(unit: 1h)
|> map(fn: (r) => ({ r with _value: r._value / 1000.0 }))
|> last()
Strom Monatsverbrauch
Diese InfluxDB Abfrage berechnet den aktuellen, in diesem Monat bisher verbrauchten Strom in kWh. Dafür nutzt es das Measurement TotalPowerConsumption. Hier müsst ihr euere gewünschtes Measurement eintragen.
import "date"
import "timezone"
option location = timezone.location(name: "Europe/Berlin")
from(bucket: "openhab_db")
|> range(start: date.truncate(t: now(), unit: 1mo))
|> filter(fn: (r) => r["_measurement"] == "TotalPowerConsumption")
|> filter(fn: (r) => r["_field"] == "value")
|> aggregateWindow(every: 10s, fn: mean, createEmpty: false)
|> integral(unit: 1h)
|> map(fn: (r) => ({ r with _value: r._value / 1000.0 }))
|> last()
Strom Jahresverbrauch
Diese InfluxDB Abfrage berechnet den aktuellen, in diesem Jahr bisher verbrauchten Strom in kWh. Dafür nutzt es das Measurement TotalPowerConsumption. Hier müsst ihr euere gewünschtes Measurement eintragen.
import "date"
import "timezone"
option location = timezone.location(name: "Europe/Berlin")
from(bucket: "openhab_db")
|> range(start: date.truncate(t: now(), unit: 1y))
|> filter(fn: (r) => r["_measurement"] == "TotalPowerConsumption")
|> filter(fn: (r) => r["_field"] == "value")
|> aggregateWindow(every: 10m, fn: mean, createEmpty: false)
|> integral(unit: 1h)
|> map(fn: (r) => ({ r with _value: r._value / 1000.0 }))
|> last()
Strom Durchschnitt Tagesverbrauch
Diese InfluxDB Abfrage nutzt unseren vorher berechneten "Strom Tagesverbrauch" und berechnet in diesem Beispiel den Durchschnittsverbrauch (in kWh) der letzten 7 Tage, den heutigen Tag ausgeschlossen.
import "date"
nowTruncated = date.truncate(t: now(), unit: 1d)
from(bucket: "openhab_db")
|> range(start: date.sub(from: nowTruncated, d: 7d), stop: nowTruncated)
|> filter(fn: (r) => r["_measurement"] == "Strom_Tagesverbrauch_Number_Result")
|> filter(fn: (r) => r["_field"] == "value")
|> aggregateWindow(every: 1d, fn: max, createEmpty: false)
|> keep(columns: ["_time", "_value"])
|> mean()
|> map(fn: (r) => ({ _time: time(v: now()), _value: r._value }))
Strom Durchschnitt Tagesverbrauch ohne 2 höchsten Werte
Möchte man wie oben den Tagesdurchnittsverbrauch berechnen, aber zum Beispiel die zwei höchsten Werte ausschließen, dann kann man diese InfluxDB Abfrage nutzen.
import "date"
nowTruncated = date.truncate(t: now(), unit: 1d)
from(bucket: "openhab_db")
|> range(start: date.sub(from: nowTruncated, d: 7d), stop: nowTruncated)
|> filter(fn: (r) => r["_measurement"] == "Strom_Tagesverbrauch_Number_Result")
|> filter(fn: (r) => r["_field"] == "value")
|> aggregateWindow(every: 1d, fn: max, createEmpty: false)
|> keep(columns: ["_time", "_value"])
|> sort(columns: ["_value"], desc: true)
|> tail(n: 5) // Höchsten Wert abschneiden
|> mean()
|> map(fn: (r) => ({ _time: time(v: now()), _value: r._value }))
Strom Durchschnitt Tagesverbrauch ohne Tage mit Wallbox Benutzung
Da ich bei mir ab und an das Auto an der Wallbox lade und nicht möchte das dies meinen Tagesdurchnittsverbrauch in die Höhe treibt, exkulpiere ich alle Tage an denen die Wallbox gelaufen ist.
Diese InfluxDB Flux-Query berechnet den durchschnittlichen Tagesverbrauch der letzten 7 Tage, ohne die Tage, an denen die Wallbox aktiv war.
1. Stromverbrauch der letzten 7 Tage:
- Holt den max()-Wert pro Tag aus dem Measurement Strom_Tagesverbrauch_Number_Result.
- Truncate auf Tagesbeginn (z. B. 2025-09-17T00:00:00Z) → sorgt für saubere Gruppierung.
2. Erkennung der Wallbox-Aktivität:
- Prüft pro Tag im Measurement Wallbox_Switch, ob irgendein Wert > 0.1 war.
- Interpretiert das als: 1.0 = aktiv, 0.0 = inaktiv, null = auch inaktiv.
3. Verknüpfen & Berechnen:
- Führt beide Streams per pivot() auf Tagesbasis zusammen.
- Filtert nur die Tage, an denen die Wallbox nicht aktiv war (wallbox < 0.1).
- Berechnet daraus den Durchschnittsverbrauch dieser „normalen“ Tage.
Ergebnis:
Ein einzelner Mittelwert in _value, der als repräsentativer Wochendurchschnitt ohne Wallbox-Ladetage gilt.
import "date"
nowTruncated = date.truncate(t: now(), unit: 1d)
// --- 1. Stromverbrauch pro Tag ---
verbrauch = from(bucket: "openhab_db")
|> range(start: date.sub(from: nowTruncated, d: 7d), stop: nowTruncated)
|> filter(fn: (r) =>
r["_measurement"] == "Strom_Tagesverbrauch_Number_Result" and
r["_field"] == "value"
)
|> aggregateWindow(every: 1d, fn: max, createEmpty: false)
|> map(fn: (r) => ({
_time: date.truncate(t: r._time, unit: 1d),
_value: r._value,
_field: "verbrauch"
}))
|> keep(columns: ["_time", "_value", "_field"])
// --- 2. Wallbox Aktivitätstage ---
wallbox = from(bucket: "openhab_db")
|> range(start: date.sub(from: nowTruncated, d: 7d), stop: nowTruncated)
|> filter(fn: (r) => r["_measurement"] == "Wallbox_Switch")
|> aggregateWindow(every: 1d, fn: mean, createEmpty: true)
|> map(fn: (r) => ({
_time: date.truncate(t: r._time, unit: 1d),
_value: if exists r._value then (if r._value > 0.1 then 1.0 else 0.0) else 0.0,
_field: "wallbox"
}))
|> keep(columns: ["_time", "_value", "_field"])
// --- 3. Zusammenführen auf gemeinsame Tage ---
union(tables: [verbrauch, wallbox])
|> group(columns: ["_time"]) // pro Tag
|> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value")
|> filter(fn: (r) =>
exists r.verbrauch and exists r.wallbox and r.wallbox < 0.1
)
|> group() // alles in eine Gruppe für globalen Mittelwert
|> mean(column: "verbrauch")
|> map(fn: (r) => ({ _time: now(), _value: r.verbrauch }))