[SOLVED]Alarm Rule - Bitte checken ob korrekt?

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Boris099
Beiträge: 383
Registriert: 19. Feb 2020 20:51
Answers: 3
Wohnort: Saarbrücken

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von Boris099 »

Nur noch was Kleines:-)

Also rule nun nochmal überarbeitet, wie empfohlen unter Verwendung von Gruppen und die If-Bedingungen einzeln.
Und das neue Mail Binding 2.5 (werde als nächstes noch Telgram aktivieren, ist irgendwie geschickter als Mail)

aber ich habe doch noch ein paar kleine Fragen:
1. Wieso nutzen wir denn nun:

Code: Alles auswählen

var lastRun = now.minutesMinutes(2)
ist hier wie vorher benutzt

Code: Alles auswählen

var lastRun = now
falsch?

2. Ich möchte erreichen, wenn Alarm Aktiv also AlarmAussen.state == ON mit Hilfe des triggeringItem.name ein Auslösen des jeweiligen
BW-Melders gesendet wird. Hierzu habe ich eine weiter If-Bedingung eingebaut. Ist die so korrekt und auch an der richtigen Stelle?

3. Woher weiß das Programm welches triggeringItem aus welcher Gruppe gemeint ist, da könnte doch im Code noch eine andere Gruppe
verwendet werden?

Code: Alles auswählen

import java.util.List
var List timers = newArrayList
var Timer shutoffTimer = null
var lastRun = now.minusMinutes(2)

rule "Sonbas Motion changed from OFF to ON 3 times in a minute"
	when
		Member of gBW changed from OFF to ON
	then
	if(AlarmAussen.state == ON) {
	val mailActions = getActions("mail","mail:smtp:c1a3d968")
    	mailActions.sendMail("xxx@gmail.com","Alarm "+ triggeringItem.name, "Bewegungsmelder " + triggeringItem.name.toString + " hat ausgelöst")
	}
	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;
    }
	if(timers.size < 3) {
		val t = createTimer(now.plusMinutes(1), [ | 
		timers.remove(0) ] )
		timers.add(t)
	}
	if(timers.size == 3) {
		val mailActions = getActions("mail","mail:smtp:c1a3d968")
		mailActions.sendMail("xxx@gmail.com","Sirene aktiviert ", "Sirene wurde aktiviert")
		Sirene_Gaeste.sendCommand(ON)
		lastRun = now
			while(timers.size > 0) {
			timers.get(0).cancel
			timers.remove(0)
		}
		shutoffTimer = createTimer(now.plusSeconds(10)) [|
			Sirene_Gaeste.sendCommand(OFF)
			logInfo("Alarmrule", "Sirene Ende")
			shutoffTimer = null
		]
	}
End
Raspberry 4, Rev.1.2b, 4GB, Openhab 2.5.12 (OH3 kommt im Winter dran:-))

Benutzeravatar
udo1toni
Beiträge: 15249
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von udo1toni »

Also, wegen lastRun = now... Allgemein sollte man nie einer globalen Variablen bei der Definition (also außerhalb der rules) einen dynamischen (also veränderlichen) Wert zuweisen. Sauber löst man das, indem man der Variablen 0 oder null zuweist und in einer Rule, die auf system started triggert, den korrekten Wert zuweist.
now ist auch suboptimal, da die Alarmierung dann frühestens 2 Minuten nach Start erfolgen kann. Deshalb now.minusMinutes(2)

Zu 2.: die Rule bricht ja bei OFF ab, warum packst Du die Mail nicht hinter die Abbruchbedingung, wo dann schon sichergestellt ist, dass der Alarm scharf ist?

Zu 3.: jede Rule wird IMMER von exakt einem Trigger ausgelöst, gleich, wie viele Trigger man angibt. Wenn für verschiedene Trigger verschiedenes Verhalten erwartet wird, sollte man über das Design der Rules Gedanken machen, aber grundsätzlich hat man ja die Information, welcher Trigger die Rule ausgelöst hat.
Gesendet von meinem SM-G973F mit Tapatalk



openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

bastler
Beiträge: 121
Registriert: 7. Jan 2020 19:36
Answers: 2

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von bastler »

... das beste ist du machst dir einfach statt der sirene zb. einfach ein licht an und probierst deine regel so aus, ich mach das auch immer so wenn ich eine regel testen wil.
Woher weiß das Programm welches triggeringItem aus welcher Gruppe gemeint ist
nun die regel triggert (also startet) nur wenn ein item von off nach on schaltet das auch der gruppe "gBW" zugeordnet wurde. wenn du wissen willst welches item das war kannst du das, wie ich schon eingearbeitet hatte, über die variable "triggeringItem.name" dir loggen oder mailen lassen

Boris099
Beiträge: 383
Registriert: 19. Feb 2020 20:51
Answers: 3
Wohnort: Saarbrücken

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von Boris099 »

Nochmal vielen Dank,

ja genau so mache ich das, ich replace zum Testen die Sirene mit einem Switch für eine Lampe und dann muß ich Draussen (bei diesem Sch..Wetter vorm Bewegungsmelder rumlaufen:-))
aber ich habe gerade das Telegram Binding aktiviert, der Bot funktioniert und den möchte ich jetzt auch nutzen ..., das finde ich echt cool!

und die Mail meinst du an dieser Stelle s.u.?
Aber ich möchte diese Nachrichten nur haben wenn die Alarmfunktion auch aktiviert ist.
und wird das dann trotzdem gesendet, auch wenn die rule abgebrochen wird?

Edit: Achso ich glaube ich habe es kapiert, ich breche ja nur ab wenn der state == OFF sonst geht es ja weiter weil state nicht OFF
aber trotzdem wo genau muß dann diese Mail hin, sorry das Programmieren ist nicht so ganz mein Metier:-)

Code: Alles auswählen

when
		Member of gBW changed from OFF to ON
	then
	if(AlarmAussen.state == OFF) {
        logInfo("bw_alarm","Alarmanlage aus, Rule Ende!")
        return;
        val mailActions = getActions("mail","mail:smtp:c1a3d968")
    	mailActions.sendMail("xxx@gmail.com","Alarm "+ triggeringItem.name, "Bewegungsmelder " + triggeringItem.name.toString + " hat ausgelöst")
    }
Raspberry 4, Rev.1.2b, 4GB, Openhab 2.5.12 (OH3 kommt im Winter dran:-))

bastler
Beiträge: 121
Registriert: 7. Jan 2020 19:36
Answers: 2

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von bastler »

... ich bin (leider) auch kein programmierer, ich probier halt viel rum. zb wegen dem bewegunsmelder draußen: hast du keinen im haus? ich würde den dann zum testen in die gruppe dazu nehmen, dann brauchst du nicht dauernd raus. ich such mir zum probieren immer was in der nähe vom rechner, und wenn es nur einfach ein extra dafür angelegter schalter ist der sonst keine funktion hat als zum testen einer regel.

wenn ich das richtig sehe wirst du so jedes mal ne email bekommen wenn die alarmanlage an ist und jemand durch den bewegungsmelder läuft. also auch wenn die 3 innerhalb der einen minute noch nicht erreicht sind und kein alarm ausgelöst wird

Benutzeravatar
udo1toni
Beiträge: 15249
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von udo1toni »

Eigentlich ist es ganz einfach ;)

Man sollte aber der besseren Lesbarkeit wegen die Formatierung der Rule korrekt gestalten. Einrückungen in der Rule sind nur für das menschliche Auge relevant, aber dann wird vieles gleich klarer.
Hier mal die komplette Rule mit ausführlicher Dokumentation (Tipp: alles auswählen, kopieren und in einen externen Editor kopieren):

Code: Alles auswählen

import java.util.List                                                                       // Notwendiger Import
var List<Timer> timers = newArrayList                                                       // globale gültige Liste
var Timer shutoffTimer = null                                                               // global gültiges Timer Objekt
var lastRun = 0                                                                             // global gültige Variable für den Zeitstempel

rule "Rule Datei eingelesen"
when
    System started
then
    lastRun = now.minusMinutes(2)
end

rule "Motion detected 3 times in a minute"
when
    Member of gBW changed from OFF to ON
then
    // hier kommt hin, was auf jeden Fall passieren soll, wenn die Rule triggert
    if(AlarmAussen.state == OFF) {                                                          // Anfang Alarm unscharf-Block
        logInfo("bw_alarm","Alarmanlage aus, Rule Ende!")                                   // kurze Meldung
        return;                                                                             // und Ende der Rule
    }                                                                                       // Ende Alarm unscharf-Block
    // hier kommt hin, was auf jeden Fall passieren soll, wenn der Alarm scharf ist
    val mailActions = getActions("mail","mail:smtp:c1a3d968")                               // MailAction Objekt anlegen
    val mailText = "Bewegungsmelder " + triggeringItem.name + " hat ausgelöst"              // MailBody erzeugen
    mailActions.sendMail("xxx@gmail.com","Alarm "+ triggeringItem.name, mailText)           // Mail verschicken
    if(shutoffTimer !== null) {                                                             // Anfang schuttoffTimer existiert
        logInfo("bw_alarm","Alarm schon aktiv, Rule Ende!")                                 // Meldung ausgeben
        return;                                                                             // und Rule Ende
    }                                                                                       // Ende schuttoffTimer existiert
    // hier kommt hin, was nur passieren soll, wenn der Alarm scharf und gerade nicht aktiv ist
    if(lastRun.isAfter(now.minusMinutes(2))) {                                              // Anfang letzter Alarm vor weniger als 2 Minuten
        logInfo("bw_alarm","letzter Alarm vor weniger als 2 Minuten, Rule Ende!")           // Meldung ausgeben
        return;                                                                             // und Rule Ende
    }                                                                                       // Ende letzter Alarm vor weniger als 2 Minuten
    // hier kommt alles hin, was nur passieren soll, wenn der letzte Alarm schon 2 Minuten her ist
    if(timers.size < 3) {                                                                   // Angang weniger als 3 Timer laufen
        val t = createTimer(now.plusMinutes(1), [ |                                         // Timer anlegen
            timers.remove(0)                                                                // Bei Ablauf des Timers, den ältesten Timer von der Liste entfernen
        ] )                                                                                 // Ende Timer
        timers.add(t)                                                                       // Den gerade erzeugten Timer der Liste hinzufügen
    }                                                                                       // Ende weniger als 3 Timer laufen
    if(timers.size == 3) {                                                                  // Anfang Liste umfasst 3 Timer
/*    
    val mailActions = getActions("mail","mail:smtp:c1a3d968") ist ier nicht nötig, da die Action schon oben definiert wurde
*/
        mailActions.sendMail("xxx@gmail.com","Sirene aktiviert ", "Sirene wurde aktiviert") // Alarmmail ausgeben
        Sirene_Gaeste.sendCommand(ON)                                                       // Sirene aktivieren
        lastRun = now                                                                       // Zeitstempel für letzten Alarm setzen
        while(timers.size > 0) {                                                            // Solange die Liste Elemente enthält
            timers.get(0).cancel                                                            // den ältesten Timer canceln
            timers.remove(0)                                                                // und von der Liste entfernen
        }
        shutoffTimer = createTimer(now.plusSeconds(10), [ |                                 // Timer zum Abschalten des Alarms anlegen
            Sirene_Gaeste.sendCommand(OFF)                                                  // Bei Ablauf Sirene aus
            logInfo("Alarmrule", "Sirene Ende")                                             // Meldung ausgeben
            shutoffTimer = null                                                             // und Timer löschen
        ] )                                                                                 // Ende Timer
    }                                                                                       // Ende Liste umfasst 3 Timer
end
Man beachte die subtilen Änderungen ;) z.B. die konsisstente Definition der beiden Timer. Klammern dienen allgemein zum bilden von Blöcken. Dabei enthalten einfache () Klammern Parameter für die voranstehende Action oder Methode, Eckige [] Klammern kennzeichnen ein Lambda und geschweifte {} Klammern bilden einen logischen Block, der quasi als ein Befehl betrachtet wird. Letzteres ist wichtig, weil z.B. if() genau einen Befehl überspringt, falls die Bedingung nicht erfüllt ist. Mit den {} kann man also dafür sorgen, dass die bedingte Verzweigung für mehrere Befehle gilt.
Lambdas (das in den eckigen Klammern) sind Code, der z.B. in einem Objekt gespeichert, oder als Parameter verwendet wird (z.B. bei der Definition eines Timers).

Durch die Einrückungen wird klar, welche Codeblöcke auf der gleichen Ebene laufen.
Es gibt weitere Regeln, z.B. ist der Gültigkeitsbereich von Variablen und Konstanten auf die Ebene (und die darunter liegenden Ebenen) begrenzt, in der sie definiert sind.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Boris099
Beiträge: 383
Registriert: 19. Feb 2020 20:51
Answers: 3
Wohnort: Saarbrücken

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von Boris099 »

das ist definitiv nicht so einfach wie es aussieht :geek: :-)

ich habe das nun 1:1 übernommen incl. Kommentaren damit ich in 1 Stunde noch weis um was es geht :lol:
BTW: er hat nochmal gemeckert das End muß wohl end sein (das ist aber auch erst seit 2.5 so)

Bzgl. der Mail Funktion:
Einmal hast du mit val mailText separat einen Betreff und den Mailtext definiert, das wird dann hinter dem 2.Komma ohne ""
beim .sendmail verwendet. Also das ist dann nur der Mailtext.
Im anderen Beispiel wird einfach hinter dem 2.Komma in "" der Mailtext direkt mitgegeben, korrekt verstanden?

Code: Alles auswählen

    val mailActions = getActions("mail","mail:smtp:c1a3d968")                               		// MailAction Objekt anlegen
    val mailText = "Bewegungsmelder " + triggeringItem.name + " hat ausgelöst"              	// MailBody erzeugen
    mailActions.sendMail("xxx@gmail.com","Alarm "+ triggeringItem.name, 	mailText)        	// Mail verschicken
  
    mailActions.sendMail("xxx@gmail.com","Sirene aktiviert ",			 "Sirene wurde aktiviert") 
Raspberry 4, Rev.1.2b, 4GB, Openhab 2.5.12 (OH3 kommt im Winter dran:-))

bastler
Beiträge: 121
Registriert: 7. Jan 2020 19:36
Answers: 2

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von bastler »

der text hinter dem 1. komma (also inter "xxx@gmail.com",) ist immer der betreff, im oberen sendmail also dann "Alarm " und im unteren ist es "Sirene aktiviert"

der text hinter dem 2. komma ist immer der mailtext, im oberen sendmail wurde da die variable "mailText" verwendet weil die in der zeile drüber aus mehreren teilen zusammengesetzt wurde. im unteren sendmail ist es ein statischer text "Sirene wurde aktiviert"

Benutzeravatar
udo1toni
Beiträge: 15249
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von udo1toni »

Genau. :) Letztlich habe ich die Zeile oben in eine Konstante ausgelagert, damit die Zeile nicht so lang wird...

Das End am Ende beweist, dass auch kleine Fehler zu Problemen führen können, und auch den Besten (dabei meine ich ausdrücklich nicht mich!) Flüchtigkeitsfehler passieren... ;)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Boris099
Beiträge: 383
Registriert: 19. Feb 2020 20:51
Answers: 3
Wohnort: Saarbrücken

Re: Alarm Rule - Bitte checken ob korrekt?

Beitrag von Boris099 »

Hallo,
ich bin nun etwas mutig und packe noch ein paar Kleinigkeiten in das rule, könnt ihr bitte da nochmal drauf schauen,
das ist bestimmt noch nicht korrekt so. Das ist nun wirklich knifflig und nur was für Insider :idea:

(Ich bekomme das mit dem Kopieren des Codes nicht ordentlich hin, sieht leider alles etwas schräg aus :lol: )

Ich möchte folgendes erreichen:
1. Die Mai Infos werden nur gesendet wenn der neu aufgesetzte Dummy Switch "InfoSenden" auf ON steht.
2. Ich schalte mit 2 zusätzlichen Timer einen LED Strahler
a. Immer wenn Alarm an und ein Bewegungsmelder triggert -> hier nur für 2 Sekunden
b. wenn der Alarm echt aktiv wird -> Kann man diesen Timer mehrfach wiederholen? z.B. 3Sek an dann 3Sek aus, evtl. solange bis Alarmzeit ausläuft, und das wären dann mehrere LED Strahler, also nicht nur dieser eine im Beispiel, die das Alarmsignal abwechselnd auch optisch begleiten.

Insbesondere diese neuen shutoffTimer, die ich da eingebaut haben, gehen die an diesen Positionen,
und stören die nicht den eigentlichen Alarmtimer?

Code: Alles auswählen

import java.util.List                                                                       // Notwendiger Import
var List<Timer> timers = newArrayList                                                       // globale gültige Liste
var Timer shutoffTimer = null                                                               // global gültiges Timer Objekt
var lastRun = 0                                                                             // global gültige Variable für den Zeitstempel

rule "Rule Datei eingelesen"
when
    System started
then
    lastRun = now.minusMinutes(2)
end

rule "Motion detected 3 times in a minute"
when
    Member of gBW changed from OFF to ON
then
    // hier kommt hin, was auf jeden Fall passieren soll, wenn die Rule triggert
    if(AlarmAussen.state == OFF) {                                                          // Anfang Alarm unscharf-Block
        logInfo("bw_alarm","Alarmanlage aus, Rule Ende!")                                   // kurze Meldung
        return;                                                                             // und Ende der Rule
    }                                                                                       // Ende Alarm unscharf-Block
    // hier kommt hin, was auf jeden Fall passieren soll, wenn der Alarm scharf ist
		LED_GaesteV.sendCommand(ON)															// Wenn ein Bewegungsmelder auslöst schaltet dieser LED Strahler ein
		shutoffTimer = createTimer(now.plusSeconds(2), [ |                                 	// Timer zum Abschalten des LED Strahler anlegen
		LED_GaesteV.sendCommand(OFF)                                                  		// Bei Ablauf LED Strahler nach 2 Sekunden aus
            shutoffTimer = null                                                             // und Timer löschen
        ] )                    																// Ende Timer
	if(InfoSenden.state == ON) {															// Abfrage ob Switch InfoSenden aktiv
	val mailActions = getActions("mail","mail:smtp:c1a3d968")                               // MailAction Objekt anlegen
    val mailText = "Bewegungsmelder " + triggeringItem.name + " hat ausgelöst"              // MailBody erzeugen
    mailActions.sendMail("xxx@gmail.com","Alarm "+ triggeringItem.name, mailText)           // Mail verschicken
	}																						// Ende Mail nur senden wenn item InfoSenden aktiv
    if(shutoffTimer !== null) {                                                             // Anfang shuttoffTimer existiert
        logInfo("bw_alarm","Alarm schon aktiv, Rule Ende!")                                 // Meldung ausgeben
        return;                                                                             // und Rule Ende
    }                                                                                       // Ende shuttoffTimer existiert
    // hier kommt hin, was nur passieren soll, wenn der Alarm scharf und gerade nicht aktiv ist
    if(lastRun.isAfter(now.minusMinutes(2))) {                                              // Anfang letzter Alarm vor weniger als 2 Minuten
        logInfo("bw_alarm","letzter Alarm vor weniger als 2 Minuten, Rule Ende!")           // Meldung ausgeben
        return;                                                                             // und Rule Ende
    }                                                                                       // Ende letzter Alarm vor weniger als 2 Minuten
    // hier kommt alles hin, was nur passieren soll, wenn der letzte Alarm schon 2 Minuten her ist
    if(timers.size < 3) {                                                                   // Angang weniger als 3 Timer laufen
        val t = createTimer(now.plusMinutes(1), [ |                                         // Timer anlegen
            timers.remove(0)                                                                // Bei Ablauf des Timers, den ältesten Timer von der Liste entfernen
        ] )                                                                                 // Ende Timer
        timers.add(t)                                                                       // Den gerade erzeugten Timer der Liste hinzufügen
    }                                                                                       // Ende weniger als 3 Timer laufen
    if(timers.size == 3) {                                                                  // Anfang Liste umfasst 3 Timer
/*    
    val mailActions = getActions("mail","mail:smtp:c1a3d968") ist ier nicht nötig, da die Action schon oben definiert wurde
*/
	if(InfoSenden.state == ON) {											// Abfrage ob Switch InfoSenden aktiv
        mailActions.sendMail("xxx@gmail.com","Sirene aktiviert ", "Sirene wurde aktiviert") 	// Alarmmail ausgeben
	}																// Ende Mail nur senden wenn item InfoSenden aktiv
        Sirene_Gaeste.sendCommand(ON)                                                       			// Sirene aktivieren
		LED_GaesteV.sendCommand(ON)									// LED Strahler ein
		Wiederholen  shutoffTimer = createTimer(now.plusSeconds(3), [ |                      // Timer zum Abschalten des LED Strahler anlegen
		LED_GaesteV.sendCommand(OFF)                                                  			// Bei Ablauf LED Strahler nach 3 Sekunden aus
            shutoffTimer = null                                                             					// und Timer löschen
        ] )                    														// Ende Timer
        lastRun = now                                                                       // Zeitstempel für letzten Alarm setzen
        while(timers.size > 0) {                                                            // Solange die Liste Elemente enthält
            timers.get(0).cancel                                                            // den ältesten Timer canceln
            timers.remove(0)                                                                // und von der Liste entfernen
        }
        shutoffTimer = createTimer(now.plusSeconds(30), [ |                                 // Timer zum Abschalten des Alarms anlegen
            Sirene_Gaeste.sendCommand(OFF)                                                  // Bei Ablauf Sirene aus
            logInfo("Alarmrule", "Sirene Ende")                                             // Meldung ausgeben
            shutoffTimer = null                                                             // und Timer löschen
        ] )                                                                                 // Ende Timer
    }                                                                                       // Ende Liste umfasst 3 Timer
end
Ich habe den Code an diesen beiden Stellen geändert:
Anmerkung 2020-02-27 183018.gif
Anmerkung 2020-02-27.gif
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Raspberry 4, Rev.1.2b, 4GB, Openhab 2.5.12 (OH3 kommt im Winter dran:-))

Antworten