Saublöde Frage:
defmod XtenderSet_Max_Solar DOIF ([Studer485_VT:PV_Power_W])\
(set openDTU/1164a011518f/cmd/limit_nonpersistent_absolute ZuBerechnendeGesamtleistung)
attr XtenderSet_Max_Solar DOIF_Readings ZuBerechnendeGesamtleistung:(2800 - [Studer485_VT:PV_Power_W])
attr XtenderSet_Max_Solar do always
wird ZuBerechnendeGesamtleistung im set den Mikrowechselrichters dann mit dem aktuellen Wert setten, oder mit dem alten Wert?
Ich weiss nichtmal, wie ich die Frage sinnvoll formulieren soll, aber ich hoffe, ihr wisst was ich meine?
Ich möchte durch Event PV_Power_W der Hauptsolaranlage dem Mikrowechselrichter mitteilen, dass er max die Differenz zu 2800W generieren darf.
EDIT: und eine weniger blöde Frage, wie bekomme ich ZuBerechnendeGesamtleistung über webCmd, StateFormat in Kombi mit DevStateIcon angezeigt?
Die volle Definition sieht gerade so aus und ich bekomme ZuBerechnendeGesamtleistung nicht eingebaut
defmod XtenderSet_Max_Solar DOIF ([Studer485_VT:PV_Power_W])\
(set openDTU/1164a011518f/cmd/limit_nonpersistent_absolute ZuBerechnendeGesamtleistung)
attr XtenderSet_Max_Solar DOIF_Readings ZuBerechnendeGesamtleistung:(2800 - [Studer485_VT:PV_Power_W])
attr XtenderSet_Max_Solar devStateIcon disabled:general_aus@red:initialize initialize:general_an@yellow:disable initialized:general_an@yellow:disable cmd_1.*:general_an@green:disable
attr XtenderSet_Max_Solar do always
DOIF_Readings werden zuerst berechnet, um sie dann in der Bedingung auszuwerten.
also:
defmod XtenderSet_Max_Solar DOIF ([$SELF:ZuBerechnendeGesamtleistung] > 0)
...
Deine Lösung triggert zwar auf das gleiche Event, sollte aber dennoch funktionieren, wenn du den set-Befehl korrekt definierst:
(set openDTU/1164a011518f/cmd/limit_nonpersistent_absolute [$SELF:ZuBerechnendeGesamtleistung])
Noch einfacher geht es allerdings mit dem Einzeiler ohne zusätzliche Attribute:
defmod XtenderSet_Max_Solar DOIF {fhem_set("openDTU/1164a011518f/cmd/limit_nonpersistent_absolute ".(2800-[Studer485_VT:PV_Power_W])}
Ah, lag ich also mal wieder umfassend komplett daneben mit meiner Syntax ;)
Danke Damian
Es ist jetzt das geworden. DOIF_readings noch gegen event_Readings getauscht um auch extern zugreifen zu können. Und mit diesem stateFormat wird auch Info/Icon untereinander angezeigt.
defmod XtenderSet_Max_Solar DOIF ([$SELF:ZuBerechnendeGesamtleistung] > 0 and [$SELF:ZuBerechnendeGesamtleistung] < 2000)\
(set openDTU/1164a011518f/cmd/limit_nonpersistent_absolute [$SELF:ZuBerechnendeGesamtleistung])
attr XtenderSet_Max_Solar devStateIcon disabled:general_aus@red:initialize initialize:general_an@yellow:disable initialized:general_an@yellow:disable cmd_1.*:general_an@green:disable
attr XtenderSet_Max_Solar do always
attr XtenderSet_Max_Solar event_Readings ZuBerechnendeGesamtleistung:(2800 - [Studer485_VT:PV_Power_W])
attr XtenderSet_Max_Solar stateFormat state\
<br>\
ZuBerechnendeGesamtleistung
Kann ich in event_Readings auch noch berechnen, dass wenn der Wert größer als 2000 ist, 2000 ausgespuckt wird? Mal wieder die Frage nach der Syntax ...
A la
userReadings
Power__W_Bereinigt:Power__W.* {if (ReadingsVal("Xtender_AC_in","Power__W",0) < 0) {return 0;} else {return ReadingsVal("Xtender_AC_in","Power__W",0);};}
Ja das geht. Ich würde es mit dem ternären Operator in Perl lösen:
attr XtenderSet_Max_Solar event_Readings Power__W_Bereinigt: {[Xtender_AC_in:Power__W] < 0 ? 0 : [Xtender_AC_in:Power__W]}
Wow, das funktioniert (und Stunden mit der anderen Syntax erfolglos rumprobiert). Danke. Hatte noch einen Fehler im set. Jetzt:
defmod XtenderSet_Max_Solar DOIF ([$SELF:ZuBerechnendeGesamtleistung] > 0 and [$SELF:ZuBerechnendeGesamtleistung] <= 2000)\
(set MQTT2_openDTU limit_absolute [$SELF:ZuBerechnendeGesamtleistung])
attr XtenderSet_Max_Solar devStateIcon disabled:general_aus@red:initialize initialize:general_an@yellow:disable initialized:general_an@yellow:disable cmd_1.*:general_an@green:disable
attr XtenderSet_Max_Solar do always
attr XtenderSet_Max_Solar event_Readings ZuBerechnendeGesamtleistung: {2800 - [Studer485_VT:PV_Power_W] > 2000 ? 2000 : [Studer485_VT:PV_Power_W]}
attr XtenderSet_Max_Solar group System_2
attr XtenderSet_Max_Solar room Xtender
attr XtenderSet_Max_Solar sortby 4
attr XtenderSet_Max_Solar stateFormat state\
<br>\
ZuBerechnendeGesamtleistung
.... und jetzt wird es doch wieder zur Knobelaufgabe. Falls jemand Lust hat mitzudenken:
Ich hol ein bißchen aus ...
InselPVanlage mit AC-gekoppelten Mikrowechselrichter. Max Leistung Hauptanlage Solar, je nach Jahreszeit 2400Wp. Der Mikro knapp 2000Wp.
GesamtStrom im Inselnetz darf 2800W nicht übersteigen (1:0-Regel). Das war die Ursprungsidee.
Bis anhin musste ich hart ca 6 mal im Jahr das Limit des Mikros manuell festlegen. So geht einiges an PV verloren, da dieses Limit immer entsprechend der zu erwartenden Maximalleistung der Hauptanlage gesetzt sein musste.
Jetzt dachte ich, ich kann das mit dem erarbeiteten DOIF optimieren.
Der Denkfehler: Wir stellen uns den perfekten Frühlingstag mit ein paar Wolken vor. Wolke verdeckt die Sonne, HauptPV fährt auf imaginäre 500W runter, das DOIF regelt den Mikro auf 2000W hoch ..... Wolke geht weg, wahrscheinlich reichen die 3 Sekunden die die HauptPV ausgelesen wird nicht aus, um den Mikro runterzuregeln und ich habe plötzlich ~ 4400W im InselNetz. Das gilt es dringenst zu vermeiden.
Schön wäre es, wenn der Mikro generell langsam hochfährt, dann könnte der Inselwechselrichter über die NetzFrequenz entspannt den Mikro runterregeln. HauptPV wie auch der Mikro regeln jedoch nach letzten Beobachtungen recht plötzlich hoch (was ich aber nochmal verifizieren werde).
Jetzt suche ich eine bessere Logik. Habe aber keine Idee, wie die Problematik abgefangen werden könnte. Noch nichtmal einen Ansatz.
.... da hatte es noch Fehler in der Grundschaltung/Rechnung. Und ich habe mir jetzt über "800" als substitution wenn wenig Generation erstmal für das Übersteuern geholfen. Siehe Code
defmod XtenderSet_Max_Solar DOIF ([$SELF:ZuBerechnendeGesamtleistung] > 0 and [$SELF:ZuBerechnendeGesamtleistung] <= 2000)\
(set MQTT2_openDTU limit_absolute [$SELF:ZuBerechnendeGesamtleistung])
attr XtenderSet_Max_Solar devStateIcon disabled:general_aus@red:initialize initialize:general_an@yellow:disable initialized:general_an@yellow:disable cmd_1.*:general_an@green:disable
attr XtenderSet_Max_Solar do always
attr XtenderSet_Max_Solar event-on-change-reading ZuBerechnendeGesamtleistung
attr XtenderSet_Max_Solar event_Readings ZuBerechnendeGesamtleistung: {(2800 - [Studer485_VT:PV_Power_W]) > 2000 ? 800 : (2800 - [Studer485_VT:PV_Power_W])}
attr XtenderSet_Max_Solar group System_2
attr XtenderSet_Max_Solar room Xtender
attr XtenderSet_Max_Solar sortby 4
attr XtenderSet_Max_Solar stateFormat state\
<br>\
ZuBerechnendeGesamtleistung
Das ist es jetzt geworden:
defmod XtenderSet_Max_Solar DOIF ([$SELF:ZuBerechnendeGesamtleistung] > 0 and [$SELF:ZuBerechnendeGesamtleistung] <= 2000)\
(set MQTT2_openDTU limit_absolute [$SELF:ZuBerechnendeGesamtleistung])
attr XtenderSet_Max_Solar devStateIcon disabled:general_aus@red:initialize initialize:general_an@yellow:disable initialized:general_an@yellow:disable cmd_1.*:general_an@green:disable
attr XtenderSet_Max_Solar do always
attr XtenderSet_Max_Solar event-on-change-reading ZuBerechnendeGesamtleistung:50
attr XtenderSet_Max_Solar event_Readings ZuBerechnendeGesamtleistung: {(2600 - [Studer485_VT:PV_Power_W]) > 1800 ? 800 : (2600 - [Studer485_VT:PV_Power_W])}
attr XtenderSet_Max_Solar stateFormat state\
<br>\
ZuBerechnendeGesamtleistung
Die "50" in
attr XtenderSet_Max_Solar event-on-change-reading ZuBerechnendeGesamtleistung:50
scheint keine direkten Auswirkungen auf die interne Berechnung zu haben. Gibt es einen Trick?
Im eventReadings hätte ich nur die Berechnung gemacht, den Vergleich dann oben. Die 800 selbst kommt ja ohnehin durch den Filter, die <= 2000 dürfte überflüssig sein.
Und wenn du > 0 abfragst, was passiert im Case <= 0?
Jup, die 2000 ist überflüssig. Peace of mind wenn ich unten quatsch gebaut habe/hätte weil du mehr als 2000 im Mikro nicht setzen kannst ;)
Größer als 0 muss es in der Theorie immer sein, weil die HauptSolarAnlage nicht mehr als 2400Wp kann.
Das Konstrukt kommt im Kern noch von meinem vorherigen Nichtverstehen von event_Readings, aber sichert nach allen Seiten ab. Von daher finde ich es gar nicht so schlecht.... und ich kann die Idee auch in zwei Jahren noch nachvollziehen.
Ursprünglich hatte ich die 2800 als feste Zahl drin, dann wäre es noch Nachvollziehbarer, aber das Werte setzen übersteuert ab und zu 200.
Was mir gerade noch fehlt ist das Gezappel/sehr häufige setzen des Maximalwertes bei 0-50W Differenz abzustellen.
um das abzuschließen:
jetzt mit 10sek Dämpfung beim Hochfahren. Weiterhin Sofortausführung nach unten. Und da kein Übersteuern mehr, wieder die alten 2800 als Referenz. Die "unnötigen" max 2000, min 0 falls sich mal was verrechnet damit nicht Unsinn an den Mikro gesendet wird.
defmod XtenderSet_Max_Solar DOIF ([$SELF:ZuBerechnendeGesamtleistung] > 800 and [$SELF:ZuBerechnendeGesamtleistung] > [$SELF:ZuBerechnendeGesamtleistung_old] and [$SELF:ZuBerechnendeGesamtleistung] <= 2000)\
(set MQTT2_openDTU limit_absolute [$SELF:ZuBerechnendeGesamtleistung])\
DOELSEIF ([$SELF:ZuBerechnendeGesamtleistung] > 0 and [$SELF:ZuBerechnendeGesamtleistung] <= 2000)\
(set MQTT2_openDTU limit_absolute [$SELF:ZuBerechnendeGesamtleistung])
attr XtenderSet_Max_Solar devStateIcon disabled:general_aus@red:initialize initialize:general_an@yellow:disable initialized:general_an@yellow:disable cmd_1.*:general_an@green:disable cmd_2.*:general_an@green:disable
attr XtenderSet_Max_Solar do always
attr XtenderSet_Max_Solar event-on-change-reading ZuBerechnendeGesamtleistung,ZuBerechnendeGesamtleistung_old
attr XtenderSet_Max_Solar event_Readings ZuBerechnendeGesamtleistung: {(2800 - [Studer485_VT:PV_Power_W]) > 2000 ? 800 : (2800 - [Studer485_VT:PV_Power_W])}
attr XtenderSet_Max_Solar oldreadings ZuBerechnendeGesamtleistung,oldreadingsAlways
attr XtenderSet_Max_Solar userReadings ZuBerechnendeGesamtleistung_old:ZuBerechnendeGesamtleistung.* { OldReadingsVal("XtenderSet_Max_Solar", "ZuBerechnendeGesamtleistung", "0") }
attr XtenderSet_Max_Solar wait 10:0
und damit ich keine Monologe halte: Verständnisfrage
attr do resetwait
vs
attr do always
im obigen Beispiel ...
mit do always ist prinzipiell klar, aber: wird dann der zu setzende Wert nach Ablauf des Waits genommen (falls in den 10 Sekunden verändert), oder der Wert zu Beginn der Wait-Zeit. Ich tippe auf ersteres?
Alternative do resetwait ... cmd_2 ohne wait-zeit verhält sich wie mit do always, cmd_1 mit wait wird das wait bei neutrigger zurückgesetzt und läuft neu los? "verhält sich wie mit do alway" ist die entscheidende Frage.
Der Befehl wird (im FHEM-Modus) erst zum Ausführungszeitpunkt ausgewertet und ausgeführt. Dh. Es wird der aktuelle Wert zum Ausführungszeitpunkt genommen und nicht der zum Triggerzeitpunkt 10 Sekunden zuvor.
Bei resetwait wird beim wiederholten Trigger im Gegensatz zu do always die ablaufende wait-Zeit zurückgesetzt, solange der Befehl noch nicht ausgeführt wurde und der wait-Timer noch aktiv war. Dh. sollte innerhalb von 10 Sekunden immer wieder ein Trigger (für den gleichen Zweig) kommen, wird der Befehl nie ausgeführt, weil die wait-Zeit nicht ablaufen kann.
All das kannst du einfach mit einem Test-DOIF und einem Dummy selbst testen.
Danke Damian, ja, könnte man testen, aber so ist es auch für Nachfolgende festgehalten. Ich suche mir immer die Finger wund im Forum und habe auch zu dieser keine Antwort gefunden. Bzw. für den Teil der Frage den du beantwortet hast schon.
Was ich noch immer nicht verstehe (das war die Kernfrage): ist ein attr do resetwait für einen Strang ohne wait das Selbe wie ein attr do always?
Die commandref schweigt sich dazu aus (bzw ist es wahrscheinlich so und bedarf keiner Erklärung?)
Das, was ich geschrieben habe, gilt auch für einen Strang.
Bei do always: Trigger -> wenn Bedingung wahr ->wait->Ausführung von cmd1 nach x Sekunden (egal ob noch zwischendurch Trigger kommen)
Bei do resetwait: Trigger -> wenn Bedingung wahr-> wait (hier wird wait bei einem erneuten Trigger mit wahrer
Bedingung auf die volle wait-Zeit zurückgesetzt-> wenn kein neuer Trigger während der Wartezeit mehr kommt, dann kommt es nach Ablauf der Zeit zur Ausführung von cmd1
Ein gutes Beispiel ist das Treppenhauslicht, bei do always würde das Licht nach der ersten Bewegung nach z. B. 5 Minuten ausgehen, egal ob sich jemand weiter bewegt oder nicht, bei do resetwait, würde das Licht weiter brennen solange sich jemand bewegt. Dazu gibt es auch ein Beispiel in der Commandref.
Edit: Warum sollte man resetwait ohne wait benutzen? Ohne wait sollte das Verhalten gleich sein.
Nicht ganz ohne, aber vllt in einem Zweig ohne, dann ist es gut zu wissen, dass es sich wie do always verhält.
Zitat von: Per am 24 November 2025, 22:14:58in einem Zweig ohne, dann ist es gut zu wissen, dass es sich wie do always verhält.
Danke Damian, Danke Per, ja, das war die Kernfrage und war mir nicht klar. Ein Nebensatz in der commandref a la "do resetwait wirkt sich auf Zweige ohne wait wie do always aus" könnte hier Abhilfe für andere schaffen.
In der Commandref steht zu do resetwait: "Das Attribut do resetwait impliziert eine beliebige Wiederholung wie do always."
Also gleiches Verhalten wie bei do always, wenn kein wait-Timer gesetzt ist.
Jo, jetzt wo ich es weiss, kann ich das auch in Bezug auf Zweige ohne wait so interpretieren ....
Danke