2 * Copyright (c) 2010-2024 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.binding.nikohomecontrol.internal.protocol;
15 import java.time.ZoneId;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ScheduledExecutorService;
19 import java.util.concurrent.ScheduledFuture;
20 import java.util.concurrent.TimeUnit;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
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.
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.
40 * @author Mark Herwege - Initial Contribution
43 public abstract class NikoHomeControlCommunication {
45 private final Logger logger = LoggerFactory.getLogger(NikoHomeControlCommunication.class);
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<>();
53 protected final NhcControllerEvent handler;
55 protected final ScheduledExecutorService scheduler;
58 private volatile int delay = 0;
59 private volatile int attempt = 0;
60 protected volatile @Nullable ScheduledFuture<?> scheduledRestart = null;
62 protected NikoHomeControlCommunication(NhcControllerEvent handler, ScheduledExecutorService scheduler) {
63 this.handler = handler;
64 this.scheduler = scheduler;
68 * Start Communication with Niko Home Control system.
70 public abstract void startCommunication();
73 * Stop Communication with Niko Home Control system.
75 public void stopCommunication() {
76 stopScheduledRestart();
82 * Stop Communication with Niko Home Control system, but keep reconnection attempts going.
84 public abstract void resetCommunication();
86 protected synchronized void stopScheduledRestart() {
87 ScheduledFuture<?> future = scheduledRestart;
91 scheduledRestart = null;
97 * Close and restart communication with Niko Home Control system.
99 public synchronized void restartCommunication() {
100 resetCommunication();
102 startCommunication();
105 private synchronized void checkAndRestartCommunication() {
106 restartCommunication();
108 // Try again if it didn't succeed
109 if (!communicationActive()) {
111 delay = ((attempt <= 5) ? 30 : 60);
112 logger.debug("schedule communication restart in {} seconds", delay);
113 scheduledRestart = scheduler.schedule(this::checkAndRestartCommunication, delay, TimeUnit.SECONDS);
115 stopScheduledRestart();
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.
124 public synchronized void scheduleRestartCommunication() {
125 // Don't do this if we already scheduled to restart
126 if (scheduledRestart == null) {
129 scheduledRestart = scheduler.schedule(this::checkAndRestartCommunication, 0, TimeUnit.SECONDS);
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.
137 * @return True if active
139 public abstract boolean communicationActive();
142 * Return the timezone for the system.
146 public ZoneId getTimeZone() {
147 return handler.getTimeZone();
151 * Return all actions in the Niko Home Control Controller.
153 * @return <code>Map<String, {@link NhcAction}></code>
155 public Map<String, NhcAction> getActions() {
160 * Return all thermostats in the Niko Home Control Controller.
162 * @return <code>Map<String, {@link NhcThermostat}></code>
164 public Map<String, NhcThermostat> getThermostats() {
169 * Return all meters in the Niko Home Control Controller.
171 * @return <code>Map<String, {@link NhcMeter}></code>
173 public Map<String, NhcMeter> getMeters() {
178 * Return all access devices in the Niko Home Control Controller.
180 * @return <code>Map<String, {@link NhcAccess}></code>
182 public Map<String, NhcAccess> getAccessDevices() {
183 return accessDevices;
187 * Return all video devices in the Niko Home Control Controller.
189 * @return <code>Map<String, {@link NhcVideo}></code>
191 public Map<String, NhcVideo> getVideoDevices() {
196 * Execute an action command by sending it to Niko Home Control.
201 public abstract void executeAction(String actionId, String value);
204 * Execute a thermostat command by sending it to Niko Home Control.
206 * @param thermostatId
209 public abstract void executeThermostat(String thermostatId, String mode);
212 * Execute a thermostat command by sending it to Niko Home Control.
214 * @param thermostatId
215 * @param overruleTemp
216 * @param overruleTime
218 public abstract void executeThermostat(String thermostatId, int overruleTemp, int overruleTime);
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}.
227 public abstract void executeMeter(String meterId);
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.
235 public void startMeterLive(String meterId) {
236 NhcMeter meter = getMeters().get(meterId);
238 meter.startMeterLive();
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.
248 public abstract void retriggerMeterLive(String meterId);
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)}.
256 public void stopMeterLive(String meterId) {
257 NhcMeter meter = getMeters().get(meterId);
259 meter.stopMeterLive();
264 * Start retrieving meter data from Niko Home Control at a regular interval.
267 * @param refresh reading frequency in minutes
269 public void startMeter(String meterId, int refresh) {
270 NhcMeter meter = getMeters().get(meterId);
272 meter.startMeter(refresh);
277 * Stop retrieving meter data from Niko Home Control at a regular interval.
279 public void stopMeter(String meterId) {
280 NhcMeter meter = getMeters().get(meterId);
287 * Stop retrieving meter data from Niko Home Control at a regular interval for all meters.
289 public void stopAllMeters() {
290 for (String meterId : getMeters().keySet()) {
292 stopMeterLive(meterId);
297 * Execute a bell command on an access control device by sending it to Niko Home Control.
301 public void executeAccessBell(String accessId) {
305 * Execute a bell command on video control device by sending it to Niko Home Control.
310 public void executeVideoBell(String accessId, int buttonIndex) {
314 * Switches state ring and come on access control device (turns on if off and off if on) by sending it to Niko Home
318 * @param ringAndComeIn status
320 public void executeAccessRingAndComeIn(String accessId, boolean ringAndComeIn) {
324 * Execute an unlock command on an access control device by sending it to Niko Home Control.
328 public void executeAccessUnlock(String accessId) {