Die "marodierenden Timer" sind nach wie vor die beste Lösung, wenn es kein Szenario gibt, um die Timer abzubrechen. Das hatte ich eingangs auch erwähnt.
Sollen die Timer abbrechbar sein, ist reschedule() eine Möglichkeit, die auch im Design Pattern vorgeschlagen wird (a.
https://community.openhab.org/t/design- ... mers/47699 oder
https://community.openhab.org/t/why-hav ... idea/47695).
Allerdings halte ich die Lösung wie im Design Pattern nur dann für sinnvoll, wenn man immer wieder und endlos den gleichen Code ausführen will.
Als Lösung für die Eingangsfrage verstellt das reschedule() und der damit verbundene Aufwand zur Unterscheidung der Aktionen (switch()) den Blick auf das, was eigentlich ausgeführt werden soll.
Intuitiver finde ich etwa den Ansatz:
Code: Alles auswählen
import java.util.Collection
import java.util.concurrent.ConcurrentLinkedQueue
var Collection<Timer> shellyTimers=null
rule "Start"
when
Item TestKontakt1STATE changed from OPEN to CLOSED
then
if (shellyTimers===null)
shellyTimers=new ConcurrentLinkedQueue()
else
shellyTimers.forEach[ t | t.cancel() ]
SRelais_B1_1.sendCommand(ON)
shellyTimers.add(createTimer(now().plusSeconds(5), [ SRelais_B1_1.sendCommand(OFF) ]) )
shellyTimers.add(createTimer(now().plusSeconds(7), [ SRelais_B1_2.sendCommand(ON) ]) )
shellyTimers.add(createTimer(now().plusSeconds(12), [ SRelais_B1_2.sendCommand(OFF); shellyTimers=null ]) )
end
oder, wenn die Timer nicht restartet werden sollen:
Code: Alles auswählen
import java.util.Collection
import java.util.Arrays
import java.util.LinkedList
var Collection<Timer> shellyTimers=null
rule "Start"
when
Item TestKontakt1STATE changed from OPEN to CLOSED
then
if (shellyTimers===null) {
SRelais_B1_1.sendCommand(ON)
shellyTimers=new LinkedList(Arrays::asList(
createTimer(now().plusSeconds(5), [ SRelais_B1_1.sendCommand(OFF) ]),
createTimer(now().plusSeconds(7), [ SRelais_B1_2.sendCommand(ON) ]),
createTimer(now().plusSeconds(12), [ SRelais_B1_2.sendCommand(OFF); shellyTimers=null ])
))
}
end
Die Collecton shellyTimers hält dabei die eigentlichen Timer als Einheit zusammen. Über sie können wie auch zu Beginn der ersten Start-Rule die Timer abgebrochen werden:
Code: Alles auswählen
rule "Abbruch"
when
...
then
if (shellyTimers!==null) {
shellyTimers.forEach[ t | t.cancel() ]
shellyTimers=null
}
end
Mehr akademisch ist diese Lösung:
Code: Alles auswählen
var Timer shellyTimer=null
rule "..."
when
Item TestKontakt1STATE changed from OPEN to CLOSED
then
if (shellyTimer!==null) shellyTimer.cancel()
SRelais_B1_1.sendCommand(ON)
shellyTimer=createTimer(now().plusSeconds(5),[
SRelais_B1_1.sendCommand(OFF)
shellyTimer=createTimer(now().plusSeconds(2),[
SRelais_B1_2.sendCommand(ON)
shellyTimer=createTimer(now().plusSeconds(5),[
SRelais_B1_2.sendCommand(OFF)
shellyTimer=null
])
])
])
end
Hier wird im Timer-Code der Timer immer wieder neu generiert.