Hallo zusammen,
ich habe bei mir mittlerweile eine relativ komplexe Anwesenheitserkennung realisiert. Teil davon ist u.a. auch ein NFC-Reader, der auf Tags lauscht, die wir am Schlüsselbund haben. Abhängig vom Tag und von der Ausgangssituation schaltet ein Notify unterschiedliche "Szenen". Soweit funktioniert das auch eigentlich ganz gut.
Meine Frage hierbei ist nun, ob es bei {if....}-Verzweigungen eine gewisse maximale Verschachtelungstiefe bei FHEM gibt?
Der Code meines Notifys sieht folgendermaßen aus:
NFC_Wolle {if ((Value("rr_Wolle") eq "anwesend") && (Value("rr_Tanja") eq "abwesend") && (Value("Alle_Fenster_check") eq "eines_offen") && ((ReadingsVal("Alarmanlage","short","0") eq "0") || (ReadingsVal("Alarmanlage","short","") eq ""))) {
fhem("set MyTTS tts Achtung! Es ist noch ein Fenster geöffnet!;
set Flur_Garderobenlampe on-for-timer 1;
sleep 1.5;
set Flur_Garderobenlampe on-for-timer 1;
sleep 3;
set Flur_Garderobenlampe on-for-timer 1;
sleep 1.5;
set Flur_Garderobenlampe on-for-timer 1")
}
elsif ((Value("rr_Wolle") eq "anwesend") && ((ReadingsVal("Alarmanlage","short","0") eq "0") || (ReadingsVal("Alarmanlage","short","") eq ""))) {
fhem("setstate Anwesenheit_Wolle_bt_w defined;
setstate Anwesenheit_Wolle_wlan_w defined;
set Wolle_anwesend_wlan 0;
set Wolle_anwesend_bt 0;
set Flur_Decke on-for-timer 1;
attr Anwesenheit_Wolle_bt_w disable 1;
attr Anwesenheit_Wolle_wlan_w disable 1;
set rr_Wolle abwesend;
set MyTTS tts Auf Wiedersehen Wolle;
sleep 900;
attr Anwesenheit_Wolle_bt_w disable 0;
attr Anwesenheit_Wolle_wlan_w disable 0");
Log 3, "Änderung Bewohneranwesenheit detektiert: Wolle abwesend"
}
elsif ((Value("rr_Wolle") eq "abwesend") && ((ReadingsVal("Alarmanlage","short","0") eq "0") || (ReadingsVal("Alarmanlage","short","") eq ""))) {
fhem("set rr_Wolle anwesend;
set MyTTS tts Willkommen zu Hause Wolle;
set Wolle_anwesend_wlan 1;
set Wolle_anwesend_bt 1");
{if((Value("rr_Tanja") eq "abwesend") && (($hour < "23") && ($hour > "06"))) {fhem("set WZ_Media_Dummy on")}};
{if((!isday()) && (($hour < "23") && ($hour > "06"))) {fhem("set AZ_Wolle_Decke on")}};
{if((ReadingsVal("Wolle_internet","isRunning","") ne "true") && (($hour < "23") && ($hour > "06"))) {fhem("set Wolle_internet on")}};
{if (Value("rr_Tanja") eq "abwesend") {fhem("set WZ_Weihnachtsbaum on")}};
{if((!isday()) && (Value("rr_Tanja") eq "abwesend")) {fhem("set KU_Unterschrankbeleuchtung on")}}
}
elsif ((ReadingsVal("Alarmanlage","short","0") ne "0") && (ReadingsVal("Alarmanlage","short","") ne ""))
{Alarm_Reset}
}
Es wird auch alles richtig geschaltet, je nach Ausgangssituation, wenn ich den Tag an den Reader halte: Das Problem ist nur beim zweiten "elsif". Hier werden die "set" Kommandos alle ausgeführt, aber die eigenständigen {if...} Unterprüfungen werden ignoriert. Es findet sich im Logfile auch keinerlei Fehlermeldung. Es ist einfach als wenn die Zeilen nicht da wären.
Dem geneigten erfahrenen Programmierer werden wahrscheinlich bei dem Code die Haare zu Berge stehen, aber er wird daraus wohl erkennen, dass ich alles andere als ein Programmierer bin ;D
Für Hilfestellung und einen Fingerzeig wäre ich sehr dankbar.
Gruß
Wolle
Bevor du irgendwie versuchst, hier noch weiter am notify herumzubasteln, lagere den Perl-Code in eine sub in einer myUtils aus. Das macht dir das Leben leichter.
Zum vorhandenen Code: Es ist nicht nötig die if-Abfragen in {} zu setzen. Du setzt insgesamt viel zu viele Klammern (das ist nicht schlimm und macht es nicht zwingend falsch, mindert aber die Übersicht und führt schnell zu Klammerfehlern). Eine Zeile, wie
{if((Value("rr_Tanja") eq "abwesend") && (($hour < "23") && ($hour > "06"))) {fhem("set WZ_Media_Dummy on")}};
kann zum Beispiel so aussehen
fhem("set WZ_Media_Dummy on") if(Value("rr_Tanja") eq "abwesend" && $hour < 23 && $hour > 6);
und bleibt trotzdem korrekt und hat die gleiche Funktion.
Im einzelnen habe ich jetzt nicht nach Klammerfehlern gesucht, tippe aber darauf, dass hier das Problem liegt.
Hallo Marvin,
ja mit Syntax habe ich immer so meine Schwierigekeiten. Irgenwo im Wiki habich mal einen Codeschnipsel gefunden, der mir Syntaxhighlightning eingebaut hat. Das war sehr hilfreich und seit dem sind die Klammerfehler merkbar zurückgegangen. Auch im vorliegenden Fall wird mir durch das Syntaxhighlightning kein Klammerfehler angezeigt. Und wie gesagt, es finden sich keine Fehler im Log; bei einem Syntaxproblem wäre das eigentlich der Fall.
Zum Problem: Ich hatte den nicht ganz funktionierenden Teil mal als eigenständiges Notify gehabt und da funktioniere alles wie es soll; erst seit ich das Ganze in ein großes if...elsif-Konstrukt gepackt habe funktionieren die eigenständigen if-Prüfungen nicht mehr.
Deinen Vorschlag alles in eine Subroutine auszulagern habe ich auch schon probiert. Ich hatte jeden if....elsif-Block in einer eigenen Unterroutine (ein Überbleibsel siehst du noch ganz unten bei {Alarm_Reset}. Das war zwar dann im Notify übersichtlicher, aber leider hat es an der Funktionalität rein gar nicht geändert. Auch hier wurden die {if...}-Prüfungen einfach ignoriert.
Naja. Es könnte auch daran liegen, dass du logische Fehler drin hast, sodass die Bedingungen niemals wahr werden.
Der Wert in $hour ist z.B. ein Integer. Ein Vergleicht mit einem Wert in Anführungszeichen macht also keinen Sinn. Ekläre mal gerade, was du z.B. hiermit genau sagen möchtest:
if((!isday()) && (($hour < "23") && ($hour > "06")))
Das ist eine Bedingung, die so, wie sie da steht besagt, dass es Nacht und zwischen 6 und 23 Uhr sein soll. Das ist aktuell kein sehr langer Zeitraum. Selbst wenn du aber genau diesen Zeitraum meisnt, schreibe es doch besser so:
if (!isday() && $hour < 23 && $hour > 6)
Das Leerzeichen hinter dem if bitte nicht vergessen!
Wie gesagt: Die Syntax hat so bereits funktioniert, als es noch ein eigenes Notify war und sie wurde genauso übernommen. Aber ich werde die andere Schreibweise gerne mal ausprobieren. Ich schreib heut nachmittag das Ergebnis.
Was die Funktion soll hast du ja genau erfasst: Wenn ich heimkomme und es draußen dunkel ist und es vor 23 Uhr ist, dann soll im Arbeitszimmer das Licht angehen und der Rechner hochfahren.
Dass das momentan ein recht kurzer Zeitraum ist, ist ja egal. Es soll ja auch mal wieder Winter werden ;)
Hallo, vlt. kann das eine Anregung für dich sein. Ich schalte, wenn die Tür geöffnet wird und es Nacht ist, zwischen 17:00 Uhr und 24:00 Uhr das Licht für 2min ein:
Schalter_Tuer:open { if(!isday() && $hour ~~ [17..24]) { fhem "set Licht_SZ on-for-timer 120" } }
läuft seit 2 Jahren problemlos und wenn es 17:00 Uhr ist aber eben noch nicht Nacht, wird nicht geschaltet :)
VG
Frank
Hallo Frank,
danke für deine Anregung. Aber das wäre ja auch wieder eine {if...} Prüfung, wenn auch mit anderem Code. Das Problem ist ja nicht gewesen, dass der Code nicht funktioniert, sondern dass er in dem Kontext dieses großen if ...elsif...if-Konstruktes aus irgendeinem grund nicht ausgeführt wurde.
So, aber nun bin ich gerade wieder heimgekommen und wollte nun Marvins Code ausprobieren, damit ich die versprochene Rückmeldung geben kann und was soll ich sagen...... ich komme zur Türe rein, das Notify hat getriggert und mein Rechner ist hochgefahren. Ich habe bislang rein gar nichts geändert seit ich mit Marvin gepostet habe. Ich versteh es nicht.
Jedenfalls weiß ich jetzt, dass es nicht an der Verschachtelung und auch nicht an der Syntax gelegen haben kann. Muss ich wohl mal weiter forschen, falls das Problem wieder auftritt.
Ich danke euch aber für die Anregungen zur Codevereinfachung. Da ist sicherlich noch Optimierungspotential. ;D ;)
Deshalb meinte ich, dass du evtl. einen Logikfehler hast. Der muss nicht unbedingt im Code liegen. Eventuell hat eine der Bedingungen auch zum erwarteten Zeitpunkt, nicht den Status, der erwartet wurde (von dir).