]> git.basschouten.com Git - openhab-addons.git/blob
dd7e8f129f8c5b67b6f3e9a65566df60730bc737
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.io.hueemulation.internal.automation;
14
15 import java.time.Duration;
16 import java.util.Random;
17 import java.util.concurrent.Callable;
18
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;
29
30 /**
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.
33  * <p>
34  * A random factor and repeat times can also be configured.
35  * 
36  * @author David Graeff - Initial contribution
37  */
38 @NonNullByDefault
39 public class TimerTriggerHandler extends BaseTriggerModuleHandler implements Callable<Duration> {
40
41     private final Logger logger = LoggerFactory.getLogger(TimerTriggerHandler.class);
42
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";
46
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";
50
51     private final Scheduler scheduler;
52     private final Duration duration;
53     private @Nullable ScheduledCompletableFuture<?> schedule;
54
55     private static class Config {
56         int repeat = 1;
57         String time = "";
58         String randomizeTime = "";
59     }
60
61     Config config;
62
63     public TimerTriggerHandler(Trigger module, Scheduler scheduler) {
64         super(module);
65         this.scheduler = scheduler;
66         config = module.getConfiguration().as(Config.class);
67
68         String[] fields = config.time.split(":");
69         Duration d1 = Duration.parse(String.format("P%dH%dM%sS", fields[0], fields[1], fields[2]));
70
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();
78             }
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())));
83         } else {
84             duration = d1;
85         }
86     }
87
88     protected long randomSeconds(long maximum) {
89         return Math.abs(new Random().nextLong()) % maximum;
90     }
91
92     @Override
93     public synchronized void setCallback(ModuleHandlerCallback callback) {
94         super.setCallback(callback);
95         if (config.repeat != 0) {
96             scheduleJob();
97         }
98     }
99
100     private void scheduleJob() {
101         schedule = scheduler.after(this, duration);
102         logger.debug("Scheduled timer to expire in '{}' for trigger '{}'.", duration, module.getId());
103     }
104
105     @Override
106     public synchronized void dispose() {
107         super.dispose();
108         ScheduledCompletableFuture<?> future = schedule;
109         if (future != null) {
110             future.cancel(true);
111             logger.debug("cancelled job for trigger '{}'.", module.getId());
112         }
113     }
114
115     @Override
116     public Duration call() {
117         ((TriggerHandlerCallback) callback).triggered(module, null);
118         config.repeat -= 1;
119         if (config.repeat == 0) {
120             schedule = null;
121         } else {
122             scheduleJob();
123         }
124         return duration;
125     }
126 }