Stromverbrauch Shelly Plug S

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Tomzk
Beiträge: 55
Registriert: 5. Nov 2019 11:04
Answers: 0

Stromverbrauch Shelly Plug S

Beitrag von Tomzk »

Hallo Zusammen,

ich zweifel gerade ein wenig an meiner Aufgabenstellung.
Ich habe mehrere Shelly Plug S im Einsatz und möchte mir die Stromverbräuche, sowie deren Kosten berechnen und ggf. in einem Grafen darstellen lassen:
pro Tag
pro Woche
pro Monat

Da standardmäßig der Verbrauch per MQTT vom Shelly Plug S in der Einheit Watt-Minuten ist, habe ich vorab eine Formel erstellt um diesen Wert in KW umzurechenen.

Code: Alles auswählen

rule "Stromzaehler kWh"

when
    Item ShellyPlugS_267A58_Verbrauch received update
    
then
    ShellyPlugS_267A58_Stromverbrauch_kWh.postUpdate(ShellyPlugS_267A58_Verbrauch.state as DecimalType /60/1000)
    
end
Für die Darstellung des Tagesverbrauches habe ich folgende Formel, bei dieser ist allerdings beim Tageswechsel von Gestern auf heute auf einmal der Wert negativ???:

Code: Alles auswählen

rule "Stromzaehler Verbrauch Tag"
 
when
    Item ShellyPlugS_267A58_Stromverbrauch_kWh received update

then
    ShellyPlugS_267A58_Stromzaehler_Verbrauch_Tag.postUpdate(ShellyPlugS_267A58_Stromverbrauch_kWh.deltaSince(now.withTimeAtStartOfDay))

end
Für die Kosten habe ich jeweils Formeln, bei denen ich die Werte mit den entsprechenden Kosten für KWh multipliziere. Hier ein Beispiel:

Code: Alles auswählen

rule "Stromkosten heute"
 
when 
    Item ShellyPlugS_267A58_Stromverbrauch_kWh received update

then
    ShellyPlugS_267A58_Strom_Kosten_Tag.postUpdate(ShellyPlugS_267A58_Stromverbrauch_kWh.state as DecimalType * 0.3)

end
Gibt es sowas wie now.withTimeAtStartOfDay auch für Woche/ Monat oder wie kann ich so etwas darstellen?
Als Percistence nutze ich rrd4j und influxdb. Können solche Daten wie Monatskosten auch abgespeichert werden für eine historische Betrachtung oder benötige ich hierfür immer wieder ein neues Item?
Gibt es ggf. einen einfacheren oder schöneren Weg für die generelle Umsetzung?

Danke und Gruß

Benutzeravatar
udo1toni
Beiträge: 15269
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Stromverbrauch Shelly Plug S

Beitrag von udo1toni »

withTimeAtStartOfDay ist je einfach Mitternacht. Das Datum kannst Du auf verschiedene Arten passend machen.

Code: Alles auswählen

now.withTimeAtStartOfDay.minusDays(now.dayOfWeek -1)
ergibt Montag der aktuellen Woche, 0:00:00 Uhr dayOfWeek liefert 1 bis 7 (1 ist Montag, 7 ist Sonntag)

Code: Alles auswählen

now.withTimeAtStartOfDay.minusDays(now.dayOfMonth -1)
ergibt den Monatsersten, 0:00:00 Uhr

Enthält das Topic tatsächlich die Totalsumme des Verbrauchs?
openHAB4.3.6 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Tomzk
Beiträge: 55
Registriert: 5. Nov 2019 11:04
Answers: 0

Re: Stromverbrauch Shelly Plug S

Beitrag von Tomzk »

Hallo Udo,

Danke für die Tipps. Mit den Befehlen wäre es mir dann möglich wenn ich Tag, Wochen und Monats Dummy Items anlege diese zu resetten.
Gibt es eine Möglichkeit für eine historische Speicherung der jeweiligen Werte?

Folgende Rules habe ich jetzt:

Code: Alles auswählen

rule "ShellyPlugS_267A58_Verbrauch_kWh"
when
    Item ShellyPlugS_267A58_Verbrauch received update
then
    ShellyPlugS_267A58_Verbrauch_kWh.postUpdate(ShellyPlugS_267A58_Verbrauch.state as DecimalType /60/1000) // Wattminuten / 60 / 1000 = kWh
end


rule "ShellyPlugS_267A58_Verbrauch_Tag"
when
    Item ShellyPlugS_267A58_Verbrauch_kWh received update
then
    ShellyPlugS_267A58_Verbrauch_Tag.postUpdate(ShellyPlugS_267A58_Verbrauch_kWh.deltaSince(now.withTimeAtStartOfDay).floatValue)
    ShellyPlugS_267A58_Verbrauch_Kosten_Tag.postUpdate(ShellyPlugS_267A58_Verbrauch_Tag.state as DecimalType * 0.3)
end


rule "ShellyPlugS_267A58_Verbrauch_Woche"
when
    Item ShellyPlugS_267A58_Verbrauch_kWh received update
then
    ShellyPlugS_267A58_Verbrauch_Woche.postUpdate(ShellyPlugS_267A58_Verbrauch_kWh.deltaSince(now.withTimeAtStartOfDay.minusDays(now.dayOfWeek -1)).floatValue)
    ShellyPlugS_267A58_Verbrauch_Kosten_Woche.postUpdate(ShellyPlugS_267A58_Verbrauch_Woche.state as DecimalType * 0.3)
end

rule "ShellyPlugS_267A58_Verbrauch_Monat"
when
    Item ShellyPlugS_267A58_Verbrauch_kWh received update
then
    ShellyPlugS_267A58_Verbrauch_Monat.postUpdate(ShellyPlugS_267A58_Verbrauch_kWh.deltaSince(now.withTimeAtStartOfDay.minusDays(now.dayOfMonth -1)).floatValue)
    ShellyPlugS_267A58_Verbrauch_Kosten_Monat.postUpdate(ShellyPlugS_267A58_Verbrauch_Monat.state as DecimalType * 0.3)
end
In einem anderen Beitrag habe ich deine Anmerkung zu einem Fehler von postUpdate gelesen und entsprechend
deltaSince(now.withTimeAtStartOfDay).floatValue)
bei allem angepasst. Somit habe diesen Fehler beheben können.
Alledings wird mir nun ein Fehler bei
dayOfWeek -1
und
dayOfMonth -1
angezeigt. Wenn ich in Visual Studio Code drüber gehe, so bekomme ich folgendes angezeigt:
Ambiguous feature call.
The methods
dayOfMonth() in DateTime and
getDayOfMonth() in AbstractDateTime
both match.(org.eclipse.xtext.xbase.validation.IssueCodes.ambiguous_feature_call)

Zu deiner Frage:
soweit ich weiß enthält das Topic nur den Gesamtverbrauch seit dem Zeitpunkt des einsteckens des Shelly Plugs.
Kann man ein eigenes Dummy Item erstellen, welches sich aufsummiert um die Totalsumme zu enthalten und wie müsste die Rule dazu aussehen?

Folgende Topics haben die Shelly Plugs S zur Verfügung:

Code: Alles auswählen

	Thing topic ShellyPlugS_0411E3 "Steckdose 7" {
    	Channels:
	    	Type string : reachable 	"Erreichbarkeit"         [ stateTopic="shellies/shellyplug-s-0411E3/online" ]
        	Type switch : power     	"Power"                  [ stateTopic="shellies/shellyplug-s-0411E3/relay/0", commandTopic="shellies/shellyplug-s-0411E3/relay/0/command", on="on", off="off"]
       	 	Type number : verbrauch 	"Verbrauch/min"          [ stateTopic="shellies/shellyplug-s-0411E3/relay/0/energy" ]
        	Type number : powerload   	"Verbrauch"              [ stateTopic="shellies/shellyplug-s-0411E3/relay/0/power" ]
        	Type number : current   	"Line current"           [ stateTopic="shellies/shellyplug-s-0411E3/overtemperature" ]
        	Type number : temperature   "Geräte Temperatur"   	 [ stateTopic="shellies/shellyplug-s-0411E3/temperature" ]
	}
Eine Frage hätte ich noch, ich habe mehrere der Steckdosen im Einsatz. Wenn die Benennungen der Items sich lediglich in der Nummer (ShellyPlugS_XXXX) ändern, ist es möglich eine einzige Rule mit entsprechenden Variablen zu schreiben, so dass ich nicht für alle Steckdosen die selbe Rules anlegen muss?

Danke und Gruß

Benutzeravatar
udo1toni
Beiträge: 15269
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Stromverbrauch Shelly Plug S

Beitrag von udo1toni »

Ja, Ja und Ja. :)

Für historische Werte nutzt Du am besten einfach die Persistence Services. Da es dort verschiedene Möglichkeiten gibt: jdbc verbindet zu einer sql-Datenbank (PostGre, MySQL, MariaDB...) influxdb tut dies zu einer InfluxDB Datenbank und rrd4j nutzt eine interne RoundRobinDB. Die interne rrd hat den Vorteil, dass man nichts weiter tun muss, man kann das Teil einfach nutzen, nachdem rrd4j einmal installiert und konfiguriert wurde (mit einer rrd4j.persist bestimmen, was gespeichert werden soll). Da es sich um eine RoundRobinDB handelt, ist die Dateigröße fix, man muss sich also nicht sorgen, dass die Persistence das Dateisystem volllaufen lässt. Auf der anderen Seite gibt es immer wieder Probleme mit rrd4j, wo diese liegen, bleibt oft im Dunkeln.
InfluxDB ist eine auf Messwerterfassung spezialisierte Datenbank, es gibt verschiedene Tools, die auf InfluxDB optimiert sind, Grafana kann z.B. hübsche dynamische Graphen aus den Daten erzeugen.
Wenn Du ohnehin irgendwo im Netz eine SQLdb laufen hast, kannst Du auch diese bequem nutzen, um dort Deine Messdaten zu speichern.

Wenn das Topic einfach aufsummiert, könnte es auch sein, dass es zu bestimmten Zeitpunkten wieder auf 0 springt, was dann den Negativwert erklären könnte (müsste man halt mal genau schauen - im Zweifel gibt es auch einen Befehl, um das Topic gezielt auf 0 zu setzen).
Du kannst einfach ein Dummy Item erstellen, indem Du keinen Link setzt, also z.B. so:

Code: Alles auswählen

Number myDummyItem "Zähler [%.1f kWh]"
Aufaddieren wäre dann z.B. so:

Code: Alles auswählen

rule "Stromzaehler kWh"
when
    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde
then
    var Number nkwh = 0
    if(myDummyItem.state instanceof Number)
        nkwh = myDummyItem.state as Number
    nkwh = nkwh + (( ShellyPlugS_267A58_Verbrauch.state as Number) /60000) // dann sollte das Topic aber den Momentanverbrauch in WattMinuten liefern...
    myDummyItem.postUpdate(nkwh)
end
Wenn Du mehrere gleichartige Items einsetzt, die jeweils identisch behandelt werden sollen, musst Du die Items gruppieren und die Rule so umbauen, dass die Items der Gruppe bearbeitet werden. Eine Herausforderung kann dabei sein, wenn ein bestimmtes Item durch ein bestimmtes Item verändert wird. Dann musst Du die Items günstig benennen, um einigermaßen bequem zu arbeiten. z.B. :

Code: Alles auswählen

Group gRealVerbrauch
Group gVerbrauch
Number ShellyPlugS_267A58_Verbrauch "Verbrauch real" (gRealVerbrauch) { channel="..." }
Number Dummy_267A58_Verbrauch "Verbrauch addiert" (gVerbrauch)
Die Items gehören jeweils zusammen, je eines pro Gruppe. Die Rule:

Code: Alles auswählen

rule "Stromzaehler kWh"
when
    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde
then
    gRealVerbrauch.members.forEach[i|
        var Number nkwh = 0
        val myItem = gVerbrauch.members.filter[f|f.name.split("_").get(1) == i.name.split("_").get(1)].head // passendes Item
        if(myItem.state instanceof Number)
            nkwh = myItem.state as Number
        nkwh = nkwh + ((i.state as Number) /60000) 
        myItem.postUpdate(nkwh)
    ]
end
Die Gruppe gRealVerbrauch wird nun durchlaufen, für jedes Item der Gruppe wird der Befehlsblock ausgeführt. Dabei steht i für das aktuelle Item der Gruppe gRealVerbrauch.
Zunächst wird eine Variable nkwh definiert und mit 0 initialisiert.
Anschließend wird das zum aktuellen Item passende Gegenstück gesucht und als Objekt myItem definiert. Das geschieht über einen Filter auf die Gruppe gVerbrauch. Der Filter prüft, ob der 2. Teil des Item Namens identisch mit dem 2. Teil des aktuellen Items der Gruppe gRealVerbrauch ist. Das trifft auf genau ein Item der Gruppe zu. Als Ergebnis wird eine Liste zurückgeliefert, von der wir das erste Item verwenden (.head)
Nun prüft die Rule, ob es sich beim Status des gefundenen Items um eine gültige Zahl handelt, falls das der Fall ist, wird sie in die Variable geschrieben. Anschließend wird der Status des aktuellen Items der Gruppe gRealVerbrauch zu der Variablen addiert (bzw. der 60000ste Teil).
Danach wir die Variable in das gefundene Item geschrieben.
Diese Rule erledigt das also für alle Itempaare auf einmal.
Soll eine Rule auf ein Update der Items triggern, geht das genauso, nur muss man nun den Trigger ändern:

Code: Alles auswählen

rule "Stromzaehler kWh"
when
    Member of gRealVerbrauch received update
then
    val myItem = gVerbrauch.members.filter[f|f.name.split("_").get(1) == triggeringItem.name.split("_").get(1)].head // passendes Item
        // ... whatever ...
    ]
end
In diesem Fall wird also das passende Item in Abhängigkeit des triggernden Items gesucht.

Die DSL ist mit relativ wenigen Befehlen überaus mächtig und erlaubt sehr effizientes Programmieren, wenn man mal verstanden hat, was die Idee dahinter ist ;)
openHAB4.3.6 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Tomzk
Beiträge: 55
Registriert: 5. Nov 2019 11:04
Answers: 0

Re: Stromverbrauch Shelly Plug S

Beitrag von Tomzk »

Danke für die Tipps.
1. Persistence:
Als Persistence habe ich RRD4J sowie InfluxDB. Über die RRD4J lasse ich alle aktuell alle Items sichern. Ich würde im hier beschriebenen Fall auf die InfluxDB setzten, da ich vorhabe für eine Darstellung Grafana zu nutzen. Wie ich einfache Grafen damit hinbekomme weiß ich soweit. Die Frage wird sich stellen, sobald ich eine Grafik entwickeln will, mit der ich auf die Persistence Werte zugreifen kann, bin ich allerdings raus. Aber werden mich dann zu gegebenen Zeitpunkt damit schlau machen.

2. Summentopic:
Ja das Topic summiert den Verbrauch einfach auf und Zeigt die Gesamtsumme. Problem ist hier, sobald die Plug ausgesteckt wurde, ist der Wert wieder genullt. Hierfür habe ich ja dann die Dummy Items.

Ich habe meine Items und Gruppen an dein Beispiel angeglichen. Was soll ich sagen, es funktioniert :D , danke!

Was mir nur ein wenig komisch vorkommt, die kWh steigen ziemlich rasant. Wird über die Rule die Differenz von letztem zum aktuellen Stand des Topics aufsummiert oder jeweils immer der Gesamtwert addiert? Anderenfalls müsste ich hier ein anderes Topic nutzen.
Ich habe das hier erwähnte Topic
- Verbrauch: Aufsummierte Gesamtverbrauch in Watt Minuten
- Powerload: Hier handelt es sich um die Leistung in Watt welche Konstant bleibt bei gleichen Verbrauchern

3. Weitere Rules:
Wenn ich nun ein Tages, Wochen und Monats Dummy anlege, welche zu gegebenen Zeitpunkt genullt werden soll, muss ich weitere Gruppenstafflungen machen? Da wir mit der von dir beschriebenen Rule immer nur genau 1 andres Item abändern können?

Ich habe mir nun noch mehrere Gruppen und Dummys erstellt:

Code: Alles auswählen

// Gruppen
Group gRealVerbrauch    "gRealVerbrauch"
Group gVerbrauch        "gVerbrauch"

Group gVerbrauchTag     "gVerbrauchTag"
Group gVerbrauchWoche   "gVerbrauchWoche"
Group gVerbrauchMonat   "gVerbrauchMonat"

// Items
Number ShellyPlugS_267A58_Verbrauch     "Verbrauch [%.4f W]"   <poweroutlet>   ( gTest, gRealVerbrauch)  { channel="mqtt:topic:MQTTBroker:ShellyPlugS_267A58:verbrauch" }

Number Dummy_267A58_Verbrauch            "Verbrauch [%.4f kWh]"         ( gTest , gVerbrauch )
Number VerbrauchTag_267A58_Verbrauch     "Verbrauch Tag[%.4f kWh]"      ( gTest , gVerbrauchTag )
Number VerbrauchWoche_267A58_Verbrauch   "Verbrauch Woche[%.4f kWh]"    ( gTest , gVerbrauchWoche )
Number VerbrauchMonat_267A58_Verbrauch   "Verbrauch Monat[%.4f kWh]"    ( gTest , gVerbrauchMonat )
Ich habe die Rules entsprechende angepasst:

Code: Alles auswählen

rule "Stromzaehler Reset Tag"
when
    Member of gVerbrauch received update

then
    gVerbrauch.members.forEach[i|
        val myItem = gVerbrauchTag.members.filter[f|f.name.split("_").get(1) == i.name.split("_").get(1)].head // passendes Item
        myItem.postUpdate(i.deltaSince(now.withTimeAtStartOfDay).floatValue)
    ]
end
Der Log meckert aber nun:

Code: Alles auswählen

2019-12-30 17:23:05.073 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Stromzaehler Reset Tag': cannot invoke method public float org.eclipse.smarthome.core.library.types.DecimalType.floatValue() on null
Danke und Gruß
Tom

Benutzeravatar
udo1toni
Beiträge: 15269
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Stromverbrauch Shelly Plug S

Beitrag von udo1toni »

Wie sehen denn Deine Rules aus?
Mein Beispiel ging davon aus, dass nicht die Summe, sondern der Momentanverbrauch im Topic steht.

Das Problem mit der Summe ist halt, wenn Du nicht kontrollieren kannst, wann der Zähler auf null gesetzt wird, musst Du minütlich den Momentanverbrauch errechnen, um den summierten Verbrauch selbst zu errechnen, also erst mal das Delta pro Minute bestimmen und dieses Delta dann auf das eigene Item aufsummieren.
Wenn das Delta negativ wird, wurde der Zähler zurückgesetzt und dieser eine Wert darf nicht aufsummiert werden.

Du kannst einfach drei Items anlegen (eines für den Tag, eines für die Woche und eines für den Monat), die Du jeweils getrennt aufsummieren lässt. Zusätzlich brauchst Du dann drei Rules, die die Items jeweils zum Termin auf 0 setzen. So:

Code: Alles auswählen

rule "Stromzaehler Verbrauch Tag"
when
    Time cron "5 * * * * ?"
then
    var Number nDelta = 0
    if(ShellyPlugS_267A58_Stromverbrauch_kWh.deltaSince(now.minusMinutes(1)) instanceof Number) nDelta = ShellyPlugS_267A58_Stromverbrauch_kWh.deltaSince(now.minusMinutes(1)) as Number
    if(nDelta > 0) {
        SummeTag.postUpdate(nDelta + if(SummeTag.state instanceof Number) (SummeTag.state as Number) else 0)
        SummeWoche.postUpdate(nDelta + if(SummeWoche.state instanceof Number) (SummeWoche.state as Number) else 0)
        SummeMonat.postUpdate(nDelta + if(SummeMonat.state instanceof Number) (SummeMonat.state as Number) else 0)
    }
end

rule "Stromzaehler Reset Tag"
when
    Time cron "0 0 0 * * ?" // täglich 0:00:00 Uhr
then
    SummeTag.postUpdate(0)
end

rule "Stromzaehler Reset Woche"
when
    Time cron "0 0 0 ? * 1" // montags 0:00:00 Uhr
then
    SummeWoche.postUpdate(0)
end

rule "Stromzaehler Reset Monat"
when
    Time cron "0 0 0 1 * ?" // Am Monatsersten 0:00:00 Uhr
then
    SummeMonat.postUpdate(0)
end
Die erste Rule errechnet das aktuelle Delta und addiert es zu allen drei Zählern. Dies geschieht einmal pro Minute
Die anderen drei Rules kümmern sich darum, die Summen auf 0 zu setzen.
Natürlich kannst Du die Rule auch so umgestalten, dass sie für mehrere Items funktionieren. Die Summen können alle in eine gemeinsame Gruppe, beim Raussuchen des Items über Filter kann man ja problemlos auf Tag, Woche und Monat filtern.
Man muss bei der Menge an beteiligten Items allerdings mal schauen, wie die Laufzeit der Rules aussieht, nicht dass sich die Rules gegenseitig ins Gehege kommen...
openHAB4.3.6 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Tomzk
Beiträge: 55
Registriert: 5. Nov 2019 11:04
Answers: 0

Re: Stromverbrauch Shelly Plug S

Beitrag von Tomzk »

Hallo Udo,

Ja ich habe es gemerkt, dass ich das falsche Topic hatte. Ich habe die Rule auf den momentan Verbrauch abgeändert, womit nun der Zähler funktioniert. Ich habe nach dem Beispiel auch eine Rule erstellt um entsprechend die Kosten zu berechnen. Das funktioniert soweit auch.
Was den Reset angeht habe ich wohl ein wenig zu kompliziert gedacht. Clever und einfacher ist es natürlich einfach über eine simple Rule den Wert auf 0 zu setzten.

(Nicht wundern ich habe die Items noch einmal umgenannt)
Meine akutellen Rules:

Code: Alles auswählen

rule "Stromzaehler kWh"
when
    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde

then
    gVerbrauch.members.forEach[i|
        var Number nkwh = 0
        val myItem = gLoad.members.filter[f|f.name.split("_").get(1) == i.name.split("_").get(1)].head // passendes Item
        if(myItem.state instanceof Number)
            nkwh = myItem.state as Number
        nkwh = nkwh + ((i.state as Number) /60000) 
        myItem.postUpdate(nkwh)
    ]
end

rule "Stromzaehler Kosten"
when
    Member of gLoad received update

then
    gLoad.members.forEach[i|
        val myItem = gLoadKosten.members.filter[f|f.name.split("_").get(1) == i.name.split("_").get(1)].head // passendes Item
        myItem.postUpdate(i.state as DecimalType * 0.3)
    ]
end

rule "Stromzaehler Reset Tag"
when
    Member of gLoad received update

then
    gLoad.members.forEach[i|
        val myItem = gLoadTag.members.filter[f|f.name.split("_").get(1) == i.name.split("_").get(1)].head // passendes Item
        myItem.postUpdate(i.deltaSince(now.withTimeAtStartOfDay).floatValue)
    ]
end
Kann ich mit der ersten Rule auch gleich die Items für Tag Woche und Monat mit summieren lassen, oder kann ich hier lediglich als "myItem" nur ein Item nutzen?
Die Items sehen folgendermaßen aus:

Code: Alles auswählen

Number ShellyPlugS_267A58_Load     "Load [%.4f W]"   <poweroutlet>   (gVerbrauch )  { channel="mqtt:topic:MQTTBroker:ShellyPlugS_267A58:powerload" }

Number Dummy_267A58_Load       "Load Dummi [%.4f kWh]"   ( gTest , gLoad )
Number DummyKosten_267A58_Load "Kosten [%.4f €]"         ( gTest , gLoadKosten )
Number LoadTag_267A58_Load     "Load Tag[%.4f kWh]"      ( gTest , gLoadTag )
Number LoadWoche_267A58_Load   "Load Woche[%.4f kWh]"    ( gTest , gLoadWoche )
Number LoadMonat_267A58_Load   "Load Monat[%.4f kWh]"    ( gTest , gLoadMonat )

Bei dem Reset der Werte nach der Methode mehrere Items zu bearbeiten würde diese dann folgend aussehen: :?:
Kann ich hier auch gleich den Reste der Kosten Items mit einbeziehen oder muss ich die Formel identisch nur für die Kosten Items erstellen?

Code: Alles auswählen


rule "Stromzaehler Reset Tag"
when
    Time cron "0 0 0 * * ?" // täglich 0:00:00 Uhr
then
    gLoadTag.members.forEach[i|
        val myItem = gLoadTag.members.filter[f|f.name.split("_").get(1) == i.name.split("_").get(1)].head // passendes Item
        myItem.postUpdate(0)
    ]
end
Danke und Gruß

Benutzeravatar
udo1toni
Beiträge: 15269
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Stromverbrauch Shelly Plug S

Beitrag von udo1toni »

Du kannst das alles in einer Rule abhandeln, nur musst Du natürlich für jedes Item einen eigenen Filter definieren.
Ich schau morgen (heute...) noch mal danach, jetzt ist es etwas spät...
openHAB4.3.6 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Benutzeravatar
udo1toni
Beiträge: 15269
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Stromverbrauch Shelly Plug S

Beitrag von udo1toni »

So, einfach ganz popelig:

Code: Alles auswählen

rule "Stromzaehler kWh"
when
    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde
then
    gVerbrauch.members.forEach[i|
        val Number nLoad = ((i.state as Number) /60000)  // 

        val myItemTag = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Tag")
        ].head // passendes Item

        val myItemWoche = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Woche")
        ].head // passendes Item

        val myItemMonat = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Monat")
        ].head // passendes Item

        val myItemKosten = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Kosten")
        ].head // passendes Item

        myItemTag.postUpdate(nLoad + if(myItemTag.state instanceof Number) (myItemTag.state as Number) else 0)
        myItemWoche.postUpdate(nLoad + if(myItemWoche.state instanceof Number) (myItemWoche.state as Number) else 0)
        myItemMonat.postUpdate(nLoad + if(myItemMonat.state instanceof Number) (myItemMonat.state as Number) else 0)
        myItemKosten.postUpdate(nLoad * 0.3 + if(myItemKosten.state instanceof Number) (myItemKosten.state as Number) else 0)
    ]
end
Alle Zielitems befinden sich in der Gruppe gLoad. Im Namen der Items steht jeweils zur Unterscheidung das Wort Tag/Woche/Monat/Kosten. (entweder im 1. Teil oder nach dem 2. Teil, das Wort muss nicht mit einem _ abgetrennt werden, aber falls es abgetrennt vor dem Identifier (also der Teil nach dem 1. _ und vor dem 2. _) stehen sollte, muss der Filter entsprechend angepasst werden.
Man könnte sicher den Code noch etwas optimieren, so dass innerhalb der ersten Iteration eine hashmap durchlaufen wird (in der Hashmap stehen dann die vier Worte getrennt (plus Korrekturfaktor, jeweils 1 für die erten drei Worte und 0.3 für den letzten Wert), aber auf die Schnelle ist das so die einfache Lösung.
openHAB4.3.6 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Tomzk
Beiträge: 55
Registriert: 5. Nov 2019 11:04
Answers: 0

Re: Stromverbrauch Shelly Plug S

Beitrag von Tomzk »

Hi Udo,

vielen vielen Dank :D :D :D

es funktioniert jetzt alles. Habe die Rules noch etwas erweitert.
Hier für andere die ggf. das gleiche Projekt verfolgen meine fertigen Settings:

Items:

Code: Alles auswählen

// Gruppen
Group gVerbrauch   "gVerbrauch" // Jedes Item mit aktuellem Verbrauch muss in dieser Gruppe sein
Group gLoad        "gLoad"      // Diese Gruppe ist für die Dummis da

Number ShellyPlugS_267A58_Load          "Load [%.2f W]"                     <poweroutlet>   ( gShellyPlugS_267A58 , gVerbrauch )                           { channel="mqtt:topic:MQTTBroker:ShellyPlugS_267A58:powerload" }

Number LoadTag_267A58_Load              "Load Tag 267A58 [%.2f kWh]"        <energy>        ( gLoad , gLoadTag )
Number LoadWoche_267A58_Load            "Load Woche 267A58 [%.2f kWh]"      <energy>        ( gLoad , gLoadWoche )
Number LoadMonat_267A58_Load            "Load Monat 267A58 [%.2f kWh]"      <energy>        ( gLoad , gLoadMonat )

Number LoadKostenTag_267A58_Load        "Kosten Tag 267A58 [%.2f €]"        <price>         ( gLoad , gLoadTag )
Number LoadKostenWoche_267A58_Load      "Kosten Woche 267A58 [%.2f €]"      <price>         ( gLoad , gLoadWoche )
Number LoadKostenMonat_267A58_Load      "Kosten Monat 267A58 [%.2f €]"      <price>         ( gLoad , gLoadMonat )

und die dazugehörigen Rules für die Stromzähler, Stromkostenzähler und die Resets täglich, wöchentlich und monatlich:

Code: Alles auswählen

rule "Stromzaehler kWh"
when
    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde
then
    gVerbrauch.members.forEach[i|
        val Number nLoad = ((i.state as Number) /60000)  // 

        val myItemTag = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Tag")
        ].head // passendes Item

        val myItemWoche = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Woche")
        ].head // passendes Item

        val myItemMonat = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Monat")
        ].head // passendes Item

        val myItemKosten = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Kosten")
        ].head // passendes Item

        val myItemKostenTag = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("KostenTag")
        ].head // passendes Item        

        val myItemKostenWoche = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("KostenWoche")
        ].head // passendes Item        

        val myItemKostenMonat = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("KostenMonat")
        ].head // passendes Item        


        myItemTag.postUpdate(nLoad + if(myItemTag.state instanceof Number) (myItemTag.state as Number) else 0)
        myItemWoche.postUpdate(nLoad + if(myItemWoche.state instanceof Number) (myItemWoche.state as Number) else 0)
        myItemMonat.postUpdate(nLoad + if(myItemMonat.state instanceof Number) (myItemMonat.state as Number) else 0)
        myItemKosten.postUpdate(nLoad * 0.3 + if(myItemKosten.state instanceof Number) (myItemKosten.state as Number) else 0)
        myItemKostenTag.postUpdate(nLoad * 0.3 + if(myItemKostenTag.state instanceof Number) (myItemKostenTag.state as Number) else 0)
        myItemKostenWoche.postUpdate(nLoad * 0.3 + if(myItemKostenWoche.state instanceof Number) (myItemKostenWoche.state as Number) else 0)
        myItemKostenMonat.postUpdate(nLoad * 0.3 + if(myItemKostenMonat.state instanceof Number) (myItemKostenMonat.state as Number) else 0)

    ]
end


rule "Stromzaehler Reset Tag"
when
    Time cron "0 0 0 * * ?" // täglich 0:00:00 Uhr
//    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde
then
    gLoad.members.forEach[i|
        val myItemTag = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Tag")
        ].head // passendes Item

        val myItemKostenTag = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("KostenTag")
        ].head // passendes Item        

        myItemTag.postUpdate(0)
        myItemKostenTag.postUpdate(0)

    ]
end


rule "Stromzaehler Reset Woche"
when
    Time cron "0 0 0 ? * 1" // montags 0:00:00 Uhr
//    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde

then
    gLoad.members.forEach[i|
        val myItemWoche = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Woche")
        ].head // passendes Item

        val myItemKostenWoche = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("KostenWoche")
        ].head // passendes Item        

        myItemWoche.postUpdate(0)
        myItemKostenWoche.postUpdate(0)
    ]
end


rule "Stromzaehler Reset Monat"
when
    Time cron "0 0 0 1 * ?" // Am Monatsersten 0:00:00 Uhr
//    Time cron "5 * * * * ?" // jede Minute in der 5. Sekunde

then
    gLoad.members.forEach[i|
        val myItemMonat = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("Monat")
        ].head // passendes Item

        val myItemKostenMonat = gLoad.members.filter[ f |
            f.name.split("_").get(1) == i.name.split("_").get(1) &&
            f.name.contains("KostenMonat")
        ].head // passendes Item        

        myItemMonat.postUpdate(0)
        myItemKostenMonat.postUpdate(0)
    ]
end

Nun muss ich mich an die Arbeit mit der Darstellung in Grafana machen. Die Grafen sollte ich recht einfach inbekommen, was eine Historische Auswertung angeht muss ich mich noch kundig machen. Aber bei einem so super Support in diesem Forum sollte das auch im Bereich des möglichen sein.

Vielen Dank, frohes neues Jahr allen
Gruß
Tom

Antworten