Schönen Nachmittag!
Ich kämpfe schon seit einigen Stunden mit folgendem DOIF und hoffe, dass mir jemand unter die Arme greifen kann.
define d_testa dummy
attr d_testa userReadings oldState { OldValue($NAME)}
define doif_test DOIF ([d_test1] eq "on" and [d_test2] eq "on") (set d_testa sleep) DOELSEIF ([d_test1] eq "on" and [d_test2] eq "off") ( IF ( {ReadingsVal("d_testa","oldState","") eq "away"} ) (set d_testa home,set d_testb home_zuvor_away) ELSE (set d_testa home,set d_testb home_zuvor_sleep) ) DOELSE (set d_testa away)
Der Ablauf ist folgender:
1. d_test1 und d_test2 sind off
-> d_testa:STATE=away -> OK
-> d_testb:STATE=initial -> OK (manuell gesetzt zur Veranschaulichung)
Internals:
NAME d_testa
NR 215
STATE away
TYPE dummy
READINGS:
2017-10-08 13:54:36 oldState home
2017-10-08 13:54:36 state away
Internals:
NAME d_testb
NR 211
STATE initial
TYPE dummy
READINGS:
2017-10-08 13:54:45 state initial
2. set d_test1 on
-> d_testa:STATE geht auf home -> OK
(man sieht hier auch, dass oldState funktioniert)
-> d_testb:STATE=home_zuvor_away -> OK
Internals:
NAME d_testa
NR 215
STATE home
TYPE dummy
READINGS:
2017-10-08 13:57:44 oldState away
2017-10-08 13:57:44 state home
Internals:
NAME d_testb
NR 211
STATE home_zuvor_away
TYPE dummy
READINGS:
2017-10-08 13:57:44 state home_zuvor_away
3. set d_test2 on
-> d_testa:STATE geht auf sleep -> OK
(oldState home passt auch)
Internals:
NAME d_testa
NR 215
STATE sleep
TYPE dummy
READINGS:
2017-10-08 14:00:30 oldState home
2017-10-08 14:00:30 state sleep
Internals:
NAME d_testb
NR 211
STATE home_zuvor_away
TYPE dummy
READINGS:
2017-10-08 13:57:44 state home_zuvor_away
4. set d_test2 off
-> d_testa:STATE geht auf home -> OK
-> aber d_testb:STATE geht nicht auf home_zuvor_sleep -> NOK
Internals:
NAME d_testa
NR 215
STATE home
TYPE dummy
READINGS:
2017-10-08 14:03:20 oldState sleep
2017-10-08 14:03:20 state home
Internals:
NAME d_testb
NR 211
STATE home_zuvor_away
TYPE dummy
READINGS:
2017-10-08 14:03:20 state home_zuvor_away
Die ELSE Anweisung innerhalb des DOIF greift also nicht und ich weiß nicht warum.
Ich hab's auch mit perl if nicht hinbekommen.
Das zeigt der Event monitor an dieser Stelle:
2017-10-08 14:22:12 dummy d_testa home
2017-10-08 14:22:12 dummy d_testa oldState: sleep
2017-10-08 14:22:12 dummy d_testb home_zuvor_away
2017-10-08 14:22:12 DOIF doif_test cmd_nr: 2
2017-10-08 14:22:12 DOIF doif_test cmd: 2
2017-10-08 14:22:12 DOIF doif_test cmd_event: d_test2
2017-10-08 14:22:12 DOIF doif_test cmd_2
2017-10-08 14:22:12 dummy d_test2 off
Und das steht im log:
2017.10.08 14:24:20 5: Cmd: >set d_test2 off<
2017.10.08 14:24:20 4: dummy set d_test2 off
2017.10.08 14:24:20 5: Starting notify loop for d_test2, 1 event(s), first is off
2017.10.08 14:24:20 5: Cmd: >IF ( {ReadingsVal("d_testa","oldState","") eq "away"} ) (set d_testa home,set d_testb home_zuvor_away) ELSE (set d_testa home,set d_testb home_zuvor_sleep)<
2017.10.08 14:24:20 5: Cmd: >{if( {ReadingsVal("d_testa","oldState","") eq "away"} ){fhem('set d_testa home');fhem('set d_testb home_zuvor_away')}else{fhem('set d_testa home');fhem('set d_testb home_zuvor_sleep')}}<
2017.10.08 14:24:20 1: PERL WARNING: Odd number of elements in anonymous hash at (eval 86072) line 1.
2017.10.08 14:24:20 3: eval: {if( {ReadingsVal("d_testa","oldState","") eq "away"} ){fhem('set d_testa home');fhem('set d_testb home_zuvor_away')}else{fhem('set d_testa home');fhem('set d_testb home_zuvor_sleep')}}
2017.10.08 14:24:20 5: Cmd: >set d_testa home<
2017.10.08 14:24:20 4: dummy set d_testa home
2017.10.08 14:24:20 5: Starting notify loop for d_testa, 2 event(s), first is home
2017.10.08 14:24:20 5: End notify loop for d_testa
2017.10.08 14:24:20 5: Cmd: >set d_testb home_zuvor_away<
2017.10.08 14:24:20 4: dummy set d_testb home_zuvor_away
2017.10.08 14:24:20 5: Starting notify loop for d_testb, 1 event(s), first is home_zuvor_away
2017.10.08 14:24:20 5: End notify loop for d_testb
2017.10.08 14:24:20 5: Starting notify loop for doif_test, 4 event(s), first is cmd_nr: 2
2017.10.08 14:24:20 5: End notify loop for doif_test
2017.10.08 14:24:20 5: End notify loop for d_test2
Hat jemand Rat?
Auch bessere Lösungen sind gerne willkommen.
Mir gefällt diese (abgesehen davon, dass sie nicht funktioniert) eh nicht 100%ig, aber mir fällt nichts besseres ein :-\)
Danke im Voraus!
Gruß,
kroman
Ich habs jetzt nicht genauer analysiert, aber ich denke die geschweiften Klammern in deinem IF sind ein Problem. Du verwendest diese um auf die perl-Ebene zu kommen, das ist aber für IF laut commandref gar nicht nötig:
ZitatThe <condition> is the same as in perl-if
Ich vermute mal, dass daher auch die perl-Warnung kommt
Odd number of elements in anonymous hash at (eval 86072) line 1.
Ja, IF ( {ReadingsVal("d_testa","oldState","") eq "away"} )
=> IF ( [d_testa:oldState] eq "away" )
Danke euch beiden mal!
Da war ich jedoch auch schon denke ich.
Hier funktioniert schon Schritt 2 nicht.
([d_test1] eq "on" and [d_test2] eq "on") (set d_testa sleep) DOELSEIF ([d_test1] eq "on" and [d_test2] eq "off") ( IF ( [d_testa:oldState] eq "away" ) (set d_testa home,set d_testb home_zuvor_away) ELSE (set d_testa home,set d_testb home_zuvor_sleep) ) DOELSE (set d_testa away)
1. d_test1 und d_test2 sind off
-> d_testa:STATE=away -> OK
-> d_testb:STATE=initial -> OK (manuell gesetzt zur Veranschaulichung)
Internals:
NAME d_testa
NR 215
STATE away
TYPE dummy
READINGS:
2017-10-08 19:45:22 oldState home
2017-10-08 19:45:22 state away
Internals:
NAME d_testb
NR 211
STATE initial
TYPE dummy
READINGS:
2017-10-08 19:49:42 state initial
2. set d_test1 on
-> d_testa:STATE geht auf home -> OK
-> d_testb:STATE=home_zuvor_sleep, sollte aber home_zuvor_away sein -> NOK
Internals:
NAME d_testa
NR 215
STATE home
TYPE dummy
READINGS:
2017-10-08 19:50:54 oldState away
2017-10-08 19:50:54 state home
Internals:
NAME d_testb
NR 211
STATE home_zuvor_sleep
TYPE dummy
READINGS:
2017-10-08 19:50:54 state home_zuvor_sleep
2017.10.08 19:50:54 5: Cmd: >set d_test1 on<
2017.10.08 19:50:54 4: dummy set d_test1 on
2017.10.08 19:50:54 5: Starting notify loop for d_test1, 1 event(s), first is on
2017.10.08 19:50:54 5: Cmd: >IF ( [d_testa:oldState] eq "away" ) (set d_testa home,set d_testb home_zuvor_away) ELSE (set d_testa home,set d_testb home_zuvor_sleep)<
2017.10.08 19:50:54 5: Cmd: >{if( ReadingValIf('d_testa','oldState','') eq "away" ){fhem('set d_testa home');fhem('set d_testb home_zuvor_away')}else{fhem('set d_testa home');fhem('set d_testb home_zuvor_sleep')}}<
2017.10.08 19:50:54 5: Cmd: >set d_testa home<
2017.10.08 19:50:54 4: dummy set d_testa home
2017.10.08 19:50:54 5: Starting notify loop for d_testa, 2 event(s), first is home
2017.10.08 19:50:54 5: End notify loop for d_testa
2017.10.08 19:50:54 5: Cmd: >set d_testb home_zuvor_sleep<
2017.10.08 19:50:54 4: dummy set d_testb home_zuvor_sleep
2017.10.08 19:50:54 5: Starting notify loop for d_testb, 1 event(s), first is home_zuvor_sleep
2017.10.08 19:50:54 5: End notify loop for d_testb
2017.10.08 19:50:54 5: Starting notify loop for doif_test, 4 event(s), first is cmd_nr: 2
2017.10.08 19:50:54 5: End notify loop for doif_test
2017.10.08 19:50:54 5: End notify loop for d_test1
Kann es sein, dass DOIF schneller ist als oldState?
Aber bei dem Moment, wo Du "set d_test1 on" machst, ist d_testa:oldState noch gleich "home".
Dann kommt das Event "d_test1 on", der triggert dein DOIF, der prüft die Bedingung (dann immer noch "home"), und führt den Befehl aus "ELSE (set d_testa home,set d_testb home_zuvor_sleep)"
Erst dann kommt das Event "d_testa home", der triggert den userReading, und dies (oldState) wechselt zu away.
Es scheint mir alles ganz normal zu sein. Das DOIF ist nicht schneller als oldState. Das DOIF löst das Event aus, das oldState dann ändert.
@anemode: absolut richtig
@kroman: das problem ist ja, dass auch userReadings ja auf die events reagieren und damit im selben notify loop wie der DOIF laufen, damit kannst Du nicht damit rechnen, dass das user reading bereits gewechselt hat.
Danke Leute!
Ich hatte einen Knopf im Hirn.
Ich brauche ja nur d_testa:state statt d_testa:oldState zu verwenden, dann funktioniert alles wie ich will.
Wie bin ich nur auf diesen oldState gekommen? (Frage an mich selbst)
Darüber werde ich morgen früh nochmal mit frischem Kopf nachdenken.
Überhaupt kein Thema - ich habe auch mindestens eine halbe Stunde draufgestarrt, bis mir endlich klar wurde, dass eigentlich kein Fehler besteht
Zitat@anemode: absolut richtig
Wer ist das? ;)
@amenomade: Oops - bitte vielstmals um Entschuldigung - kleine Rechtschreibstörung am Abend - wenn man einmal nicht Ctrl-C/Ctrl-V macht - schon ist es verkehrt
Kein Thema. Wenn man 1/2 Stunde lang auf ein DOIF starrt, fängt man bestimmt an, zu schielen ;)
Dann könnt ihr euch vorstellen wie's mir geht, ich starr da schon fast durchgehend seit gestern drauf ;D
Warum löst du das IF nicht ohnehin einfach auf und machst zwei DOELSEIF-Zweige draus? So groß ist die Ersparnis auch nicht auf der Vergleichsseite.
Und bitte: verwende <Enter>, um den Code lesbarer zu machen.
([d_test1] eq "on" and [d_test2] eq "on") (set d_testa sleep)
DOELSEIF ([d_test1] eq "on" and [d_test2] eq "off" and [d_testa:oldState] eq "away" ) (set d_testa home,set d_testb home_zuvor_away)
DOELSEIF ([d_test1] eq "on" and [d_test2] eq "off") (set d_testa home,set d_testb home_zuvor_sleep)
DOELSE (set d_testa away)
(hier mal noch mit "oldState")
Noch besser wird es mit <Enter> und <Tab>, letzteren muss man aber rein kopieren, z.B. aus einem echten Editor oder einem alten Beitrag.
([d_test1] eq "on" and [d_test2] eq "on")
(set d_testa sleep)
DOELSEIF ([d_test1] eq "on" and [d_test2] eq "off" and [d_testa:oldState] eq "away" )
(set d_testa home,set d_testb home_zuvor_away)
DOELSEIF ([d_test1] eq "on" and [d_test2] eq "off")
(set d_testa home,set d_testb home_zuvor_sleep)
DOELSE
(set d_testa away)
Zitat<Tab>, letzteren muss man aber rein kopieren, z.B. aus einem echten Editor oder einem alten Beitrag
Oder man aktiviert CodeMirror https://wiki.fhem.de/wiki/Konfiguration#Syntaxhervorhebung
Dann funktioniert TAB. Und dazu profitiert man von Syntaxhervorhebungs-, Befehlsauswahl- und Befehlsvervollständigungsfunktionen.
Zitat von: amenomade am 09 Oktober 2017, 16:44:46Oder man aktiviert CodeMirror
Stimmt, auf Fhem habe ich das. Aber im Forum funktioniert das noch nicht ;).
Zitat
Warum löst du das IF nicht ohnehin einfach auf und machst zwei DOELSEIF-Zweige draus? So groß ist die Ersparnis auch nicht auf der Vergleichsseite.
Danke für den Vorschlag Per, das ist vielleicht die übersichtlichere Variante, wenn auch Geschmackssache würde ich sagen.
Zitat
Und bitte: verwende <Enter>, um den Code lesbarer zu machen.
Darüber hab ich sogar nachgedacht, doch es dann gelassen, weil ich nicht wußte ob (um alles richtig zu machen) ich nun den Backslash am Ende ranmachen muss oder nicht.
Also nicht, weil man ja von der DEF ausgeht und nicht von der fhem.cfg, richtig?
Ich werde das aber künftig beherzigen.
Codemirror hatte ich schon mal in Verwendung, aber dann wieder abgeschalten weil die DEF keinen Zeilenbruch macht und man bei langen defines immer links und rechts scrollen muss. Wenn man den Zeilenumbruch manuell macht, steht der auch in der fhem.cfg was mich hauptsächlich beim grepen stört.
Also auch hier:
https://forum.fhem.de/index.php?topic=40836.0
Leider, sonst hätte ich es angelassen.
attr WEB codemirrorParam { "lineWrapping":true }
Jetzt bin ich wieder dabei.