Hallo Zusammen,
ich versuche mit DOIF eine Berechnung mit mehreren Readings durchzuführen was im wesentlichen funktioniert.
Zwangsläufig gibt es die situation das die Werte der Readings sich durch Null teilen das ergibt folgende Fehlermeldung
2015.12.05 17:58:09 1: PERL WARNING: Argument "Illegal division by zero at (eval 213693) line 1.\n" isn't numeric in int at (eval 213694) line 1.
define PV_Wirkungsgrad DOIF
attr PV_Wirkungsgrad event-on-change-reading 1
attr PV_Wirkungsgrad state {([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100)}
attr PV_Wirkungsgrad stateFormat {sprintf "%.2f %%", int(ReadingsVal($name, "state", 0))}
attr PV_Wirkungsgrad verbose 1
define FileLog_PV_Wirkungsgrad FileLog ./log/PV_Wirkungsgrad-%Y.log PV_Wirkungsgrad
auch der Versuch mit nur brechnen wenn "wr11_currentPower >0 hat keinen erfolgt.
#attr PV_Wirkungsgrad state ([sv:wr11_currentPower] > 0) ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff])*100}
#attr PV_Wirkungsgrad stateFormat {sprintf "%.2f %", ReadingsVal($name, "state", 0)}
Kann Bitte einer Helfen.
Viele Grüße
Iron
Hallo,
hinter dem DOIF sollte auch etwas stehen - worauf soll das den triggern bzw. wann soll es denn ausgelöst werden und was dann machen ? Wenn keine Bedingung angegeben ist, kann das Modul nichts vergleichen - daher die Fehlermeldung.
Gruß Christoph
PS. event-on-change-reading 1 funktioniert so auch nicht - es sei denn Du hast ein Reading mit dem Namen 1
event-on-change-reading
Dieses Attribut enthält eine durch Kommata getrennte Liste von "readings". Wenn gesetzt, erzeugen nur Veränderungen der gelisteten "readings" ein Ereignis. Wenn die aktualiserten Werte der gelisteten "readings" identisch sind, wird kein Ereignis generiert.
Wenn hinter dem Namen eines "readings" eine :Schwelle angegeben ist, wird das Event nur getriggert wenn die Änderung grösser als diese Schwelle ist.
Also die Logik müsste sein: bei "currentPower" das event-on-change-reading auf .* setzen. Damit kommen nur noch Werte durch, die sich vom letzen Wert unterscheiden. Das DOIF müsste dann auf einen neuen Wert reagieren (auslösen) - ohne Bedingung damit Deine Berechung ausgeführt werden.
Du musst auf den Nenner prüfen, nicht auf den Zähler.
define PV_Wirkungsgrad DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0)
attr PV_Wirkungsgrad state {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))}
attr PV_Wirkungsgrad verbose 1
stateFormat kannst Du sparen, s. http://fhem.de/commandref_DE.html#DOIF_state
Alternativ:
define PV_Wirkungsgrad DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0) (setreading PV_Wirkungsgrad state {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))})
attr PV_Wirkungsgrad verbose 1
Nicht getestet, ggf. Syntax ergänzen.
Guten Morgen Zusammen,
Danke für Eure Antworten und Unterstützung.
@Bennemannc
"currentPower" ist auf event-on-change-reading .* gesetzt hier wird der Wert nur alle 5 min aktualisiert.
Die Berechnung an sich hat ja funktioniert solange die zu berechnenten Werte nicht Null waren.
@Ellert
habe Deine alternative Code getestet, hatte den erfolgt das über nacht das Log sauber bleibt.
Sobald die PV-Anlage anfängt Werte zu Liefern habe ich folgende Fehlermeldung im Log
2015-12-06_07:35:45 PV_Wirkungsgrad error: no right bracket
2015-12-06_07:35:45 PV_Wirkungsgrad cmd_1
2015-12-06_07:35:46 PV_Wirkungsgrad cmd_2
2015-12-06_07:35:51 PV_Wirkungsgrad error: no right bracket
2015-12-06_07:35:51 PV_Wirkungsgrad cmd_1
2015-12-06_07:35:52 PV_Wirkungsgrad cmd_2
2015-12-06_07:36:19 PV_Wirkungsgrad error: no right bracket
2015-12-06_07:36:19 PV_Wirkungsgrad cmd_1
2015-12-06_07:36:21 PV_Wirkungsgrad cmd_2
2015-12-06_07:36:23 PV_Wirkungsgrad error: no right bracket
2015-12-06_07:36:23 PV_Wirkungsgrad cmd_1
2015-12-06_07:36:24 PV_Wirkungsgrad cmd_2
2015-12-06_07:36:26 PV_Wirkungsgrad error: no right bracket
Mit dem Code
Zitatdefine PV_Wirkungsgrad DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0)
attr PV_Wirkungsgrad state {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))}
attr PV_Wirkungsgrad event-on-change-reading state.*
attr PV_Wirkungsgrad verbose 1
define FileLog_PV_Wirkungsgrad FileLog ./log/PV_Wirkungsgrad-%Y.log PV_Wirkungsgrad
gibt es kein Ergebnis das Log sieht so aus:
2015-12-06_08:58:22 PV_Wirkungsgrad 0.00 %
2015-12-06_08:58:24 PV_Wirkungsgrad 0.00 %
2015-12-06_08:58:25 PV_Wirkungsgrad 0.00 %
2015-12-06_08:58:25 PV_Wirkungsgrad 0.00 %
2015-12-06_08:58:26 PV_Wirkungsgrad 0.00 %
2015-12-06_08:58:27 PV_Wirkungsgrad 0.00 %
2015-12-06_08:58:28 PV_Wirkungsgrad 0.00 %
2015-12-06_08:58:28 PV_Wirkungsgrad 0.00 %
Mit event-on-change-reading state.* versuche ich die Menge der Log-Einträge zu reduzieren
Readings
Device SOLAR_th 2015-12-06 09:29:48
cmd_event SOLAR_th 2015-12-06 08:55:11
cmd_nr 1 2015-12-06 08:55:11
e_SOLAR_th_PV_Einstrahlung_eff 9683.2 2015-12-06 09:29:48
error no right bracket 2015-12-06 08:55:11
state 0.00 % 2015-12-06 09:29:48
Irgendwie fehlt hier der Wert "Current_Power"
Danke für die Hilfe
MfG
Iron
define PV_Wirkungsgrad DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0) (setreading PV_Wirkungsgrad state {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))})
attr PV_Wirkungsgrad verbose 1
hier ist die Klammersetzung nicht OK...! irgendwo fehlt dir eine Klammer
Zitat2015-12-06_07:35:51 PV_Wirkungsgrad error: no right bracket
dieser Fehler muss erst einmal weg...
Ich habe den Code angepasst.
([SOLAR_th:PV_Einstrahlung_eff] != 0)
(
(setreading PV_Wirkungsgrad state
{(sprintf("%.2f %%",([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff])*100))})
)
Zumindest wird jetzt keine Fehler mehr angezeigt, aber ein Ergebnis auch nicht.
Das DOIF hat noch nicht getriggert, state steht noch auf initialized.
kann ja nicht gehen wenn der zweite Wert fehlt.
Nun wo er da ist steht bei "state cmd_1"
Wie bekomme ich den Berechneten Wert angezeigt?
im Log steht:
2015-12-06_14:59:18 PV_Wirkungsgrad 0.00 %
2015-12-06_14:59:18 PV_Wirkungsgrad cmd_nr: 1
2015-12-06_14:59:18 PV_Wirkungsgrad cmd_event: SOLAR_th
2015-12-06_14:59:18 PV_Wirkungsgrad cmd_1
Da hab ich was dazu gelernt. Ich hätte gedacht, dass setreading, "state" auf den Wert setzt. Wird wohl auch, aber dann durch cmd_1 überschrieben, falls die Reihenfolge im Log stimmt. Dann versuch mal "attr PV_Wirkungsgrad state ...", wie in der Commandref beschrieben und fang Nenner=0 mit IF ab.
define PV_Wirkungsgrad DOIF
attr PV_Wirkungsgrad state IF ([SOLAR_th:PV_Einstrahlung_eff] != 0) ({(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))})
Ich habe die Klammern nicht überprüft.
Du kannst das Attribut "state" komfortabel im DEF-Editor definieren, wenn Du beim DOIF folgendes Attibut setzt.
attr PV_Wirkungsgrad widgetOverride state:textField-long
Zitat von: Ellert am 06 Dezember 2015, 18:42:11
Da hab ich was dazu gelernt. Ich hätte gedacht, dass setreading, "state" auf den Wert setzt. Wird wohl auch, aber dann durch cmd_1 überschrieben, falls die Reihenfolge im Log stimmt. Dann versuch mal "attr PV_Wirkungsgrad state ...", wie in der Commandref beschrieben und fang Nenner=0 mit IF ab.
define PV_Wirkungsgrad DOIF
attr PV_Wirkungsgrad state IF ([SOLAR_th:PV_Einstrahlung_eff] != 0) ({(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))})
Ich habe die Klammern nicht überprüft.
Du kannst das Attribut "state" komfortabel im DEF-Editor definieren, wenn Du beim DOIF folgendes Attibut setzt.
attr PV_Wirkungsgrad widgetOverride state:textField-long
Das wird nicht funktionieren.
Das Attribut state ist in erster Linie dazu gedacht, beliebige Texte zu definieren, wo in eckigen Klammern Stati, Readings usw. eingesetzt werden oder eben Perlbefehle, die etwas ausgeben, beginnend mit {(.
FHEM-Befehle dagegen wie z. B. IF werden im state nicht ausgeführt. Ich denke, am einfachsten ist die Variante ohne state-Attribut mit setreading auf ein selbst definiertes Reading oder mit set auf ein Dummy, welches man sich dann, wo auch immer anzeigen lassen kann.
Gruß
Damian
@Damian: würde es mit dem Perl if funktionieren?
attr PV_Wirkungsgrad state {if ([SOLAR_th:PV_Einstrahlung_eff] != 0) {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))}}
Zitat von: Ellert am 06 Dezember 2015, 19:03:54
@Damian: würde es mit dem Perl if funktionieren?
attr PV_Wirkungsgrad state {if ([SOLAR_th:PV_Einstrahlung_eff] != 0) {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100))}}
wenn, dann so (Perl muss im State mit {( beginnen):
attr PV_Wirkungsgrad state {();if ([SOLAR_th:PV_Einstrahlung_eff] != 0) {sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100)}}
aber, ob dann noch jemand versteht, warum man das so umständlich formulieren muss, wage ich zu bezweifeln.
Gruß
Damian
Zitat von: Damian am 06 Dezember 2015, 19:27:13
wenn, dann so (Perl muss im State mit {( beginnen):
attr PV_Wirkungsgrad state {();if ([SOLAR_th:PV_Einstrahlung_eff] != 0) {sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100)}}
oder so (ist auch weitgehend Perl):
attr PV_Wirkungsgrad state {([SOLAR_th:PV_Einstrahlung_eff] ? sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100):"kein Wert")}
Hallo Zusammen,
Danke für die Unterstützung,hätte nicht gedacht das es solche Probleme macht.
Habe den Code aus dem letzten Post 19:37:23 mal eingesetzt.
im Log steht:
2015-12-06_19:43:50 PV_Wirkungsgrad kein Wert
im FHEM Log steht kein Eintrag.
Alles andere können wir erst morgen sehen wenn wieder Werte anliegen
Melde mich dann.
Danke
MfG Iron
Man könnte es auch rechnerisch lösen, ohne einen großen Fehler zu erzeugen.
Wenn SOLAR_th:PV_Einstrahlung_eff = 0, dann sollte auch sv:wr11_currentPower = 0 sein, wenn man eine geringe Resteinstrahlung einführt, wirkt sich das kaum auf den Wirkungsgrad aus.
Wirkungsgrad = currentPOWER /(Einstahlung + 0.0000001)
Der Ausdruck (Einstahlung + 0.0000001) wird nie 0 und vermeidet die Division durch 0. Dann kann man "state" ohne if berechnen.
@Ellert
habe Dein Vorschlag mal als zusätzliches DOIF angelegt
define PV_Wirkungsgrad1 DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0)
attr PV_Wirkungsgrad1 state {([sv:wr11_currentPower]/([SOLAR_th:PV_Einstrahlung_eff]+ 0.0000001)*100)}
attr PV_Wirkungsgrad1 stateFormat {sprintf "%.2f %%", int(ReadingsVal($name, "state", 0))}
attr PV_Wirkungsgrad1 event-min-interval 600
attr PV_Wirkungsgrad1 event-on-change-reading state.*
attr PV_Wirkungsgrad1 verbose 5
define FileLog_PV_Wirkungsgrad1 FileLog ./log/PV_Wirkungsgrad1-%Y.log PV_Wirkungsgrad1
Zitat von: Iron-R am 06 Dezember 2015, 21:02:08
@Ellert
habe Dein Vorschlag mal als zusätzliches DOIF angelegt
define PV_Wirkungsgrad1 DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0)
attr PV_Wirkungsgrad1 state {([sv:wr11_currentPower]/([SOLAR_th:PV_Einstrahlung_eff]+ 0.0000001)*100)}
attr PV_Wirkungsgrad1 stateFormat {sprintf "%.2f %%", int(ReadingsVal($name, "state", 0))}
attr PV_Wirkungsgrad1 event-min-interval 600
attr PV_Wirkungsgrad1 event-on-change-reading state.*
attr PV_Wirkungsgrad1 verbose 5
define FileLog_PV_Wirkungsgrad1 FileLog ./log/PV_Wirkungsgrad1-%Y.log PV_Wirkungsgrad1
Das kannst du wiederum etwas einfacher haben:
define PV_Wirkungsgrad1 DOIF
attr PV_Wirkungsgrad1 state {(sprintf "%.2f %%", int([sv:wr11_currentPower]/([SOLAR_th:PV_Einstrahlung_eff]+ 0.0000001)*100))}
attr PV_Wirkungsgrad1 event-min-interval 600
attr PV_Wirkungsgrad1 event-on-change-reading state.*
attr PV_Wirkungsgrad1 verbose 5
define FileLog_PV_Wirkungsgrad1 FileLog ./log/PV_Wirkungsgrad1-%Y.log PV_Wirkungsgrad1
Gruß
Damian
Zitat von: Damian am 06 Dezember 2015, 19:37:23
oder so (ist auch weitgehend Perl):
attr PV_Wirkungsgrad state {([SOLAR_th:PV_Einstrahlung_eff] ? sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100):"kein Wert")}
Das hat mich auf die Idee gebracht das nachgestellte if zu probieren, das klappt auch:
attr PV_Wirkungsgrad state {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100) if ([SOLAR_th:PV_Einstrahlung_eff] != 0)}
Getestet habe ich mit:
{([BMP180:temperature]) if ([BMP180:temperature] != 0)}
Allerdings ist state leer/undef nach
setreading BMP180 temperature 0
Hallo Zusammen,
es gibt ein Ergebnis was gut aussieht:
diese Version:
Zitat von: Iron-R am 06 Dezember 2015, 21:02:08
@Ellert
habe Dein Vorschlag mal als zusätzliches DOIF angelegt
define PV_Wirkungsgrad1 DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0)
attr PV_Wirkungsgrad1 state {([sv:wr11_currentPower]/([SOLAR_th:PV_Einstrahlung_eff]+ 0.0000001)*100)}
attr PV_Wirkungsgrad1 stateFormat {sprintf "%.2f %%", int(ReadingsVal($name, "state", 0))}
attr PV_Wirkungsgrad1 event-min-interval 600
attr PV_Wirkungsgrad1 event-on-change-reading state.*
attr PV_Wirkungsgrad1 verbose 5
define FileLog_PV_Wirkungsgrad1 FileLog ./log/PV_Wirkungsgrad1-%Y.log PV_Wirkungsgrad1
hatte folgendes im Log:
2015-12-07_16:04:44 PV_Wirkungsgrad1 8.40336134012428
2015-12-07_16:04:46 PV_Wirkungsgrad1 7.35294117309148
2015-12-07_16:04:47 PV_Wirkungsgrad1 8.40336134012428
2015-12-07_16:04:49 PV_Wirkungsgrad1 7.35294117309148
2015-12-07_16:05:16 PV_Wirkungsgrad1 0
2015-12-07_16:34:03 PV_Wirkungsgrad1 0.00 %
Deine vereinfachte Version habe ich auch eingepflegt (letzter Log Eintrag) danach hat sich die PV-Anlage abgschaltet-keine Werte mehr.
Die Version mit iF bringt Fehler
2015-12-07_16:34:03 PV_Wirkungsgrad syntax error at (eval 126195) line 1, near ") if"
Muss noch mal testen habe den Fehler noch nicht gefunden.
Danke erst mal.
Viele Grüße
Iron
attr PV_Wirkungsgrad state {(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100) if ([SOLAR_th:PV_Einstrahlung_eff] != 0))}
die fehlende Klammer hatte ich schon eingefügt.
Der Fehler bleibt.
Hallo,
also die Logik erschließt sich mir nicht - was macht eine if-Abfrage ohne then für einen Sinn ? Das if müsste vor {(sprintf ....) stehen. Dann würde die Berechnung nicht ausgeführt, wenn der Wert 0 ist.
Gruß Christoph
@Bennemannc: https://wiki.selfhtml.org/wiki/Perl/Bedingte_Anweisungen#Nachgestellte_Bedingungen (https://wiki.selfhtml.org/wiki/Perl/Bedingte_Anweisungen#Nachgestellte_Bedingungen)
Zitat von: Bennemannc am 07 Dezember 2015, 19:41:41
Hallo,
also die Logik erschließt sich mir nicht - was macht eine if-Abfrage ohne then für einen Sinn ? Das if müsste vor {(sprintf ....) stehen. Dann würde die Berechnung nicht ausgeführt, wenn der Wert 0 ist.
Gruß Christoph
In Perl gibt es auch die Syntax mit einem nachgestellten if:
<Perl-Befehl> if (...)
Allerdings hat die Definition, die so aussehen müsste:
{(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100)) if ([SOLAR_th:PV_Einstrahlung_eff] != 0)}
den Nachteil, dass der Status leer wird, wenn die Bedingung nicht wahr ist.
Gruß
Damian
Hallo Damian,
das kannte ich noch nicht - ist für mich irgendwie blöde zu lesen, ungewohnt.
Gruß Christoph
@Damian
nachdem ich den Code eingefügt habe hat sich fhem verabschiedet
Zitat von: Damian am 07 Dezember 2015, 20:29:57
In Perl gibt es auch die Syntax mit einem nachgestellten if:
<Perl-Befehl> if (...)
Allerdings hat die Definition, die so aussehen müsste:
{(sprintf "%.2f %%", ([sv:wr11_currentPower]/[SOLAR_th:PV_Einstrahlung_eff]*100)) if ([SOLAR_th:PV_Einstrahlung_eff] != 0)}
den Nachteil, dass der Status leer wird, wenn die Bedingung nicht wahr ist.
Gruß
Damian
Fehler im fhem.log
Unmatched ( in regex; marked by <-- HERE in m/ {( <-- HERE sprintf[ :;]/ at fhem.pl line 2401, <$fh> line 559.
War der Code die Ursache?
Nachdem ich die fhem.pl neu aufgespielt habe ging alles wieder.
Hallo Zusammen,
der Code aus Post 16 läuft jetzt seit 5Tagen zufriedenstellen.
Danke für die Unterstützung
Grüße
Iron
Zitat von: Iron-R am 11 Dezember 2015, 17:30:45
Hallo Zusammen,
der Code aus Post 16 läuft jetzt seit 5Tagen zufriedenstellen.
Danke für die Unterstützung
Grüße
Iron
Man sollte allerdings wissen, dass beim state-Attribut mit Readingangaben [...] der Status unabhängig davon aktualisiert wird, was in der Bedingung steht, dafür habe ich im DOIF einen separaten Triggermechanismus eingebaut. Mit anderen Worten: die Abfrage
define PV_Wirkungsgrad1 DOIF ([SOLAR_th:PV_Einstrahlung_eff] != 0)
hat hier keine Bedeutung, man hätte die ganze Bedingung auch weglassen können. Sollen die Readingangaben im Status dagegen nicht selbstständig triggern, so muss man wie üblich ein Fragezeichen davor setzen.
Gruß
Damian