2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.io.hueemulation.internal.automation;
15 import java.time.Duration;
16 import java.util.Random;
17 import java.util.concurrent.Callable;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.core.automation.ModuleHandlerCallback;
22 import org.openhab.core.automation.Trigger;
23 import org.openhab.core.automation.handler.BaseTriggerModuleHandler;
24 import org.openhab.core.automation.handler.TriggerHandlerCallback;
25 import org.openhab.core.scheduler.ScheduledCompletableFuture;
26 import org.openhab.core.scheduler.Scheduler;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * This trigger module time allows a trigger that is setup with a time (hours:minutes:seconds).
32 * As soon as that time has run up, it will trigger.
34 * A random factor and repeat times can also be configured.
36 * @author David Graeff - Initial contribution
39 public class TimerTriggerHandler extends BaseTriggerModuleHandler implements Callable<Duration> {
41 private final Logger logger = LoggerFactory.getLogger(TimerTriggerHandler.class);
43 public static final String MODULE_TYPE_ID = "timer.TimerTrigger";
44 public static final String CALLBACK_CONTEXT_NAME = "CALLBACK";
45 public static final String MODULE_CONTEXT_NAME = "MODULE";
47 public static final String CFG_REPEAT = "repeat";
48 public static final String CFG_TIME = "time";
49 public static final String CFG_TIME_RND = "randomizeTime";
51 private final Scheduler scheduler;
52 private final Duration duration;
53 private @Nullable ScheduledCompletableFuture<?> schedule;
55 private static class Config {
58 String randomizeTime = "";
63 public TimerTriggerHandler(Trigger module, Scheduler scheduler) {
65 this.scheduler = scheduler;
66 config = module.getConfiguration().as(Config.class);
68 String[] fields = config.time.split(":");
69 Duration d1 = Duration.parse(String.format("P%dH%dM%sS", fields[0], fields[1], fields[2]));
71 // Take optional random time (a range-like parameter) into account
72 if (!config.randomizeTime.isEmpty()) {
73 fields = config.randomizeTime.split(":");
74 Duration d2 = Duration.parse(String.format("P%dH%dM%sS", fields[0], fields[1], fields[2]));
75 // The random time must be later a bigger value than time
76 if (d1.compareTo(d2) >= 0) {
77 throw new IllegalArgumentException();
79 // Compute the difference, turn in to seconds, get a random second value between 0 and that upper bound
80 // and then add it to the base time
81 Duration difference = d2.minus(d1);
82 duration = d1.plus(Duration.ofSeconds(randomSeconds(difference.getSeconds())));
88 protected long randomSeconds(long maximum) {
89 return Math.abs(new Random().nextLong()) % maximum;
93 public synchronized void setCallback(ModuleHandlerCallback callback) {
94 super.setCallback(callback);
95 if (config.repeat != 0) {
100 private void scheduleJob() {
101 schedule = scheduler.after(this, duration);
102 logger.debug("Scheduled timer to expire in '{}' for trigger '{}'.", duration, module.getId());
106 public synchronized void dispose() {
108 ScheduledCompletableFuture<?> future = schedule;
109 if (future != null) {
111 logger.debug("cancelled job for trigger '{}'.", module.getId());
116 public Duration call() {
117 ((TriggerHandlerCallback) callback).triggered(module, null);
119 if (config.repeat == 0) {