Klingel Rule (Regel) Optimierung

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Bernd99
Beiträge: 20
Registriert: 16. Feb 2018 22:01
Answers: 0

Klingel Rule (Regel) Optimierung

Beitrag von Bernd99 »

Hallöchen,

nach der doch recht schönen und langen Sommerpause habe ich mir mal neues Spielzeug bestellt und erweitere jetzt nach und nach mein System. Akzuell sind sehr viele Komponenten von Xiaomi schon Zuhause und noch im Zulauf. Einen Schalter habe ich mir jetzt als Klingel umfunktioniert und bräuchte vielleicht noch eins zwei Tipps.

Code: Alles auswählen

rule "Klingel von 08:00 bis 21:00 Uhr"
when
	Channel "mihome:sensor_switch_aq2:xxxx:button" triggered SHORT_PRESSED or
	Channel "mihome:sensor_switch_aq2:xxxx:button" triggered DOUBLE_PRESSED
then
	if (now.getHourOfDay() >= 08 && now.getHourOfDay() <= 20) {
	sendBroadcastNotification("Es klingelt!")
	sendLogNotification("Es klingelt!")
	sendCommand(GateU_SoundVolume, 10)
	sendCommand(GateU_SoundSelector, 10)
	//sendCommand(GateO_SoundVolume, 10)
	//sendCommand(GateO_SoundSelector, 10)
	Thread::sleep(2500)
	sendCommand(GateU_SoundVolume, 0)
	sendCommand(GateU_SoundSelector, 10000)
	} else {
		sendBroadcastNotification("Es klingelt außerhalb der Sprechzeiten!")
		sendLogNotification("Es klingelt außerhalb der Sprechzeiten!")
	}
end
Die Regel funktioniert für mich schon sehr gut.

Zu Erklärung falls jeman dieses Thread findet:

Von 08:00 bis 21:00 Uhr gibt das Gateway ein Klingelgeräusch ab beim Betätigen des Buttons.
Zusätzlich auch eine Push Nachricht auf mein Handy.
Nach 21 und vor 08 klingelt das Gateway nicht mehr sondern ich kriege nur eine Pushnachricht.
Zusätzlich werden die Pushnachrichten in der App gespeichert (sendLogNotification).


Meine Fragen dazu:

1. Wieso muss ich <=20 einstellen damit die Klingel bis 21 Uhr klingelt?
2. Wenn erneut der Button (also kurz danach) gedrückt wird unterbricht das erste Klingeln und es wird erneut ausgeführt. Ich dachte das Thread::sleep bedeutet, dass die Regel nicht sofort erneut ausgeführt wird.
3. Gibt es sonst noch Optimierungsmöglichkeiten?

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

Re: Klingel Rule (Regel) Optimierung

Beitrag von udo1toni »

Moin!

Zu Deinen Fragen:
1. Die Funktion heißt now.getHourOfDay() und liefert die Stunde des Tages. Die Uhrzeit kann von 0:00:00 bis 23:59:59 gehen. Somit liefert die Funktion um 20:59:59 eine 20 zurück, um 21:00:00 Uhr dann eine 21. Du könntest auch auf <21 testen, statt auf <=20. Sinngemäß gilt das gleiche für die andere Seite, Du könntest also für "Ab 8 Uhr" auch >7 abfragen. Eine etwas verschwurbelte Version wäre diese hier:

Code: Alles auswählen

val Integer hVon = 8
val Integer hBis = 21
if(now.minusHours(hVon).getHourOfDay < hBis-hVon) //klingeln
else //nicht klingeln
Um 8 Uhr wäre es vor 8 Stunden (minusHours(8)) 0 Uhr gewesen. Eine Sekunde vorher wäre es 23:59:59 Uhr gewesen.
Um 21 Uhr wäre es vor 8 Stunden (minusHours(8)) 13 Uhr gewesen. Eine Sekunde vorher wäre es 12:59:59 Uhr gewesen.
So kommt man mit nur einer Bedingung aus. :)
Prinzipiell gibt es einen Stolperstein, nämlich, wenn Sommer/Winterzeitumstellung stattfindet. Das spielt natürlich nur eine Rolle, wenn dieses Ereignis im Zeitfenster liegt, außerdem hat sich das ja spätestens im November 2019 erstmal erledigt.
Ansonsten kann man sich trefflich streiten, welche Version eleganter ist...

openHAB arbeitet komplett asynchron und multithreaded, das heißt in diesem Fall, wenn Du ein Thread::sleep() absetzt, schickst Du zwar den Thread schlafen, der die Rule ausführt, das hindert openHAB aber nicht daran, die Rule ein weiteres Mal zu starten, sobald sie wieder getriggert wird, die Rule läuft dann also n-mal (n = Anzahl erkannte Trigger, n < 6)
Die Einschränkung auf 5 Threads rührt daher, dass openHAB default 5 Threads zur Ausführung von Rules zur Verfügung stellt. Damit ist auch sofort klar, dass Thread::sleep() nur für kleine Verzögerungen (erfahrungsgemäß weniger als 500 Millisekunden) verwendet werden sollte, weil sonst die Gefahr steigt, dass Rules nicht ausgeführt werden, obwohl es ein Trigger Ereignis gab.

Und jetzt? Man kann das Problem elegant umschiffen, indem man einen Timer verwendet.

Code: Alles auswählen

var Timer tKlingel = null //Definition zu Beginn des Rule File, diese Variablen sind global gültig!

rule "Klingel von 08:00 bis 21:00 Uhr"
when
    Channel "mihome:sensor_switch_aq2:xxxx:button" triggered SHORT_PRESSED or
    Channel "mihome:sensor_switch_aq2:xxxx:button" triggered DOUBLE_PRESSED
then
    if (now.getHourOfDay > 7 && now.getHourOfDay < 21) { //zwischen 8 Uhr und 21  Uhr
        if(tKlingel === null) {                          // Timer läuft noch nicht?
            sendBroadcastNotification("Es klingelt!")
            sendLogNotification("Es klingelt!")
            GateU_SoundVolume.sendCommand(10)
            GateU_SoundSelector.sendCommand(10)
            tKlingel = createTimer(now.plusMillis(2500),[
                GateU_SoundVolume.sendCommand(0)
                GateU_SoundSelector.sendCommand(10000)
                tKlingel = null
            ])
        }
    } else {
        sendBroadcastNotification("Es klingelt außerhalb der Sprechzeiten!")
        sendLogNotification("Es klingelt außerhalb der Sprechzeiten!")
    }
end
Diese Rule sollte sich genauso verhalten wie Deine, mit dem Unterschied, dass der Klingelsound nicht neu gestartet wird (und auch keine weitere Notification erfolgt), falls innerhalb der 2,5 Sekunden erneut geklingelt wird. Nebenbei wird die Rule ohne weitere Verzögerung beendet, so schnell das geht. Nach 2,5 Sekunden endet der Timer und das übergebene Lambda (alles zwischen [ und ]) wird ausgeführt. Wichtig (da wir darauf testen) ist das Zurücksetzen der Variable am Schluss.
Je länger man pausieren möchte, desto wichtiger ist es, Timer zu verwenden.
Eine Alternative wäre ein lock-Mechanismus, aber das ist mit Vorsicht zu genießen :)

Wie Du im Code sehen kannst, habe ich die Methode Item.sendCommand(Value) statt der Action sendCommand(Item, Value) verwendet. Im vorliegenden Fall sollte es unerheblich sein, aber zum einen ist das besserer Stil, zum anderen gibt es Situationen (genau dann, wenn man Primitives übergibt), wo die Methode wunderbar funktioniert, die Action aber nicht mehr, denn die Action erwartet immer zwingend zwei Strings, während die Methode den Wert abhängig vom Itemtyp erwartet.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Bernd99
Beiträge: 20
Registriert: 16. Feb 2018 22:01
Answers: 0

Re: Klingel Rule (Regel) Optimierung

Beitrag von Bernd99 »

Vielen Dank für die ausführliche Erklärung. Habe den Code eingebaut und werde es heute Abend gleich probieren.

Alles ausprobiert, läuft vielen Dank nochmal.
Danke auch nochmal für die ausführliche Erklärung, als Laie sind es doch teilweise böhmische Wälder.

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

Re: Klingel Rule (Regel) Optimierung

Beitrag von udo1toni »

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

Antworten