Hallo Gemeinde,
Ich könnte mal eure Unterstützung gebrauchen. Ich habe mir einen schönen Slider gebaut, um zu visualisieren, wie lange der Timer noch zu laufen hat. Soweit so gut, allerdings schaffe ich es nicht, den Countdown zu killen, damit er wieder neu startet. Mit der aktuellen Rule setz er den Count zwar kurzzeitig wieder auf 60, zählt aber von der letzten Stelle weiter runter. Ich möchte aber, wenn der Sprengler1 erneut ON schaltet, die Zeit wieder hochgesetzt wird.
rule "Bewässerung Vorgarten"
when
Item Sprengler1 changed to ON
then
val Integer TIMER_TIME = (Sprengler3.state as DecimalType).intValue
var count = TIMER_TIME
while(count >= 0) {
Sprengler3.postUpdate(count)
count = count - 1
Thread::sleep(1000)
}
end
Rule Countdown mit Möglichkeit zum Killen
-
- Beiträge: 5
- Registriert: 5. Sep 2020 10:43
-
- Beiträge: 167
- Registriert: 1. Jun 2020 17:29
Re: Rule Countdown mit Möglichkeit zum Killen
Ich würde mit createTimer und den Timer dann ggf. Canceln wenn es gewünscht ist. Evtl. Braucht man dazu noch eine Variable dazu wird dir udo oder jemand anderes sicherlich weiterhelfen können. Da bei sleep die Regel nur pausiert hat man darüber meines Wissens keine Chance.bananajoe86 hat geschrieben:Hallo Gemeinde,
Ich könnte mal eure Unterstützung gebrauchen. Ich habe mir einen schönen Slider gebaut, um zu visualisieren, wie lange der Timer noch zu laufen hat. Soweit so gut, allerdings schaffe ich es nicht, den Countdown zu killen, damit er wieder neu startet. Mit der aktuellen Rule setz er den Count zwar kurzzeitig wieder auf 60, zählt aber von der letzten Stelle weiter runter. Ich möchte aber, wenn der Sprengler1 erneut ON schaltet, die Zeit wieder hochgesetzt wird.
rule "Bewässerung Vorgarten"
when
Item Sprengler1 changed to ON
then
val Integer TIMER_TIME = (Sprengler3.state as DecimalType).intValue
var count = TIMER_TIME
while(count >= 0) {
Sprengler3.postUpdate(count)
count = count - 1
Thread::sleep(1000)
}
end
Gesendet von meinem SM-G981B mit Tapatalk
- udo1toni
- Beiträge: 15248
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Rule Countdown mit Möglichkeit zum Killen
Also, die Idee ist gaaanz schlecht.bananajoe86 hat geschrieben: ↑29. Sep 2020 20:04 Ich könnte mal eure Unterstützung gebrauchen. Ich habe mir einen schönen Slider gebaut, um zu visualisieren, wie lange der Timer noch zu laufen hat. [...]

openHAB arbeitet ereignisorientiert. Eine Rule sollte im schlimmsten Fall unter eine Sekunde laufen, im besten Fall innerhalb weniger Millisekunden.
Ein Thread::sleep() hält den Thread einfach für die gewählte Zeit an, er steht nicht zur Verarbeitung anderer Rules zur Verfügung.
Besser:
Code: Alles auswählen
var Timer tWater = null // globale Variablen vor der ersten Rule einfügen
var Integer iWater = 61
rule "Bewässerung Vorgarten"
when
Item Sprengler1 changed to ON
then
tWater?.cancel // falls noch ein Timer läuft, abbrechen
iWater = 61 // Zähler zurücksetzen
tWater = createTimer(now, [| // Timer anlegen und sofort ausführen
iWater = iWater - 1 // Zähler runterzählen
Sprengler3.postUpdate(iWater) // Zähleritem aktualisieren
if(iWater > 0) // Falls Zähler größer 0
tWater.reschedule(now.plusSeconds(1)) // Timer in einer Sekunde erneut ausführen
])
end
Die beiden Variablen werden für den Timer und den Zähler gebraucht. Da die Rule nicht dauerhaft läuft, müssen beide Variaben global definiert werden. Man könnte auch das Item als "Zählerquelle" nutzen, allerdings braucht das wesentlich mehr Prozessorzyklen

Ob das allerdings so funktioniert, wie Du Dir das vorstellst? Die UI ist nicht unbedingt dazu gedacht, im Sekundentakt upzudaten.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet
-
- Beiträge: 5
- Registriert: 5. Sep 2020 10:43
Re: Rule Countdown mit Möglichkeit zum Killen
Mega, das funkt wie ich es mir vorgestellt habe. Besten Dank für die Unterstützung.
-
- Beiträge: 1
- Registriert: 9. Dez 2022 11:13
Re: Rule Countdown mit Möglichkeit zum Killen
Hallo,
ich bin leider etwas unwissend. Gibt es bei der Rule ein Möglichkeit den Countdown von einem Number:Item loslaufen zu lassen?
Also nicht bei einer fixen Zahl.
Danke
ich bin leider etwas unwissend. Gibt es bei der Rule ein Möglichkeit den Countdown von einem Number:Item loslaufen zu lassen?
Also nicht bei einer fixen Zahl.
Danke
- udo1toni
- Beiträge: 15248
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Rule Countdown mit Möglichkeit zum Killen
Ja, das geht. Aber weil ich immer auf Krümel achte: Es gibt kein Number:Item
Es gibt Number Items. Wenn Du den Doppelpunkt anhängst, handelt es sich um ein UoM Item und hinter dem Doppelpunkt steht dann die Messgröße, also z.B. Number:Temperature. Solche Items übergeben nicht nur den Zahlenwert, sondern zusätzlich auch noch die Einheit, in der sie angegeben ist, also z.B. °F oder K. Und der Witz an der Sache: Du kannst für die Ausgabe eine beliebige passende Einheit erzwingen, also der Channel übergibt z.B. 20 °C und Du erzwingst °F, dann gibt das Item 68 °F aus, oder wenn Du K erzwingst, 293,15 K, und das komplett ohne sich mit irgendwelchen Formeln zu beschäftigen, also eigentlich eine sehr coole Funktion. Leider muss man dann in Rules sehr genau aufpassen, wie man diese Werte weiterverarbeitet
aber irgendwas ist ja immer...
Zurück zu Deiner Anforderung: Als Beispiel mag der Code von oben gelten, in leicht abgeänderter Form:
Das Item Countdown wird als Item zum Runterzählen verwendet. Sobald es einen Befehl empfängt, wird dieser auf Gültigkeit geprüft und gegebenenfalls die Rule abgebrochen. Ist es eine gültige Zahl über 0, wird der Timer gestartet und die Rule ist beendet.
Nach einer Sekunde läuft der Timer ab und der Scheduler startet den hinterlegten Code. Dieser liest den aktuellen Wert aus dem Item und zieht gleich 1 ab.
Anschließend wird der neue Wert ins Item geschrieben. Ist der neue Wert größer 0, wird der Timer erneut geplant.
Limitierung in dieser Form: Wenn Du über die UI den Zahlenwert eingibst, geschieht dies in den meisten Fällen über plus/minus. Jeder einzelne Tastendruck führt nun zu einem Befehl. Das bedeutet, um Werte über 1 einstellen zu können, musst Du mehrmals pro Sekunde den Wert erhöhen, sonst fängt der Timer umgehend an zu arbeiten und zieht die von Dir erhöhten Werte gleich wieder ab
Sinnnvoller wäre es also, entweder über Selection vorgegebene Werte in das Item zu laden (also meinetwegen einen Knopf mit dem hinterlegten Wert 120, ein weiterer mit 300 und noch einer mit 600, dann kannst Du auf Knopfdruck den Timer auf 2, 5 oder 10 Minuten setzen und der Countdown startet.
Oder man erstellt ein Start Item, welches den Countdown startet und nutzt das Number Item nur zum Einstellen und Anzeigen des Countdowns, nicht aber zum Start des Countdowns.
Wichtig ist in dem Zusammenhang, den Unterschied zwischen Command und Update zu verstehen. Command sendet einen Befehl (deshalb sendCommand), Update ändert lediglich den Status des Items (das geschieht meist automatisch nach einem Befehl, deshalb postUpdate - nur so als Eselsbrücke) Eingaben in der UI (also über Pages oder die Sitemap) lösen gewöhnlich immer einen Befehl aus, den das betreffende Item empfängt.
In den Rules gibt es Trigger für beide Ereignisse, changed für den Status, received command für einen durch das Item empfangenen Befehl.


Zurück zu Deiner Anforderung: Als Beispiel mag der Code von oben gelten, in leicht abgeänderter Form:
Code: Alles auswählen
var Timer tCountdown = null // globale Variablen vor der ersten Rule einfügen
rule "Count down"
when
Item Countdown received command // Item hat Befehl empfangen
then
if(!(receivedCommand instanceof Number)) { // war Befehl eine Zahl?
logWarn("countdown","Command ist ungültig! ({})",receivedCommand) // Falls nein, Fehlermeldung
return; // und Abbruch
}
if(!(receivedCommand as Number).intValue > 0) { // war Zahl größer 0?
logWarn("countdown","Command ist kleiner 1, Abbruch.!") // Falls nein, Fehlermeldung
return; // und Abbruch
}
tCountdown?.cancel // falls noch ein Timer läuft, abbrechen
tCountdown = createTimer(now.plusSeconds(1), [| // Timer anlegen und nach einer Sekunde ausführen
val iCd = (Countdown..state as Number) - 1 // Wert auslesen und herunterzählen
Countdown.postUpdate(iCd) // Zähleritem aktualisieren
if(iCd > 0) // Falls Zähler größer 0
tCountdown.reschedule(now.plusSeconds(1)) // Timer in einer Sekunde erneut ausführen
])
end
Nach einer Sekunde läuft der Timer ab und der Scheduler startet den hinterlegten Code. Dieser liest den aktuellen Wert aus dem Item und zieht gleich 1 ab.
Anschließend wird der neue Wert ins Item geschrieben. Ist der neue Wert größer 0, wird der Timer erneut geplant.
Limitierung in dieser Form: Wenn Du über die UI den Zahlenwert eingibst, geschieht dies in den meisten Fällen über plus/minus. Jeder einzelne Tastendruck führt nun zu einem Befehl. Das bedeutet, um Werte über 1 einstellen zu können, musst Du mehrmals pro Sekunde den Wert erhöhen, sonst fängt der Timer umgehend an zu arbeiten und zieht die von Dir erhöhten Werte gleich wieder ab

Sinnnvoller wäre es also, entweder über Selection vorgegebene Werte in das Item zu laden (also meinetwegen einen Knopf mit dem hinterlegten Wert 120, ein weiterer mit 300 und noch einer mit 600, dann kannst Du auf Knopfdruck den Timer auf 2, 5 oder 10 Minuten setzen und der Countdown startet.
Oder man erstellt ein Start Item, welches den Countdown startet und nutzt das Number Item nur zum Einstellen und Anzeigen des Countdowns, nicht aber zum Start des Countdowns.
Wichtig ist in dem Zusammenhang, den Unterschied zwischen Command und Update zu verstehen. Command sendet einen Befehl (deshalb sendCommand), Update ändert lediglich den Status des Items (das geschieht meist automatisch nach einem Befehl, deshalb postUpdate - nur so als Eselsbrücke) Eingaben in der UI (also über Pages oder die Sitemap) lösen gewöhnlich immer einen Befehl aus, den das betreffende Item empfängt.
In den Rules gibt es Trigger für beide Ereignisse, changed für den Status, received command für einen durch das Item empfangenen Befehl.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet