]> git.basschouten.com Git - openhab-addons.git/blob
a08362fb13c510deda047e4c125728ca91323837
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.binding.nikohomecontrol.internal.protocol;
14
15 import java.time.ZoneId;
16 import java.util.Map;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ScheduledExecutorService;
19 import java.util.concurrent.ScheduledFuture;
20 import java.util.concurrent.TimeUnit;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * The {@link NikoHomeControlCommunication} class is an abstract class representing the communication objects with the
29  * Niko Home Control System.
30  * {@link org.openhab.binding.nikohomecontrol.internal.protocol.nhc1.NikoHomeControlCommunication1} or
31  * {@link org.openhab.binding.nikohomecontrol.internal.protocol.nhc2.NikoHomeControlCommunication2} should be
32  * used for the respective version of Niko Home Control.
33  * <ul>
34  * <li>Start and stop communication with the Niko Home Control System.
35  * <li>Read all setup and status information from the Niko Home Control Controller.
36  * <li>Execute Niko Home Control commands.
37  * <li>Listen to events from Niko Home Control.
38  * </ul>
39  *
40  * @author Mark Herwege - Initial Contribution
41  */
42 @NonNullByDefault
43 public abstract class NikoHomeControlCommunication {
44
45     private final Logger logger = LoggerFactory.getLogger(NikoHomeControlCommunication.class);
46
47     protected final Map<String, NhcAction> actions = new ConcurrentHashMap<>();
48     protected final Map<String, NhcThermostat> thermostats = new ConcurrentHashMap<>();
49     protected final Map<String, NhcMeter> meters = new ConcurrentHashMap<>();
50     protected final Map<String, NhcAccess> accessDevices = new ConcurrentHashMap<>();
51     protected final Map<String, NhcVideo> videoDevices = new ConcurrentHashMap<>();
52
53     protected final NhcControllerEvent handler;
54
55     protected final ScheduledExecutorService scheduler;
56
57     // restart attempts
58     private volatile int delay = 0;
59     private volatile int attempt = 0;
60     protected volatile @Nullable ScheduledFuture<?> scheduledRestart = null;
61
62     protected NikoHomeControlCommunication(NhcControllerEvent handler, ScheduledExecutorService scheduler) {
63         this.handler = handler;
64         this.scheduler = scheduler;
65     }
66
67     /**
68      * Start Communication with Niko Home Control system.
69      */
70     public abstract void startCommunication();
71
72     /**
73      * Stop Communication with Niko Home Control system.
74      */
75     public void stopCommunication() {
76         stopScheduledRestart();
77
78         resetCommunication();
79     }
80
81     /**
82      * Stop Communication with Niko Home Control system, but keep reconnection attempts going.
83      */
84     public abstract void resetCommunication();
85
86     protected synchronized void stopScheduledRestart() {
87         ScheduledFuture<?> future = scheduledRestart;
88         if (future != null) {
89             future.cancel(true);
90         }
91         scheduledRestart = null;
92         delay = 0;
93         attempt = 0;
94     }
95
96     /**
97      * Close and restart communication with Niko Home Control system.
98      */
99     public synchronized void restartCommunication() {
100         resetCommunication();
101
102         startCommunication();
103     }
104
105     private synchronized void checkAndRestartCommunication() {
106         restartCommunication();
107
108         // Try again if it didn't succeed
109         if (!communicationActive()) {
110             attempt++;
111             delay = ((attempt <= 5) ? 30 : 60);
112             logger.debug("schedule communication restart in {} seconds", delay);
113             scheduledRestart = scheduler.schedule(this::checkAndRestartCommunication, delay, TimeUnit.SECONDS);
114         } else {
115             stopScheduledRestart();
116         }
117     }
118
119     /**
120      * Close and restart communication with Niko Home Control system. This method will keep doing multiple reconnection
121      * attempts, starting immediately, then 5 times with 30 second intervals and every minute thereafter until the
122      * connection is re-established.
123      */
124     public synchronized void scheduleRestartCommunication() {
125         // Don't do this if we already scheduled to restart
126         if (scheduledRestart == null) {
127             delay = 0;
128             attempt = 0;
129             scheduledRestart = scheduler.schedule(this::checkAndRestartCommunication, 0, TimeUnit.SECONDS);
130         }
131     }
132
133     /**
134      * Method to check if communication with Niko Home Control is active. This method can be blocking for max 5s to wait
135      * for completion of startup.
136      *
137      * @return True if active
138      */
139     public abstract boolean communicationActive();
140
141     /**
142      * Return the timezone for the system.
143      *
144      * @return zoneId
145      */
146     public ZoneId getTimeZone() {
147         return handler.getTimeZone();
148     }
149
150     /**
151      * Return all actions in the Niko Home Control Controller.
152      *
153      * @return <code>Map&lt;String, {@link NhcAction}></code>
154      */
155     public Map<String, NhcAction> getActions() {
156         return actions;
157     }
158
159     /**
160      * Return all thermostats in the Niko Home Control Controller.
161      *
162      * @return <code>Map&lt;String, {@link NhcThermostat}></code>
163      */
164     public Map<String, NhcThermostat> getThermostats() {
165         return thermostats;
166     }
167
168     /**
169      * Return all meters in the Niko Home Control Controller.
170      *
171      * @return <code>Map&ltString, {@link NhcMeter}></code>
172      */
173     public Map<String, NhcMeter> getMeters() {
174         return meters;
175     }
176
177     /**
178      * Return all access devices in the Niko Home Control Controller.
179      *
180      * @return <code>Map&ltString, {@link NhcAccess}></code>
181      */
182     public Map<String, NhcAccess> getAccessDevices() {
183         return accessDevices;
184     }
185
186     /**
187      * Return all video devices in the Niko Home Control Controller.
188      *
189      * @return <code>Map&ltString, {@link NhcVideo}></code>
190      */
191     public Map<String, NhcVideo> getVideoDevices() {
192         return videoDevices;
193     }
194
195     /**
196      * Execute an action command by sending it to Niko Home Control.
197      *
198      * @param actionId
199      * @param value
200      */
201     public abstract void executeAction(String actionId, String value);
202
203     /**
204      * Execute a thermostat command by sending it to Niko Home Control.
205      *
206      * @param thermostatId
207      * @param mode
208      */
209     public abstract void executeThermostat(String thermostatId, String mode);
210
211     /**
212      * Execute a thermostat command by sending it to Niko Home Control.
213      *
214      * @param thermostatId
215      * @param overruleTemp
216      * @param overruleTime
217      */
218     public abstract void executeThermostat(String thermostatId, int overruleTemp, int overruleTime);
219
220     /**
221      * Query meter for energy, gas consumption or water production/consumption data. The query will update the total
222      * production/consumption and production/consumption from the start of the day through the meterReadingEvent
223      * callback in {@link NhcMeterEvent}.
224      *
225      * @param meterId
226      */
227     public abstract void executeMeter(String meterId);
228
229     /**
230      * Start retrieving energy meter data from Niko Home Control. The method is used to regularly retrigger the
231      * information flow. It can be left empty in concrete classes if the power data is flowing continuously.
232      *
233      * @param meterId
234      */
235     public void startMeterLive(String meterId) {
236         NhcMeter meter = getMeters().get(meterId);
237         if (meter != null) {
238             meter.startMeterLive();
239         }
240     }
241
242     /**
243      * Retrigger retrieving energy meter data from Niko Home Control. This is used if the power data does not continue
244      * flowing automatically and needs to be retriggered at regular intervals.
245      *
246      * @param meterId
247      */
248     public abstract void retriggerMeterLive(String meterId);
249
250     /**
251      * Stop retrieving energy meter data from Niko Home Control. This method can be used to stop a scheduled retrigger
252      * of the information flow, as scheduled in {{@link #startMeterLive(String)}.
253      *
254      * @param meterId
255      */
256     public void stopMeterLive(String meterId) {
257         NhcMeter meter = getMeters().get(meterId);
258         if (meter != null) {
259             meter.stopMeterLive();
260         }
261     };
262
263     /**
264      * Start retrieving meter data from Niko Home Control at a regular interval.
265      *
266      * @param meterId
267      * @param refresh reading frequency in minutes
268      */
269     public void startMeter(String meterId, int refresh) {
270         NhcMeter meter = getMeters().get(meterId);
271         if (meter != null) {
272             meter.startMeter(refresh);
273         }
274     }
275
276     /**
277      * Stop retrieving meter data from Niko Home Control at a regular interval.
278      */
279     public void stopMeter(String meterId) {
280         NhcMeter meter = getMeters().get(meterId);
281         if (meter != null) {
282             meter.stopMeter();
283         }
284     }
285
286     /**
287      * Stop retrieving meter data from Niko Home Control at a regular interval for all meters.
288      */
289     public void stopAllMeters() {
290         for (String meterId : getMeters().keySet()) {
291             stopMeter(meterId);
292             stopMeterLive(meterId);
293         }
294     }
295
296     /**
297      * Execute a bell command on an access control device by sending it to Niko Home Control.
298      *
299      * @param accessId
300      */
301     public void executeAccessBell(String accessId) {
302     }
303
304     /**
305      * Execute a bell command on video control device by sending it to Niko Home Control.
306      *
307      * @param accessId
308      * @param buttonIndex
309      */
310     public void executeVideoBell(String accessId, int buttonIndex) {
311     }
312
313     /**
314      * Switches state ring and come on access control device (turns on if off and off if on) by sending it to Niko Home
315      * Control.
316      *
317      * @param accessId
318      * @param ringAndComeIn status
319      */
320     public void executeAccessRingAndComeIn(String accessId, boolean ringAndComeIn) {
321     }
322
323     /**
324      * Execute an unlock command on an access control device by sending it to Niko Home Control.
325      *
326      * @param accessId
327      */
328     public void executeAccessUnlock(String accessId) {
329     }
330 }