Hauptmenü

Alarmfunktion mit DOIF

Begonnen von PsychoD, 06 März 2016, 01:13:31

Vorheriges Thema - Nächstes Thema

PsychoD

Hi,

ich versuche  mittels DOIF eine warnende Alarmfunktion zu realisieren. Leider scheitere ich fast auf ganzer Linie. Zunächst, was passieren soll:

Es gibt:
- HM-Türsensor
- Dummy: Anwesenheitsstatus
- TTS Sprachausgabe
- Rauchmelder als Sirene

Wenn der Anwesenheitsstatus auf "Abwesend" steht, und die Tür geöffnet wird, soll dreimal mittels Sprachausgabe gewarnt werden. Dabei sollen die Sprachausgaben einen Abstand von 5 Sekunden haben. Das soll nicht abgebrochen werden, auch wenn die Türe wieder geschlossen wird, oder sich der Anwesenheitsstatus ändert.
Nach 20 Sekunden soll, sofern in der Zwischenzeit der Anwesenheitsstatus nicht auf Anwesend gewechselt wurde, die Sirene ausgelöst werden. Dabei soll egal sein, ob die Türe noch offen ist, oder nicht.

Ich habe nun die verschiedene Dinge probiert, scheitere aber weiterhin, und bitte euch daher um Hilfe. Insb. scheint die Verwendung von mehreren fhem-sleep problematisch zu sein. Ich habe darüber hinaus Probleme nachzuvollziehen, wann (und wie viele) ";" und "\" am Ende der Zeilen zu verwenden sind. Auch da würd ich mich über einen Hinweis oder Link freuen. Stimmt das nicht, wird mir manchmal der Code ganz unnachvollziehbar zerhauen.
Ich hatte es auch an repeatcmd gedacht, aber sobald die Türe dann geschlossen wird, wird die Kommandoausführung abgebrochen, was ich natürlich nicht gebrauchen kann. 

Hier mein aktueller Testcode:


define di_alarm DOIF ([flur_wohnungstuer:"open"] and [HomeStatus] eq "Abwesend")\
( {my $stamp = TimeNow();;sendPush("ALARM","$stamp: Türöffnung bei Abwesenheit!","digital-alarm")};;\
sleep 5;;\
set speakerbot tts Alarm ausgelöst;;\
sleep 8;;\
set speakerbot tts Alarm ausgelöst;;\
sleep 8;;\
set speakerbot tts Alarm ausgelöst;;\
{if ( Value("HomeStatus") eq "Abwesend" ) {\
fhem("set fl_rauchmelder teamCall");;\
sendPush("Ohoh...","$stamp: Jetzt wirds laut!","digital-alarm");;}})
attr di_alarm do always
attr di_alarm room Flur



Danke für jeden Rat!

VG
Psy

Damian

#1
Zitat von: PsychoD am 06 März 2016, 01:13:31
Hi,

ich versuche  mittels DOIF eine warnende Alarmfunktion zu realisieren. Leider scheitere ich fast auf ganzer Linie. Zunächst, was passieren soll:

Es gibt:
- HM-Türsensor
- Dummy: Anwesenheitsstatus
- TTS Sprachausgabe
- Rauchmelder als Sirene

Wenn der Anwesenheitsstatus auf "Abwesend" steht, und die Tür geöffnet wird, soll dreimal mittels Sprachausgabe gewarnt werden. Dabei sollen die Sprachausgaben einen Abstand von 5 Sekunden haben. Das soll nicht abgebrochen werden, auch wenn die Türe wieder geschlossen wird, oder sich der Anwesenheitsstatus ändert.
Nach 20 Sekunden soll, sofern in der Zwischenzeit der Anwesenheitsstatus nicht auf Anwesend gewechselt wurde, die Sirene ausgelöst werden. Dabei soll egal sein, ob die Türe noch offen ist, oder nicht.

Ich habe nun die verschiedene Dinge probiert, scheitere aber weiterhin, und bitte euch daher um Hilfe. Insb. scheint die Verwendung von mehreren fhem-sleep problematisch zu sein. Ich habe darüber hinaus Probleme nachzuvollziehen, wann (und wie viele) ";" und "\" am Ende der Zeilen zu verwenden sind. Auch da würd ich mich über einen Hinweis oder Link freuen. Stimmt das nicht, wird mir manchmal der Code ganz unnachvollziehbar zerhauen.
Ich hatte es auch an repeatcmd gedacht, aber sobald die Türe dann geschlossen wird, wird die Kommandoausführung abgebrochen, was ich natürlich nicht gebrauchen kann. 

Hier mein aktueller Testcode:


define di_alarm DOIF ([flur_wohnungstuer:"open"] and [HomeStatus] eq "Abwesend")\
( {my $stamp = TimeNow();;sendPush("ALARM","$stamp: Türöffnung bei Abwesenheit!","digital-alarm")};;\
sleep 5;;\
set speakerbot tts Alarm ausgelöst;;\
sleep 8;;\
set speakerbot tts Alarm ausgelöst;;\
sleep 8;;\
set speakerbot tts Alarm ausgelöst;;\
{if ( Value("HomeStatus") eq "Abwesend" ) {\
fhem("set fl_rauchmelder teamCall");;\
sendPush("Ohoh...","$stamp: Jetzt wirds laut!","digital-alarm");;}})
attr di_alarm do always
attr di_alarm room Flur



Danke für jeden Rat!

VG
Psy

Sleep ist im Normalfall bei DOIF überflüssig, weil man Sequenzen mit wait definieren kann. Wenn du do always definierst, dann gibt es auch keinen cmd_2-Fall und deine Ausführung wird nicht unterbrochen.

Befehlssequenzen mit Sleep:

...
(set speakerbot tts Alarm ausgelöst)
(set speakerbot tts Alarm ausgelöst)
...

attr ... wait 8,8


In der Commandref sind einige Beispiele zu Befehlssequenzen. Trennzeichen ist Komma statt Semikolon. Editieren am besten über Web-Oberfläche, dann gibt´s einen Syntax-Check umsonst ;)

Gruß

Damian
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PsychoD

Hallo Damian,

Danke für deinen Rat! Ich habe es nun so umgesetzt. Mir war nicht klar, dass ich kein "sleep" brauche, und dass das Command nicht abgebrochen wird, wenn die auslösenden Voraussetzungen nicht mehr gegeben sind. Da blicke ich wohl noch nicht ganz durch ;-)

So klappt es jedenfalls bei mir (Editiert mit DEF-Editor, C&P aber aus cfg):

define di_alarm DOIF ([flur_wohnungstuer:"open"] and [HomeStatus] eq "Abwesend")\
( {my $stamp = TimeNow();;;;sendPush("Türöffnung","$stamp: Türöffnung bei Abwesenheit!","digital-alarm")})\
(set speakerbot tts Alarm ausgelöst - Türöffnung bei Abwesenheit)\
(set speakerbot tts Alarm ausgelöst - Verständige Sicherheitsdienst)\
(set speakerbot tts Alarm ausgelöst - Sicherheitsdienst unterwegs)\
( {\
if ( Value("HomeStatus") eq "Abwesend" ) {\
my $stamp = TimeNow();;;;sendPush("ALARM","$stamp: Jetzt wirds laut!","digital-alarm");;;;fhem("set fl_rauchmelder teamCall")\
} else {\
my $stamp = TimeNow();;;;sendPush("Alarm deactivated","$stamp: Alarm deaktiviert.","digital-alarm")\
}\
}\
)
attr di_alarm do always
attr di_alarm room Flur
attr di_alarm wait 0,5,5,5,0


Nochmal Danke und viele Grüße
Damian <-- wir sind Namensvettern ;)

Damian

Konstrukte der Art:

( {my $stamp = TimeNow();;;;sendPush("Türöffnung","$stamp: Türöffnung bei Abwesenheit!","digital-alarm")})

Kannst du im DOIF etwas einfacher ohne zusätzliche Variablen definieren:

((sendPush("Türöffnung","{(TimeNow)}: Türöffnung bei Abwesenheit!","digital-alarm"))

Gruß

Damian
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PsychoD

Danke! Cooles Konstrukt dieses DOIF. Nachdem ich etwas länger brauchte es zu verstehen und mir "sleep" den letzten Nerv geraubt hat bin ich echt froh damit :)

Ich habe noch ein paar Verständnisfragen:

1) Aus der Commandref war mir nicht ganz klar, in welchen Fällen ein DOELSE ausgeführt würde (FALLS ich mal eins brauche). Denn: Vom programmieren kennt man "If ... then...else...", das zu einem bestimmten Zeitpunkt aufgerufen wird, und der Zustand der Bedingung zu dem Zeitpunkt ausgewertet wird. DOIF wird dann durch Events o.ä. getriggert, wenn die Bedingung wahr ist - aber DOELSE doch sicher nicht permanent, wenn die Bedingung falsch ist, oder? Wann wird also DOELSE oder DOELSEIF ausgelöst? 

2) In der Commandref gibt es das Beispiel "Waschmaschine fertig": "wenn Verbrauch mindestens 5 Minuten unter 2 Watt"
define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})
attr di_washer wait 300


Also interpretiere ich es so, dass das DOIF ausgelöst wird, wenn der Verbrauch unter 2 Watt fällt, und nach 300 Sekunden geprüft wird, ob die Bedingung noch immer gegeben ist. Erst dann wird das PERL Command ausgeführt.

Prinzipiell verwendet das Beispiel ja den gleichen Aufbau wie mein Alarm-DOIF, daher hätte ich erwartet, dass das Command auch dann ausgeführt wird, wenn der Verbrauch nochmal steigt, denn die Commandabarbeitung bei mir erfolgt ja auch, wenn die Tür wieder geschlossen wird. Der einzige für mich erkennbare Unterschied ist das "do always" bei mir, was ich jedoch so interpretiert habe, dass eine erneute Auslösung erfolgen kann, wenn die Bedingungen erneut getriggert werden, ohne dass zwischendurch ein anderer Wert getriggert wurde.   

Ich bin dir sehr dankbar, wenn du mir da auf die Sprünge helfen könntest ;)

Danke & Gruß
Damian

Damian

Zitat von: PsychoD am 08 März 2016, 08:34:13
Danke! Cooles Konstrukt dieses DOIF. Nachdem ich etwas länger brauchte es zu verstehen und mir "sleep" den letzten Nerv geraubt hat bin ich echt froh damit :)

Ich habe noch ein paar Verständnisfragen:

1) Aus der Commandref war mir nicht ganz klar, in welchen Fällen ein DOELSE ausgeführt würde (FALLS ich mal eins brauche). Denn: Vom programmieren kennt man "If ... then...else...", das zu einem bestimmten Zeitpunkt aufgerufen wird, und der Zustand der Bedingung zu dem Zeitpunkt ausgewertet wird. DOIF wird dann durch Events o.ä. getriggert, wenn die Bedingung wahr ist - aber DOELSE doch sicher nicht permanent, wenn die Bedingung falsch ist, oder? Wann wird also DOELSE oder DOELSEIF ausgelöst? 

2) In der Commandref gibt es das Beispiel "Waschmaschine fertig": "wenn Verbrauch mindestens 5 Minuten unter 2 Watt"
define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})
attr di_washer wait 300


Also interpretiere ich es so, dass das DOIF ausgelöst wird, wenn der Verbrauch unter 2 Watt fällt, und nach 300 Sekunden geprüft wird, ob die Bedingung noch immer gegeben ist. Erst dann wird das PERL Command ausgeführt.

Prinzipiell verwendet das Beispiel ja den gleichen Aufbau wie mein Alarm-DOIF, daher hätte ich erwartet, dass das Command auch dann ausgeführt wird, wenn der Verbrauch nochmal steigt, denn die Commandabarbeitung bei mir erfolgt ja auch, wenn die Tür wieder geschlossen wird. Der einzige für mich erkennbare Unterschied ist das "do always" bei mir, was ich jedoch so interpretiert habe, dass eine erneute Auslösung erfolgen kann, wenn die Bedingungen erneut getriggert werden, ohne dass zwischendurch ein anderer Wert getriggert wurde.   

Ich bin dir sehr dankbar, wenn du mir da auf die Sprünge helfen könntest ;)

Danke & Gruß
Damian

Bsp.:

DOIF ([mydevice1] eq "on")(set bla 1)
DOELESEIF ([mydevice2] eq "on") (set bla 2)
DOELSE (set bla 3)


Trigger von mydevice1 mit mydevice1=off:

DOIF wird ausgewertet nicht wahr -> weiter schauen
DOELSEIF wird nicht ausgewertet, da mydevice1 dort nicht vorkommt -> weiter schauen
DOELSE wird ausgeführt.

Trigger von mydevice2 mit mydevice2=on:

DOIF wird nicht ausgewertet, da mydevice2 dort nicht vorkommt -> weiter schauen
DOELSEIF wird ausgewertet -> Bedingung wahr-> Befehl wird ausgeführt -> Ende

Es gibt eine Ausnahme:

Ohne do always wird cmd_2 auch  dann gesetzt, auch wenn es kein DOELSE gibt:

define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})

entspricht dann:

define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")}) DOELSE

Gruß

Damian
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

PsychoD

Zitat von: Damian am 08 März 2016, 09:29:31
Bsp.:

DOIF ([mydevice1] eq "on")(set bla 1)
DOELESEIF ([mydevice2] eq "on") (set bla 2)
DOELSE (set bla 3)


Trigger von mydevice1 mit mydevice1=off:

DOIF wird ausgewertet nicht wahr -> weiter schauen
DOELSEIF wird nicht ausgewertet, da mydevice1 dort nicht vorkommt -> weiter schauen
DOELSE wird ausgeführt.

Trigger von mydevice2 mit mydevice2=on:

DOIF wird nicht ausgewertet, da mydevice2 dort nicht vorkommt -> weiter schauen
DOELSEIF wird ausgewertet -> Bedingung wahr-> Befehl wird ausgeführt -> Ende

Danke für das Beispiel, wird jetzt klarer! :) Also wird DOIF immer dann getriggert, wenn sich ein in der Bedingung (egal ob im DOIF- oder DOESLEIF-Teil) vorkommender Trigger wie auch immer verändert.

Zitat von: Damian am 08 März 2016, 09:29:31
Es gibt eine Ausnahme:

Ohne do always wird cmd_2 auch  dann gesetzt, auch wenn es kein DOELSE gibt:

define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})

entspricht dann:

define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")}) DOELSE

Gruß

Damian

Das verstehe ich noch nicht ganz. Was genau wird mit "cmd_1", "cmd_2" etc. bezeichnet? Intuitiv hätte ich jetzt gedacht, das sind die angegebenen Befehle - jedoch gibt es davon ja nur einen in deinem Beispiel, nämlich ({system("wmail washer finished")}).

Gruß & Danke für deine Mühe
Damian

Damian

#7
Zitat von: PsychoD am 10 März 2016, 08:25:26
Danke für das Beispiel, wird jetzt klarer! :) Also wird DOIF immer dann getriggert, wenn sich ein in der Bedingung (egal ob im DOIF- oder DOESLEIF-Teil) vorkommender Trigger wie auch immer verändert.

Das verstehe ich noch nicht ganz. Was genau wird mit "cmd_1", "cmd_2" etc. bezeichnet? Intuitiv hätte ich jetzt gedacht, das sind die angegebenen Befehle - jedoch gibt es davon ja nur einen in deinem Beispiel, nämlich ({system("wmail washer finished")}).

Gruß & Danke für deine Mühe
Damian

Genau. Im Normalfall werden die Zustände cmd_1, cmd_2 entsprechend der ausgeführten Zweige gesetzt. Wenn kein DOELSE-Fall angegeben wird, dann wird auch kein entsprechender Zustand gesetzt, außer man hat nur einen einzigen Fall, wie im obigen Waschmaschinen-Bespiel. Hier wird falls der DOIF-Fall nicht zutrifft (nicht wahr ist), der Zustand cmd_2 gesetzt, obwohl es keinen DOELSE-Fall gibt. Das ist auch erforderlich, ansonsten könnte das Modul nur ein einziges Mal schalten, da ohne do always das Modul nur nach Zustandswechsel wieder schaltet und mit nur einem Zustand cmd_1 wäre ein Zustandswechsel nicht möglich.

Gruß

Damian
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF