Seite 10 von 13
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 11. Mai 2023 13:10
von KellerK1nd
Servus,
Ich hänge mich mal hier an. Habe jetzt seit knapp 5 Tagen ein BKW am Laufen. Soweit so gut, Ertragserfassung mache ich mit einem ShellyEM. Mein Problem, an dem ich mir momentan die Zähne ausbeiße, die Ermittlung der täglichen Ausbeute.
Code: Alles auswählen
rule "36 BKW"
when
Item ShellyEM_bkw_kwh changed
then
val Daybeginn = ZonedDateTime.now().with(LocalTime.MIDNIGHT)
var nTagErtrag = ShellyEM_bkw_kwh.deltaSince(Daybeginn, "influxdb") as Number
ShellyEM_bkw_max_day_kwh.postUpdate(nTagErtrag)
end
Die Items ShellyEM_bkw_kwh und ShellyEM_bkw_max_day_kwh.postUpdate werden beide in der Influxdb persistiert. Nur stimmt was nicht, denn der Ertrag ist viel zu hoch. Mir zeigt es heute 4,9kWh an. In Grafana werte ich die Daten ja auch aus, da sind es bis jetzt 460Wh... Wo liegt denn da der Fehler.
Werte in Grafana:
Werte in VSC:

Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 11. Mai 2023 21:09
von oh73
Hallo,
hab mich auch mal mit Werte aus der Datenbank abrufen beschäftigt.
was mir dabei aufgefallen ist, zumindest bei mir, die Timezone von oh und jdbc stimmt nicht immer überein!
hab mal ein paar Muster, was bei mir funktioniert.
besonders gut die Abfrage von - bis !
Code: Alles auswählen
// Strom Haus, Tag, Monat,
rule "Stromverbrauch Haus"
when
Item Total_Verbrauch received update or
Item Verbrauch changed
then
//val dtMidnight = ZonedDateTime.now().with(LocalTime.MIDNIGHT)
// Zeit Mitternacht um 1 Stunde verschoben
val dtMidnight = ZonedDateTime.now().with(LocalTime.now.withHour(1).withMinute(0).withSecond(0))
//
var Number Verbrauch_tag = Total_Verbrauch.deltaSince(now.withHour(1).withMinute(0).withSecond(0), "jdbc") as Number
var Number Verbrauch_Monat = Total_Verbrauch.deltaSince(dtMidnight.withDayOfMonth(1), "jdbc") as Number
var Number Verbrauch_Jahr = Total_Verbrauch.deltaSince(dtMidnight.withDayOfYear(1), "jdbc") as Number
postUpdate(Stromzaehler_Verbrauch_Tag, Verbrauch_tag)
postUpdate(Stromz_Verbrauch_Monat, Verbrauch_Monat)
postUpdate(Stromz_Verbrauch_Jahr, Verbrauch_Jahr)
// ############# von bis abfragen ################ geht ! nur beachten das Datenbank auch richtig befüllt ist!
var von = "2023-03-31T00:00:00.000Z"
var bis = "2023-04-30T00:00:00.000Z"
// Strom Haus
var Bereich_Strom = Total_Verbrauch.deltaBetween(ZonedDateTime.parse(von), ZonedDateTime.parse(bis))
// Ertrag , Datenbank erst ab 2023-04-01
var Bereich_Ertrag = inverter1TotalErtrag.deltaBetween(ZonedDateTime.parse(von), ZonedDateTime.parse(bis))
// Verkauf, Datenbank erts ab ca 15.04.23
var Bereich_Verkauf = Total_Verkauf.deltaBetween(ZonedDateTime.parse(von), ZonedDateTime.parse(bis))
logInfo("DB_abfragen","April, Strom Total = "+Bereich_Strom )
logInfo("DB_abfragen","April, Ertrag Total = "+Bereich_Ertrag )
logInfo("DB_abfragen","April, Verkauf Total = "+Bereich_Verkauf )
logInfo("Uhrzeit",""+ZonedDateTime.parse(von)+" bis "+ZonedDateTime.parse(bis)) // nur Kontrolle
// ############ ein Wert von einem bestimmten Zeitpunkt abrufen ! #######
val datum1 = "2023-04-12T00:00:00.000Z"
var Ergebnis = Total_Verbrauch.historicState(ZonedDateTime.parse(datum1)).state
logInfo("DB_abfragen_Test3=",""+Ergebnis )
end
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 12. Mai 2023 06:09
von udo1toni
Es wäre interessant, ein paar Werte zu loggen:
Code: Alles auswählen
rule "36 BKW"
when
Item ShellyEM_bkw_kwh changed
then
val Daybeginn = ZonedDateTime.now().with(LocalTime.MIDNIGHT)
var nTagErtrag = ShellyEM_bkw_kwh.deltaSince(Daybeginn, "influxdb") as Number
val nKwhNew = ShellyEM_bkw_kwh.state
val nKwhOld = ShellyEM_bkw_kwh.historicState(Daybeginn, "influxdb").state
val dtOld = ShellyEM_bkw_kwh.historicState(Daybeginn, "influxdb").timestamp
logInfo("bkw","neu: {} alt: {} von: {} delta: {}",nKwhNew,nKwhOld,dtOld,nTagErtrag)
ShellyEM_bkw_max_day_kwh.postUpdate(nTagErtrag)
end
Die Ausgabe kann man dann in openhab.log nachlesen (falls es sich um eine openHABian Installation handelt, bequem über frontail)
Der Zeitstempel des Datensatzes wird in der Datenbank selbst erzeugt (bei jdbc ist das konfigurierbar). Wenn es also zu Inkonsistenzen kommt, so liegt das fast sicher daran, dass die Zeit in der Datenbank falsch ist.
An dieser Stelle nur als unpassende Randbemerkung: die alljährliche Zeitumstellung ist eine Pest!
Jegliche Zeitbezüge (was Abfrage und Speichern betrifft) sollten ausschließlich mit UTC ausgeführt werden.
Nur die Anzeige der Daten müsste auf die lokale Zeit umgerechnet werden.
Die Datenbank müsste intern ebenfalls fest mit UTC arbeiten.
So kann es auch nicht zu Doppelungen der Datenbankeinträge kommen (letzter Sonntag im Oktober, 2a - 3b Uhr)
Ich bin mir aber nicht sicher, ob das so in openHAB möglich ist - zumindest gibt es dafür meines Wissens keinen Parameter.
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 12. Mai 2023 11:59
von KellerK1nd
Hier die Ausgabe des Loggers:
Code: Alles auswählen
2023-05-12 11:54:26.478 [INFO ] [org.openhab.core.model.script.bkw ] - neu: 8.72737790 alt: 3.10058 von: 2023-05-07T14:40:21.604+02:00[Europe/Berlin] delta: 5.62679790
So wie du vermutet hast ist die Zeit das Problem.
Code: Alles auswählen
[11:56:32] root@openhab:~# timedatectl
Local time: Fri 2023-05-12 11:56:36 CEST
Universal time: Fri 2023-05-12 09:56:36 UTC
RTC time: n/a
Time zone: Europe/Berlin (CEST, +0200)
System clock synchronized: yes
NTP service: inactive
RTC in local TZ: no
Persistiert werden die Items in der InfluxDB.
Code: Alles auswählen
root@InfluxDB:~# timedatectl
Local time: Fri 2023-05-12 11:58:44 CEST
Universal time: Fri 2023-05-12 09:58:44 UTC
RTC time: n/a
Time zone: Europe/Berlin (CEST, +0200)
System clock synchronized: yes
NTP service: inactive
RTC in local TZ: no
In beiden Maschinen stimmt die Zeit. Wo kann ich denn weitersuchen?
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 12. Mai 2023 18:33
von udo1toni
Das bedeutet, in der Datenbank sind keine Messwerte zwischen heute (0 Uhr) und dem 7.5. um 14:40:21 Uhr.
Zur Erklärung:
.historicState(zeitpunkt).state liefert den Status, den das Item zu dem Zeitpunkt hatte.
.historicState(Zeitpunkt).timestamp wiederum liefert den Zeitpunkt, zu dem das Item den Status angenommen hat. Dies ist fast sicher ein Zeitpunkt, der vor dem abgefragten Zeitpunkt liegt. Dass hier mehrere Tage dazwischen liegen, erklärt den viel zu hohen Messwert.
Du musst also zunächst dafür sorgen, dass jede Änderung des Items zuverlässig in die Datenbank geschrieben wird.
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 14. Mai 2023 14:39
von KellerK1nd
Ich konnte für diese Berechnung nur ein neues Item nutzen. Komischerweise kann ich über Grafana ja die Daten des alten Items sehen. Jetzt funktioniert es, aber wie gesagt, nur mit einem neuen Item in der Datenbank. Hab es nicht hinbekommen in der Influxdb 2 das Item selbst zu löschen...
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 16. Mai 2023 08:58
von TomW80
Hallo zusammen,
ich habe die
Rule von udo1toni verwendet und die funktioniert soweit auch super. Ist alles viel einfacher gehalten wie bei meinem Versuch.
Jetzt habe ich das Problem dass ich zwei Werte voneinander abziehen möchte, aber immer diesen Fehler erhalte:
Script execution of rule with UID 'energie-7' failed: cannot invoke method public abstract float java.lang.Number.floatValue() on null in energie
Was mach ich falsch?
Der Fehler entsteht hier:
Code: Alles auswählen
val eigenverbrauch_Heute = erzeugung_Heute - einspeisung_Heute
Die ganze Rule sieht so aus:
Code: Alles auswählen
rule "Stromerzeugung Tag Woche Monat Jahr" // Deutscher Zeichensatz zulässig
when
Item Meter_EnergyProduced changed // changed reicht.
then
val ZonedDateTime zdt = ZonedDateTime.now() // jetzt
val ZonedDateTime start_of_day = zdt.with(LocalTime.MIDNIGHT) // heute, Mitternacht
val ZonedDateTime start_of_week = start_of_day.minusDays(start_of_day.getDayOfWeek.getValue - 1) // Montag
val ZonedDateTime start_of_month = start_of_day.withDayOfMonth(1) // Erster Tag des Monats
val ZonedDateTime start_of_year = start_of_day.withDayOfYear(1) // Erster Tag des Jahres
val einspeisung_Heute = (Meter_EnergyProduced.deltaSince(start_of_day) as Number).floatValue
val einspeisung_Woche = (Meter_EnergyProduced.deltaSince(start_of_week) as Number).floatValue
val einspeisung_Monat = (Meter_EnergyProduced.deltaSince(start_of_month) as Number).floatValue
val einspeisung_Jahr = (Meter_EnergyProduced.deltaSince(start_of_year) as Number).floatValue
val erzeugung_Heute = (Day_Energy.deltaSince(start_of_day) as Number).floatValue
var eigenverbrauch_Heute = erzeugung_Heute - einspeisung_Heute
EnergieproduktionTag.postUpdate(einspeisung_Heute)
EnergieproduktionWoche.postUpdate(einspeisung_Woche)
EnergieproduktionMonat.postUpdate(einspeisung_Monat)
EnergieproduktionJahr.postUpdate(einspeisung_Jahr)
tempEigenVerbrauch_Tag.postUpdate(eigenverbrauch_Heute)
end
Gruß Tom
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 16. Mai 2023 18:48
von udo1toni
Der Fehler bedeutet, dass (mindestens) eine der beiden Konstanten
erzeugung_Heute und
einspeisung_Heute keinen gültigen Zahlenwert enthält.
Eigentlich sollte man vor der Zuweisung immer prüfen, ob der Aufruf der Funktion einen gültigen Wert liefern wird, z.B. so:
Code: Alles auswählen
var einspeisung_Heute = 0
if(Meter_EnergyProduced.deltaSince(start_of_day) instanceof Number)
einspeisung_Heute = (Meter_EnergyProduced.deltaSince(start_of_day) as Number).floatValue
oder
Code: Alles auswählen
val einspeisung_Woche = if(Meter_EnergyProduced.deltaSince(start_of_week) instanceof Number)
(Meter_EnergyProduced.deltaSince(start_of_week) as Number).floatValue
else
0
Die erste Variante benötigt eine Variable (var), die zweite Variante kommt mit einer Konstanten (val) aus.
Die zweite Variante kann natürlich auch in einer Zeile geschrieben werden.
Auf diese Weise ist sichergestellt, dass jede der Variablen (oder Konstanten) stets einen gültigen Zahlenwert enthält. Deshalb kommt es anschließend nicht mehr zu Fehlermeldungen bei Berechnungen.
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 16. Mai 2023 21:15
von TomW80
udo1toni hat geschrieben: ↑16. Mai 2023 18:48
Der Fehler bedeutet, dass (mindestens) eine der beiden Konstanten
erzeugung_Heute und
einspeisung_Heute keinen gültigen Zahlenwert enthält.
Ok, dann ist die Frage warum.
udo1toni hat geschrieben: ↑16. Mai 2023 18:48
Code: Alles auswählen
if(Meter_EnergyProduced.deltaSince(start_of_day) instanceof Number)
Hier erhalte ich den Fehler:
The expression of type DecimalType is already of type Number
Re: Stromverbrauch für Tag, Woche, Monat, Jahr berechnen
Verfasst: 16. Mai 2023 21:42
von TomW80
Hab meinen Fehler gefunden.
Day_Energy ist ein Tageswert, anscheinend funktioniert da das deltasince nicht.
So klappt es jedenfalls:
Code: Alles auswählen
val einspeisung_Heute = (Meter_EnergyProduced.deltaSince(start_of_day) as Number).floatValue
val einspeisung_Woche = (Meter_EnergyProduced.deltaSince(start_of_week) as Number).floatValue
val einspeisung_Monat = (Meter_EnergyProduced.deltaSince(start_of_month) as Number).floatValue
val einspeisung_Jahr = (Meter_EnergyProduced.deltaSince(start_of_year) as Number).floatValue
val erzeugung_Heute = (Day_Energy.state as Number).floatValue
val eigenverbrauch_Heute = erzeugung_Heute - einspeisung_Heute