Shelly Pro 3 EM "saldierend"
Moderator: seppy
- PeterA
- Beiträge: 1070
- Registriert: 8. Feb 2019 12:12
Re: Shelly Pro 3 EM "saldierend"
Ok was der Zähler vom EVU macht ist erst mal nicht so Wichtig.
Was mir jetzt noch eingefallen ist wie ich nun von den momentanen WATT (negatives Vorzeichen) auf Wh und/oder kWh komme.
Der Faktor Zeit fehlt irgendwie noch in der Rule.
Gruß
Peter
Was mir jetzt noch eingefallen ist wie ich nun von den momentanen WATT (negatives Vorzeichen) auf Wh und/oder kWh komme.
Der Faktor Zeit fehlt irgendwie noch in der Rule.
Gruß
Peter
- OpenHab 2.4
#PWRUP
#PWRUP
- PeterA
- Beiträge: 1070
- Registriert: 8. Feb 2019 12:12
Re: Shelly Pro 3 EM "saldierend"
Da ich mit meiner Suche hier und in der englischen Community und im Web nicht weiter komme
formuliere die Vorstellung meiner Rule noch mal hier:
Wenn der aktuelle Wert in Watt negativ ist soll dieser zu kWh auf summiert werden.
Wenn der aktuelle Wert in Watt positiv oder 0 ist soll die Rule abbrechen.
Wird der aktuelle Wert in Watt wieder negativ soll weiter das kWh Item summiert werden.
Gruß
Peter
formuliere die Vorstellung meiner Rule noch mal hier:
Wenn der aktuelle Wert in Watt negativ ist soll dieser zu kWh auf summiert werden.
Wenn der aktuelle Wert in Watt positiv oder 0 ist soll die Rule abbrechen.
Wird der aktuelle Wert in Watt wieder negativ soll weiter das kWh Item summiert werden.
Gruß
Peter
- OpenHab 2.4
#PWRUP
#PWRUP
- udo1toni
- Beiträge: 14415
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Shelly Pro 3 EM "saldierend"
Du kannst Watt nicht als Kilowattstunden aufaddieren, das sind nun mal unterschiedliche Größen.
Du könntest bei jeder Änderung bestimmen, wie lange die letzte Änderung her ist und z.B. für diese Zeit den gemessenen Wert multipliziert mit der Zeit in Sekunden als Wattsekunden aufaddieren.
Je nachdem, die die Leistung gemessen und geliefert wird, kann das auch funktionieren, darauf wetten würde ich nicht.
Aber ein Versuch:
Zu beachten: Die Rule triggert bei Wertänderung des Items (d.h., die bisherige Leistung hat sich geändert). Zu diesem Zeitpunkt können wir also die vergangene(!) Leistung aufaddieren (nicht die aktuelle!).
Deshalb prüft die Rule, ob der vorherige Wert eine gültige Zahl ist und bricht die Rule ab, falls das nicht der Fall ist.
Handelt es sich um eine gültige Zahl, interessiert uns, wann dieser Wert gesetzt wurde, also der Zeitstempel der letzten Änderung (das ist der Parameter true, false würde den Zeitstempel der letzten Aktualisierung liefern).
Leider kann auch der Zeitstempel ungültig sein, also prüfen wir, ob wir einen Wert ungleich null bekommen (man könnte auch explizit auf instanceof DateTimeType prüfen).
Wird kein gültiger Zeitstempel geliefert, muss die Messung verworfen werden, also Abbruch der Rule.
Nun steht also fest, dass wir einen gültigen Messwert haben und auch einen passenden Zeitstempel dazu. Aber handelt es sich um einen negativen Messwert? Das lässt sich erst nach Übernahme des vorherigen Wertes in eine lokale Konstante sicher feststellen und falls der Wert nicht negativ ist, kann die Rule wiederum abgebrochen werden.
Zu guter Letzt müssen wir uns noch die aktuelle Summe aus dem Item holen, welches die Ws (Watt * Sekunde) enthält. Wird hier kein gültiger Wert geliefert, geht die Rule davon aus, dass der Zählerstand 0 ist.
Ansonsten wird die aktuelle Summe in eine lokale Variable übernommen.
Nun wird noch die Differenz zwischen aktueller Zeit und dem Zeitstempel gebildet (in Sekunden), sowie das Produkt aus dem letzten Messwert und der Differenz. Dieser Wert wird abschließend von der Summe abgezogen denn da die Leistung ja negativ ist, ist auch das Produkt negativ und muss also abgezogen werden, um einen positiven Wert zu erhalten.
Das Ergebnis der Rechnung wird in das Summenitem übernommen.
Allein an der Anzahl der Prüfungen vor der Berechnung kann man schon sehen, was da alles schief gehen kann und ob die Leistung nun wirklich über den gesamten Zeitraum zwischen zwei unterschiedlichen Messwerten konstant war, ist nur eine Mutmaßung, aber ich habe ja schon weiter oben darauf hingewiesen, dass wir vermutlich kein belastbares Ergebnis erhalten werden.
Du kannst den Wert auch in kWh berechnen, dann musst Du halt die Watt durch 1000 teilen und die Sekunden durch 3600 teilen. Allerdings solltest Du dann unbedingt überall Double (.doubleValue) als Zahlenformat wählen. Ich möchte dringend die Einheit Ws empfehlen, auch im Hinblick auf ein hoffentlich bald erfolgendes Upgrade auf openHAB4 wo Du Dir die Ws einfach als kWh anzeigen lassen kannst (oder als Joule, Kalorie, wie auch immer es beliebt). Notfalls kannst Du bis zum Upgrade in einem zweiten Item die Ws in kWh speichern, jedoch ohne die Genauigkeit des Wertes zu verlieren. Die Rule wird alle paar Sekunden triggern, die dann addierte Energiemenge ist so klein, dass kWh hier vermutlich schlicht zu ungenau wird, denn das interne Format des Items kannst Du nicht beeinflussen.
Du könntest bei jeder Änderung bestimmen, wie lange die letzte Änderung her ist und z.B. für diese Zeit den gemessenen Wert multipliziert mit der Zeit in Sekunden als Wattsekunden aufaddieren.
Je nachdem, die die Leistung gemessen und geliefert wird, kann das auch funktionieren, darauf wetten würde ich nicht.
Aber ein Versuch:
Code: Alles auswählen
rule "Zähle Ws wenn negativ"
when
Leistung changed
then
if(!(previousState instanceof Number)) // letzter(!) Wert ungültig?
return;
if(Leistung.previousState(true).timestamp === null) // Zeitstempel von letztem Wert nicht vorhanden?
return;
val nWatt = (previousState as Number).floatValue
if(nWatt >= 0) // Wert positiv oder 0?
return;
var nSum = 0.0
if(Energie.state instanceof Number) { // gültige Summe?
nSum = (Energie.state as Number).floatValue // dann Summe in Variable übernehmen
val dtTS = (Leistung.previousState(true).timestamp as DateTimeType).getZonedDateTime() // Zeitpunkt letzte Änderung
val nSec = ((now().toInstant.toEpochMilli - dtTS.toInstant.toEpochMilli) / 1000).floatValue // Sekunden seit letzter Änderung
val nWs = nWatt * nSec
nSum = nSum - nWs // nWs ist negativ
Energie.postUpdate(nSum)
end
Deshalb prüft die Rule, ob der vorherige Wert eine gültige Zahl ist und bricht die Rule ab, falls das nicht der Fall ist.
Handelt es sich um eine gültige Zahl, interessiert uns, wann dieser Wert gesetzt wurde, also der Zeitstempel der letzten Änderung (das ist der Parameter true, false würde den Zeitstempel der letzten Aktualisierung liefern).
Leider kann auch der Zeitstempel ungültig sein, also prüfen wir, ob wir einen Wert ungleich null bekommen (man könnte auch explizit auf instanceof DateTimeType prüfen).
Wird kein gültiger Zeitstempel geliefert, muss die Messung verworfen werden, also Abbruch der Rule.
Nun steht also fest, dass wir einen gültigen Messwert haben und auch einen passenden Zeitstempel dazu. Aber handelt es sich um einen negativen Messwert? Das lässt sich erst nach Übernahme des vorherigen Wertes in eine lokale Konstante sicher feststellen und falls der Wert nicht negativ ist, kann die Rule wiederum abgebrochen werden.
Zu guter Letzt müssen wir uns noch die aktuelle Summe aus dem Item holen, welches die Ws (Watt * Sekunde) enthält. Wird hier kein gültiger Wert geliefert, geht die Rule davon aus, dass der Zählerstand 0 ist.
Ansonsten wird die aktuelle Summe in eine lokale Variable übernommen.
Nun wird noch die Differenz zwischen aktueller Zeit und dem Zeitstempel gebildet (in Sekunden), sowie das Produkt aus dem letzten Messwert und der Differenz. Dieser Wert wird abschließend von der Summe abgezogen denn da die Leistung ja negativ ist, ist auch das Produkt negativ und muss also abgezogen werden, um einen positiven Wert zu erhalten.
Das Ergebnis der Rechnung wird in das Summenitem übernommen.
Allein an der Anzahl der Prüfungen vor der Berechnung kann man schon sehen, was da alles schief gehen kann und ob die Leistung nun wirklich über den gesamten Zeitraum zwischen zwei unterschiedlichen Messwerten konstant war, ist nur eine Mutmaßung, aber ich habe ja schon weiter oben darauf hingewiesen, dass wir vermutlich kein belastbares Ergebnis erhalten werden.
Du kannst den Wert auch in kWh berechnen, dann musst Du halt die Watt durch 1000 teilen und die Sekunden durch 3600 teilen. Allerdings solltest Du dann unbedingt überall Double (.doubleValue) als Zahlenformat wählen. Ich möchte dringend die Einheit Ws empfehlen, auch im Hinblick auf ein hoffentlich bald erfolgendes Upgrade auf openHAB4 wo Du Dir die Ws einfach als kWh anzeigen lassen kannst (oder als Joule, Kalorie, wie auch immer es beliebt). Notfalls kannst Du bis zum Upgrade in einem zweiten Item die Ws in kWh speichern, jedoch ohne die Genauigkeit des Wertes zu verlieren. Die Rule wird alle paar Sekunden triggern, die dann addierte Energiemenge ist so klein, dass kWh hier vermutlich schlicht zu ungenau wird, denn das interne Format des Items kannst Du nicht beeinflussen.
openHAB4.2.0 stable in einem Debian-Container (bookworm) (Proxmox 8.2.4, LXC), mit openHABian eingerichtet
- PeterA
- Beiträge: 1070
- Registriert: 8. Feb 2019 12:12
Re: Shelly Pro 3 EM "saldierend"
OH Wow! Mein Gehirn kann so was nicht
Es gibt noch gemaule im Log:
und:
Hab die Rule auf meine Items angepasst und noch ein "Item" beim Trigger Item davor gesetzt und eine geschweifte Klamme entfernt die da so
alleine rumstand.
Ja und Umrechnung auf Wh und / oder kWh wäre noch nice.
Es gibt noch gemaule im Log:
Code: Alles auswählen
2023-07-27 13:53:32.988 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'test.rules', using it anyway:
Cannot cast from Date to DateTimeType
Code: Alles auswählen
2023-07-27 13:53:35.008 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Zähle Ws wenn negativ': rrd4j does not allow querys without a begin date, unless order is descending and a single value is requested
alleine rumstand.
Code: Alles auswählen
rule "Zähle Ws wenn negativ"
when
Item em0_total_act_power changed
then
if(!(previousState instanceof Number)) // letzter(!) Wert ungültig?
return;
if(em0_total_act_power.previousState(true).timestamp === null) // Zeitstempel von letztem Wert nicht vorhanden?
return;
val nWatt = (previousState as Number).floatValue
if(nWatt >= 0) // Wert positiv oder 0?
return;
var nSum = 0.0
if(Energie_shelly_phasen_sum.state instanceof Number) // gültige Summe?
nSum = (Energie_shelly_phasen_sum.state as Number).floatValue // dann Summe in Variable übernehmen
val dtTS = (em0_total_act_power.previousState(true).timestamp as DateTimeType).getZonedDateTime() // Zeitpunkt letzte Änderung
val nSec = ((now().toInstant.toEpochMilli - dtTS.toInstant.toEpochMilli) / 1000).floatValue // Sekunden seit letzter Änderung
val nWs = nWatt * nSec
nSum = nSum - nWs // nWs ist negativ
Energie_shelly_phasen_sum.postUpdate(nSum)
- OpenHab 2.4
#PWRUP
#PWRUP
- udo1toni
- Beiträge: 14415
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Shelly Pro 3 EM "saldierend"
Sehr gut! Prüfung bestanden... (Spaß, eigene Fehler übersehe ich genauso wie jeder andere auch...)
Statt .timestamp muss es wohl .getTimestamp heißen. Das kommt davon, wenn man zu faul ist, noch mal in der Doku nachzuschlagen (Achtung, zweimal im Code).
Es ist auch möglich, dass .getTimestamp (so wie in der ersten INFO zu lesen) gar kein DateTimeType zurückliefert, dann nehmen wir es halt so:
Code: Alles auswählen
val dtTS = em0_total_act_power.previousState(true).getTimestamp
ergibt für mich allerdings keinen Sinn, .previousState(true) bietet gar keine Möglichkeit, noch mehr Parameter anzugeben (außer halt, gezielt eine andere Persistence als die Default Persistence zu nutzen). Aber vielleicht hängt das auch mit dem fehlerhaften .timestamp zusammen.rrd4j does not allow querys without a begin date
Für Wh und/oder kWh nutzt Du am besten ein zweites Item, meinetwegen Energie_shelly_phasen_sumkWh und schreibst den entsprechend reduzierten Wert zusätzlich dort rein:
Code: Alles auswählen
Energie_shelly_phasen_sumkWh.postUpdate(nSum/3600000)
openHAB4.2.0 stable in einem Debian-Container (bookworm) (Proxmox 8.2.4, LXC), mit openHABian eingerichtet
- PeterA
- Beiträge: 1070
- Registriert: 8. Feb 2019 12:12
Re: Shelly Pro 3 EM "saldierend"
So sieht die Rule jetzt aus:
Die DateTime Fehlermeldung ist jetzt weg.
Aber die rrdj4 kommt noch:
Code: Alles auswählen
rule "Zähle Ws wenn negativ"
when
Item em0_total_act_power changed
then
if(!(previousState instanceof Number)) // letzter(!) Wert ungültig?
return;
if(em0_total_act_power.previousState(true).getTimestamp === null) // Zeitstempel von letztem Wert nicht vorhanden?
return;
val nWatt = (previousState as Number).floatValue
if(nWatt >= 0) // Wert positiv oder 0?
return;
var nSum = 0.0
if(Energie_shelly_phasen_sum.state instanceof Number) // gültige Summe?
nSum = (Energie_shelly_phasen_sum.state as Number).floatValue // dann Summe in Variable übernehmen
val dtTS = em0_total_act_power.previousState(true).getTimestamp // Zeitpunkt letzte Änderung
val nSec = ((now().toInstant.toEpochMilli - dtTS.toInstant.toEpochMilli) / 1000).floatValue // Sekunden seit letzter Änderung
val nWs = nWatt * nSec
nSum = nSum - nWs // nWs ist negativ
Energie_shelly_phasen_sum.postUpdate(nSum)
end
Aber die rrdj4 kommt noch:
Code: Alles auswählen
2023-07-27 17:51:32.599 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Zähle Ws wenn negativ': rrd4j does not allow querys without a begin date, unless order is descending and a single value is requested
- OpenHab 2.4
#PWRUP
#PWRUP
- udo1toni
- Beiträge: 14415
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Shelly Pro 3 EM "saldierend"
Das Item em0_total_act_power ist aber auch über rrd4j mit everyMinute,everyChange persistiert, oder?
openHAB4.2.0 stable in einem Debian-Container (bookworm) (Proxmox 8.2.4, LXC), mit openHABian eingerichtet
- PeterA
- Beiträge: 1070
- Registriert: 8. Feb 2019 12:12
Re: Shelly Pro 3 EM "saldierend"
Code: Alles auswählen
// Shelly Pro 3 EM
em0_total_act_power : strategy = everyMinute, everyChange, restoreOnStartup
Habe mal über die RestApi geschaut da ist auch was in der DB:
Code: Alles auswählen
{
"name": "em0_total_act_power",
"datapoints": "360",
"data": [
{
"time": 1690387200000,
"state": "149.55857916666668"
},
{
"time": 1690387440000,
"state": "137.40427083333333"
},
{
"time": 1690387680000,
"state": "94.35439583333334"
- OpenHab 2.4
#PWRUP
#PWRUP
- udo1toni
- Beiträge: 14415
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Shelly Pro 3 EM "saldierend"
Kann auch sein, dass die ganze Berechnung an rrd4j scheitert, weil rrd4j nicht beliebig feingranular persistieren kann.
openHAB4.2.0 stable in einem Debian-Container (bookworm) (Proxmox 8.2.4, LXC), mit openHABian eingerichtet
- PeterA
- Beiträge: 1070
- Registriert: 8. Feb 2019 12:12