Seite 1 von 8

[SOLVED]Alarm Rule - Bitte checken ob korrekt?

Verfasst: 19. Feb 2020 21:20
von Boris099
Ich habe hier ein rule für eine Alarmanlage, welche aus 7 Sensoren und einer Sirene besteht.
Die rule soll bei dreimaliger Aktivierung innerhalb einer Minute (egal welcher Sensor) die Sirene aktivieren.
Das rule wurde mit Unterstützung des englischen Openhab Forums zusammengebaut, das ist auf Englisch aber alles so mühselig:-) Das wurde mit Openhab 2.1 erstellt und ich möchte bevor ich es nun aktiviere nochmal von euch checken lassen, ob das so OK ist, oder ob ihr da evtl. noch Verbesserungen seht, oder ....

Ich bin Anfänger und bin erst mal stolz das dieses Ding überhaupt läuft, obwohl ich bei weitem nicht
jedem Befehl folgen kann.
Benötigt man denn wirklich diese Befehle wie var List timers .. und import java.util.List?

Ich habe auch den Umstand, wenn eingeschaltet, braucht es warum auch immer 4 Aktivierungen,
danach nur 3 zum Auslösen der Sirene, ist nicht weiter schlimm aber irgendwie eigenartig, kann man das ändern?

Der Befehl AlarmAussen.state == OFF (Das ist ein Dummy Switch den ich definiert habe, um die Alarmanlage scharf zu schalten) bedeutet doch wenn der Status OFF ist, müsste das denn nicht genau andersrum abgefragt werden?

Und was macht eigentlich lastRun.isAfter(now.minusMinutes(2))) return;?

und Vielen Dank im Voraus

Code: Alles auswählen

import java.util.List
var List timers = newArrayList
var Timer shutoffTimer = null
var lastRun = now

rule "Sonbas Motion changed from OFF to ON 3 times in a minute"
	when
		Item BW_Kueche changed from OFF to ON or
		Item BW_Schwimmbad changed from OFF to ON or
		Item BW_Tobias changed from OFF to ON or
		Item BW_Nachbar changed from OFF to ON or
		Item BW_Wohnzimmer changed from OFF to ON or
		Item BW_Eingang changed from OFF to ON or
		Item BW_Wintergarten changed from OFF to ON
	then
		if(shutoffTimer !== null || AlarmAussen.state == OFF || lastRun.isAfter(now.minusMinutes(2))) return;
		if(timers.size < 3) {
			val t = createTimer(now.plusMinutes(1), [ | timers.remove(t) ] )
			timers.add(t)
}
		if(timers.size == 3) {
			sendMail("xxx@gmail.com", "Sonbas", "Sonbas Motion")
			Sirene_Gaeste.sendCommand(ON)
			lastRun = now
			logInfo("RuleInfo", "Siren START")
         timers.clear()
			shutoffTimer = createTimer(now.plusSeconds(10)) [ |
			Sirene_Gaeste.sendCommand(OFF)
			logInfo("RuleInfo", "Siren STOP")
			shutoffTimer = null ]
}
end

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 19. Feb 2020 22:29
von bastler
hi,
habs mal kurz ausprobiert, nette funktion, gefällt mir. das "lastrun" heißt dass nach dem letzten alarm mindestens zwei minuten vergehen müssen vor wieder neu gezählt wird und alarm ausgelöst werden kann. bedingt dadurch aber auch dass beim programmstart erst mal zwei minuten vergehen müssen vor wieder bewegungen registriert werden.
wenn du das drin hast kannst ud in der if-abfrage den eintrag mit dem shutofftimer sparen, weil der ja schon 10sek nach alarmauslösung wieder aus geht, der lastrun mit zwei minuten nach alarm also immer länger ist.
das einzige was mir visualstudio angemeckert hat ist

Code: Alles auswählen

var List<String> timers = newArrayList
und hier

Code: Alles auswählen

val t = createTimer(now.plusMinutes(1), [ | timers.remove(t.toString) ] )
timers.add(t.toString)
dein problem mit den 4 aktivierungen konnte ich hier nicht nachvollziehen

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 20. Feb 2020 11:57
von Boris099
Hi,
Also grundsätzlich in Ordnung, schon mal gut.
Mit der if-Bedingung für den shutofftimer ist die aber wieder notwendig wenn der Alarm länger als 10s ist?
Ich habe nur zum Testen die Alarmdauer mal auf 10s gesetzt, normal sind das ja eher 3min oder so.

Ich kann mit den Fehlern die Visualstudio angemeckert hat nicht wirklich was anfangen, was soll ich denn da korrigieren, kannst Du mir da helfen?

Muss diese If-Bedingung sinnvollerweise nicht ON anstatt OFF lauten AlarmAussen.state == OFF?

Wenn ich nun 4 anstatt 3 Alarmaktivierungen einstellen möchte, dann muß ich auch beide Male die 3 in 4 ändern, korrekt?

Und eines noch, mit dieser Regel sende ich eine Mail sobald 3 Aktivierungen stattgefunden haben, kann ich es auch einfach hinbekommen das jeder Melder einzel eine Aktivierung mailt? z.B. sendMail hinter jeder Melderabfrage?

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 20. Feb 2020 13:33
von udo1toni
Ich hab hier mal inline ein paar Infos dazu gepackt.:

Code: Alles auswählen

import java.util.List                                                                               // Listen verfügbar machen

var List timers = newArrayList                                                                      // neue globale Liste anlegen
var Timer shutoffTimer = null                                                                       // globalen Timer definieren
var lastRun = now                                                                                   // globale Variable, zu Beginn auf den aktuellen Zeitstempel gesetzt

rule "Sonbas Motion changed from OFF to ON 3 times in a minute"
when
    Item BW_Kueche changed from OFF to ON or
    Item BW_Schwimmbad changed from OFF to ON or
    Item BW_Tobias changed from OFF to ON or
    Item BW_Nachbar changed from OFF to ON or
    Item BW_Wohnzimmer changed from OFF to ON or
    Item BW_Eingang changed from OFF to ON or
    Item BW_Wintergarten changed from OFF to ON
then
    if(shutoffTimer !== null || AlarmAussen.state == OFF || lastRun.isAfter(now.minusMinutes(2)))   // ShutoffTimer läuft oder kein Außenalarm oder letzter Alarm nicht länger als 2 Minuten her
        return;                                                                                     // Rule abbrechen
    if(timers.size < 3) {                                                                           // Falls weniger als 3 Timer in der Liste
        val t = createTimer(now.plusMinutes(1), [ |                                                 // Timer anlegen
            timers.remove(t)                                                                        // Wenn Timer abläuft, Timer von der Liste entfernen
        ] )
        timers.add(t)                                                                               // Timer zur Liste hinzufügen
    }
    if(timers.size == 3) {                                                                          // Falls Anzahl Timer = 3
        sendMail("xxx@gmail.com", "Sonbas", "Sonbas Motion")
        Sirene_Gaeste.sendCommand(ON)                                                               // Sirene anschalten
        lastRun = now                                                                               // Zeitstempel für Alarm setzen
        logInfo("RuleInfo", "Siren START")
        timers.clear()                                                                              // Alle Timer löschen
        shutoffTimer = createTimer(now.plusSeconds(10), [ |                                         // nach 10 Sekunden
            Sirene_Gaeste.sendCommand(OFF)                                                          // Sirene abschalten
            logInfo("RuleInfo", "Siren STOP")
            shutoffTimer = null                                                                     // Timer löschen
        ] )
    }
end
AlarmAussen ist der Schalter, mit dem die Alarmanlage deaktiviert wird. Solange AlarmAussen auf OFF steht, wird es keine Meldung geben, da die Rule sofort beendet wird.
shutoffTimer setzt den Alarm zurück. Dieser Timer wird nur gestartet, falls der Alarm ausgelöst wurde. Wenn der Timer aktiv ist, ist auch der Alarm aktiv und die Rule wird abgebrochen
lastRun enthält den Zeitstempel des letzten Alarms. Ist der letzte Alarm weniger als 2 Minuten her, wird die Rule abgebrochen.
timers ist eine Array Liste. In dieser werden Timer gespeichert (mittels timers.add(Timer)) und wieder entfernt (mittels timers.remove(Timer)). An dieser Stelle bin ich mir nicht sicher, ob das tatsächlich so funktioniert, da t innerhalb des Lambdas eigentlich gar nicht referenzierbar sein dürfte, aber vielleicht ist das die große Ausnahme der Regel...
Da timers eine Liste ist, kann man mittels timers.size bestimmen, wie viele Einträge (Timer) die Liste enthält.
Wenn weniger als 3 Einträge vorhanden sind, wird ein neuer Eintrag angelegt.
Wenn 3 Einträge vorhanden sind, wird Alarm ausgelöst, die Liste der Timer gelöscht und ein Timer zum stoppen des Alarms angelegt.
Der nächste Knackpunkt: mit timers.clear() wird zwar die Liste geleert, die Timer existieren aber weiterhin. Wenn die Timer ablaufen, versuchen sie, sich selbst von der Liste zu löschen, die aber schon geleert wurde. Ich möchte es nicht beschwören, könnte mir aber vorstellen, dass es da Fehler gibt.

Optimirungspotential:
1. Definiere eine Gruppe, in der die Bewegungsmelder zusammengefasst sind, welche als Alarmtrigger dienen sollen, z.B. gBW_Alarm. Dann reicht ein Trigger:

Code: Alles auswählen

Member of gBW_Alarm changed from OFF to ON
2. Teile das erste if() auf:

Code: Alles auswählen

    if(AlarmAussen.state == OFF) {
        logInfo("bw_alarm","Alarmanlage aus, Rule Ende!")
        return;
    }
    if(shutoffTimer !== null) {
        logInfo("bw_alarm","Alarm schon aktiv, Rule Ende!")
        return;
    }
    if(lastRun.isAfter(now.minusMinutes(2))) {
        logInfo("bw_alarm","letzter Alarm vor weniger als 2 Minuten, Rule Ende!")
        return;
    }
Damit hast Du dann im Log direkt eine Information, wawrum die Rule abgebrochen wurde.

Wie gesagt bin ich nicht sicher, ob das Timerlistenkonstrukt so funktioniert, aber man könnte es etwas anders gestaltet schon so beibehalten.

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 20. Feb 2020 18:21
von bastler
da t innerhalb des Lambdas eigentlich gar nicht referenzierbar sein dürfte
vollkommen richtig udo, das hatte ich beim probieren übersehen, das wird auch von visual studio angemeckert.
mit timers.clear() wird zwar die Liste geleert, die Timer existieren aber weiterhin
hast du auch recht, wenn die timer ablaufen kommen fehler im log, nicht so schön.

ich denk mir inzwischen schon gar nichts mehr dabei, hab ganz viele warnings von vsc seit einer neuen version zu lauter variablen die nur in der rule (also nicht global) definiert sind, dann aber innerhalb eines lambda verwendet werden. hab da mal versucht zu recherchieren aber nur eine info gefunden wo es so ähnlich hieß: es sind ja nur warnings, denk dir nichts dabei. ich wollte nicht so viele globale variablen definineren aber wenn du jetzt auch meinst das ist nicht ganz richtig werd ich mich doch mal dran machen und die alle umdefinieren. danke für die info!

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 20. Feb 2020 20:54
von udo1toni
Das Problem ist, es reicht hier nicht, die Variable t global zu definieren, denn sie ist ja nur für den einen Timer zuständig. Ich bin mir, wie gesagt, nicht sicher, ob die Referenzierung an dieser Stelle trotzdem funktioniert - da müsste man halt schauen, ob die Rule das tut, was sie soll. Wenn man die Rule dreimal innerhalb einer Minute triggert, wird ein Alarm ausgelöst, das dürfte auf jeden Fall funktionieren. Was passiert aber, wenn man alle 2 Minuten einmal triggert? Wird dann evtl. nach dem dritten Trigger doch ein Alarm gemeldet?
Das elegante am gezeigten Ansatz: wenn es funktioniert, wird für jedes Ereignis ein eigener Timer gestartet und automatisch auch wieder von der Liste entfernt. Falls die Referenzierung hier aber scheitert, werden die Timer nicht mehr von der Liste entfernt.
Man könnte stattdess eine Liste mit Zeitstempeln führen und beim Anlegen von Einträgen gleich prüfen, ob Einträge älter als eine Minute sind und diese gegebenenfalls entfernen. Das ist aber jedenfalls nicht trivial.

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 21. Feb 2020 10:46
von Boris099
Hallo ihr beiden, zuerst mal vielen Dank für euren Input - jetzt brauch ich erst mal etwas Zeit zur Analyse:-)
Super das ich nun auch mal kommentiert sehe was die einzelnen Befehle auslösen.

Ich hatte schon mit einem Melder "rumgespielt" und denke das hat auch funktioniert wenn ich 2 Minuten gewartet hatte vor dem nächsten triggern. Nun möchte ich das halt live schalten mit den 7 Meldern und die Sirene in echt:-) deshalb nochmal mit den Spezialisten abklären.
Hatte etlichen Aufwand mit der Hardware-Installation und die Tasmotas stabil im DHCP versorgt zu bekommen, usw....
nun ist das aber alles stabil und der Schritt in die Praxis soll bald erfolgen.

Melde mich sicher gleich zurück

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 21. Feb 2020 11:24
von Boris099
Also,
mit dem globalen t in Lambda kann ich leider nix anfangen:-)
aber kann ich denn irgendwie anzeigen, ob die Timer wieder sauber entfernt wurden, läuft da die Liste über, oder ist das egal?
Ich kann und werde das natürlich in Live nochmal checken, ob da ein Fehler aufkommt, wenn ich z.B. 3mal alle 3min einen Alarm auslöse, denn das wäre echt doof, denke aber ich hatte sowas schon mal gecheckt.

Kann ich mit sendMail("xxx@gmail.com", "Sonbas", "Sonbas Motion") direkt hinter den when Abfragen
bei jedem einzelnen Melder eine Mail lossenden, oder muß da immer noch ein then hin, oder wie sieht das coding dann aus?
Oder gibt es was geschickteres z.B. über ein Push via die OpenHab app, oder...
when
Item BW_Kueche changed from OFF to ON
sendMail("xxx@gmail.com", "BW_Kueche", "BW_Kueche_Motion") or
Item BW_Schwimmbad changed from OFF to ON
sendMail("xxx@gmail.com", "BW_Schwimmbad", "BW_Schwimmbad_Motion") or

Achso und eigentlich wollte ich noch von 2.4 stable (mqtt devices sind wegen 2.4 somit schon alle wieder neu aufgesetzt) auf 2.5 upgraden. Habe das noch nicht gemacht weil es da wohl ein paar Probleme gab (Zwave) und bin immer noch verunsichert wie und ob ich das nun einfach tun soll. Einfach über openhabconfig oder wie?
Ich habe noch ein paar Zwave devices (die Sirene hängt auch einem Zwave Switch)

Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 21. Feb 2020 11:42
von udo1toni
OpenHAB2.5 ist das aktuelle stabile Release, es gab ein paar kleinere Bugfixes, grundsätzlich sollte das besser laufen als die 2.4.
Wenn Du openHABian verwendest, sollte ein Update aus openhabian-config heraus ausreichen.

Nun zu den Rules:

Eine Rule besteht aus zwei Teilen, dem when-Teil und dem then-Teil.
Der when-Teil beinhaltet ausschließlich Trigger (deshalb gibt es auch kein and, obwohl es doch ein or gibt)
Der then-Teil beinhaltet den auszuführenden Code, wenn einer der Trigger die Rule auslöst.
Ich habe es ja oben schon geschrieben, packe alle auslösenden Items in eine Gruppe und lass auf die Member der Gruppe triggern.
Innerhalb des then-Teils reicht dann eine Zeile zu Beginn, um eine Nachricht zu verschicken, auf welche Weise es Dir am liebsten ist. Mit triggeringItem.name steht auch die Information zur Verfügung, wer die Rule ausgelöst hat.


Gesendet von meinem SM-G973F mit Tapatalk


Re: Alarm Rule - Bitte checken ob korrekt?

Verfasst: 21. Feb 2020 12:02
von bastler
Mit triggeringItem.name steht auch die Information zur Verfügung, wer die Rule ausgelöst hat.
das sieht dann praktisch so aus:

Code: Alles auswählen

mailActions.sendMail("xxx@gmail.com","Alarm "+ triggeringItem.name, "Bewegungsmelder " + triggeringItem.name.toString + " hat angeschlagen")
... bin nur nicht sicher ob ".toString" dazu muß oder nicht, habs hier mal mit und mal ohne - scheint beides zu funktionieren

ABER:
Was passiert aber, wenn man alle 2 Minuten einmal triggert?
udo1toni hat auch hier recht: ich habs gerade probiert, die sirene geht tatsächlich auch dann los wenn man immer 2minuten wartet, schade also aber dann funktioniert das ganze so leider doch nicht!