]> git.basschouten.com Git - openhab-addons.git/blob
d519ea156e7c3961dfec0d75357f55ce6c6e5ad4
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.Map;
17 import java.util.Random;
18 import java.util.concurrent.Callable;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.core.automation.ModuleHandlerCallback;
23 import org.openhab.core.automation.Trigger;
24 import org.openhab.core.automation.handler.BaseTriggerModuleHandler;
25 import org.openhab.core.automation.handler.TriggerHandlerCallback;
26 import org.openhab.core.scheduler.ScheduledCompletableFuture;
27 import org.openhab.core.scheduler.Scheduler;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * This trigger module time allows a trigger that is setup with a time (hours:minutes:seconds).
33  * As soon as that time has run up, it will trigger.
34  * <p>
35  * A random factor and repeat times can also be configured.
36  *
37  * @author David Graeff - Initial contribution
38  */
39 @NonNullByDefault
40 public class TimerTriggerHandler extends BaseTriggerModuleHandler implements Callable<Duration> {
41
42     private final Logger logger = LoggerFactory.getLogger(TimerTriggerHandler.class);
43
44     public static final String MODULE_TYPE_ID = "timer.TimerTrigger";
45     public static final String CALLBACK_CONTEXT_NAME = "CALLBACK";
46     public static final String MODULE_CONTEXT_NAME = "MODULE";
47
48     public static final String CFG_REPEAT = "repeat";
49     public static final String CFG_TIME = "time";
50     public static final String CFG_TIME_RND = "randomizeTime";
51
52     private final Scheduler scheduler;
53     private final Duration duration;
54     private @Nullable ScheduledCompletableFuture<?> schedule;
55
56     private static class Config {
57         int repeat = 1;
58         String time = "";
59         String randomizeTime = "";
60     }
61
62     Config config;
63
64     public TimerTriggerHandler(Trigger module, Scheduler scheduler) {
65         super(module);
66         this.scheduler = scheduler;
67         config = module.getConfiguration().as(Config.class);
68
69         String[] fields = config.time.split(":");
70         Duration d1 = Duration.parse(String.format("P%dH%dM%sS", fields[0], fields[1], fields[2]));
71
72         // Take optional random time (a range-like parameter) into account
73         if (!config.randomizeTime.isEmpty()) {
74             fields = config.randomizeTime.split(":");
75             Duration d2 = Duration.parse(String.format("P%dH%dM%sS", fields[0], fields[1], fields[2]));
76             // The random time must be later a bigger value than time
77             if (d1.compareTo(d2) >= 0) {
78                 throw new IllegalArgumentException();
79             }
80             // Compute the difference, turn in to seconds, get a random second value between 0 and that upper bound
81             // and then add it to the base time
82             Duration difference = d2.minus(d1);
83             duration = d1.plus(Duration.ofSeconds(randomSeconds(difference.getSeconds())));
84         } else {
85             duration = d1;
86         }
87     }
88
89     protected long randomSeconds(long maximum) {
90         return Math.abs(new Random().nextLong()) % maximum;
91     }
92
93     @Override
94     public synchronized void setCallback(ModuleHandlerCallback callback) {
95         super.setCallback(callback);
96         if (config.repeat != 0) {
97             scheduleJob();
98         }
99     }
100
101     private void scheduleJob() {
102         schedule = scheduler.after(this, duration);
103         logger.debug("Scheduled timer to expire in '{}' for trigger '{}'.", duration, module.getId());
104     }
105
106     @Override
107     public synchronized void dispose() {
108         super.dispose();
109         ScheduledCompletableFuture<?> future = schedule;
110         if (future != null) {
111             future.cancel(true);
112             logger.debug("cancelled job for trigger '{}'.", module.getId());
113         }
114     }
115
116     @Override
117     public Duration call() {
118         ((TriggerHandlerCallback) callback).triggered(module, Map.of());
119         config.repeat -= 1;
120         if (config.repeat == 0) {
121             schedule = null;
122         } else {
123             scheduleJob();
124         }
125         return duration;
126     }
127 }