Timers
With timers in SmartBeans you can schedule actions to be executed after a specific time.
If you want to trigger actions at specific times or on a regular schedule (similar to cron jobs), use the time trigger feature of Home Assistant. The SmartBeans timer is not designed for this kind of scheduled operations. Instead, it is better suited for delaying actions after specific events or for implementing timeout mechanisms within automation flows.
A timer in SmartBeans is an instance of the Timer
class that can be instantiated programmatically by invoking the
createTimer()
method on the SmartBeans
API. For example, consider a scenario where you have implemented a bean for
motion-controlled lighting: instead of turning off the lights immediately when no motion is detected, you might want to
implement a 30-second delay. This can be efficiently achieved using a timer.
public class KitchenMotionControl implements SmartBean {
private SmartBeans sb;
@Entity("light.kitchen_ceiling")
private Light ceilingLight;
@OnStateTrigger(entity = "binary_sensor.motion_kitchen", to = "off")
public void onNoMotionDetected() {
Timer lightOffTimer = sb.createTimer(timer -> timer
.setInterval(Duration.ofSeconds(30))
.onElapsed(evt -> ceilingLight.turnOff())
);
lightOffTimer.start();
}
}
Using Annotations
Alternatively, you can define a timer using the @TimerDef
annotation. To implement this approach, create a field of
type Timer
in your SmartBean and annotate it with @TimerDef
. The annotation allows you to specify various timer
properties such as interval, repetition settings, and autostart behavior. SmartBeans will automatically instantiate
the timer and inject it into this field.
A significant advantage of this method is the ability to use additional annotations on your SmartBean methods to connect them directly to the timer. This annotation-driven approach results in more concise and readable code.
public class KitchenMotionControl implements SmartBean {
@TimerDef(interval = @Interval(seconds = 30))
private Timer lightOffTimer;
@Entity("light.kitchen_ceiling")
private Light ceilingLight;
@OnStateTrigger(entity = "binary_sensor.motion_kitchen", to = "off")
public void onNoMotionDetected() {
lightOffTimer.start();
}
@OnTimerElapsed("lightOffTimer")
public void turnOffLight() {
ceilingLight.turnOff();
}
}
Another advantage of having the Timer
object as a field of your bean is that you can invoke other operations on the timer
as described below.
Cancelling a Timer
You can cancel a timer by invoking the cancel()
method on the timer object. This immediately stops the timer and
triggers a cancellation event. For example, in our motion detection scenario, if motion is detected again while the
timer is running, you might want to prevent the light from turning off. In this case, you would cancel the timer,
ensuring that the light doesn't turn off after the 30-second delay.
public class KitchenMotionControl implements SmartBean {
@TimerDef(interval = @Interval(seconds = 30))
private Timer lightOffTimer;
@Entity("light.kitchen_ceiling")
private Light ceilingLight;
@OnStateTrigger(entity = "binary_sensor.motion_kitchen", to = "on")
public void onMotionDetected() {
if(lightOffTimer.isRunning()) {
lightOffTimer.cancel();
}
ceilingLight.turnOn();
}
@OnStateTrigger(entity = "binary_sensor.motion_kitchen", to = "off")
public void onNoMotionDetected() {
lightOffTimer.start();
}
@OnTimerElapsed("lightOffTimer")
public void turnOffLight() {
ceilingLight.turnOff();
}
}
Repeating and Autostart
SmartBeans timers can be configured to execute repeatedly at specified intervals. When a timer is initiated, the elapsed
event is triggered at each interval for the designated number of repetitions. If the timer is canceled during execution,
all subsequent event firings are immediately terminated, and no further elapsed
events will be triggered.
This timer will fire an elapsed
event every 10 seconds for three repetitions.
public class ASampleBean implements SmartBean {
private SmartBeans sb;
@TimerDef(interval = @Interval(seconds = 10), repeatCount = 3)
private Timer timer;
@OnTimerElapsed("timer")
public void onElapsed(TimerEvent evt) {
sb.log("Timer elapsed, there are %d repititions left.", evt.getRemainingRepeats());
}
@OnTimerCancelled("timer")
public void onTimerCanceled(TimerEvent evt) {
sb.log("Timer canceled with %d repititions left.", evt.getRemainingRepeats());
}
}
The autostart feature enables a timer to initialize and begin execution immediately upon creation, eliminating the need
for an explicit start()
method invocation. For timers configured via annotations, execution starts automatically
during bean deployment in SmartBeans.
public class ASampleBean implements SmartBean {
private SmartBeans sb;
@TimerDef(interval = @Interval(seconds = 20), autostart = true)
private Timer timer;
@OnTimerElapsed("timer")
public void onElapsed(TimerEvent evt) {
sb.log("Bean is deplyed for %d seconds now.", evt.getInterval().toSeconds());
}
}