]> git.basschouten.com Git - openhab-addons.git/blob
b7e4472ff5071da2fdc685c0d3edf8b95448465c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.handler;
14
15 import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
16
17 import java.net.InetAddress;
18 import java.net.UnknownHostException;
19 import java.util.Map;
20 import java.util.Map.Entry;
21 import java.util.concurrent.ScheduledFuture;
22 import java.util.concurrent.TimeUnit;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.nikohomecontrol.internal.discovery.NikoHomeControlDiscoveryService;
27 import org.openhab.binding.nikohomecontrol.internal.protocol.NhcControllerEvent;
28 import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlCommunication;
29 import org.openhab.core.config.core.Configuration;
30 import org.openhab.core.thing.Bridge;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.thing.binding.BaseBridgeHandler;
35 import org.openhab.core.types.Command;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * {@link NikoHomeControlBridgeHandler} is an abstract class representing a handler to all different interfaces to the
41  * Niko Home Control System. {@link NikoHomeControlBridgeHandler1} or {@link NikoHomeControlBridgeHandler2} should be
42  * used for the respective
43  * version of Niko Home Control.
44  *
45  * @author Mark Herwege - Initial Contribution
46  */
47 @NonNullByDefault
48 public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler implements NhcControllerEvent {
49
50     private final Logger logger = LoggerFactory.getLogger(NikoHomeControlBridgeHandler.class);
51
52     protected @NonNullByDefault({}) NikoHomeControlBridgeConfig config;
53
54     protected @Nullable NikoHomeControlCommunication nhcComm;
55
56     private volatile @Nullable ScheduledFuture<?> refreshTimer;
57
58     protected volatile @Nullable NikoHomeControlDiscoveryService nhcDiscovery;
59
60     public NikoHomeControlBridgeHandler(Bridge nikoHomeControlBridge) {
61         super(nikoHomeControlBridge);
62     }
63
64     @Override
65     public void handleCommand(ChannelUID channelUID, Command command) {
66         // There is nothing to handle in the bridge handler
67     }
68
69     /**
70      * Create communication object to Niko Home Control IP-interface and start communication.
71      * Trigger discovery when communication setup is successful.
72      */
73     protected void startCommunication() {
74         NikoHomeControlCommunication comm = nhcComm;
75         if (comm == null) {
76             bridgeOffline();
77             return;
78         }
79
80         scheduler.submit(() -> {
81             comm.startCommunication();
82             if (!comm.communicationActive()) {
83                 bridgeOffline();
84                 return;
85             }
86
87             updateProperties();
88
89             updateStatus(ThingStatus.ONLINE);
90
91             int refreshInterval = config.refresh;
92             setupRefreshTimer(refreshInterval);
93
94             NikoHomeControlDiscoveryService discovery = nhcDiscovery;
95             if (discovery != null) {
96                 discovery.discoverDevices();
97             } else {
98                 logger.debug("cannot discover devices, discovery service not started");
99             }
100         });
101     }
102
103     /**
104      * Schedule future communication refresh.
105      *
106      * @param interval_config Time before refresh in minutes.
107      */
108     private void setupRefreshTimer(int refreshInterval) {
109         ScheduledFuture<?> timer = refreshTimer;
110         if (timer != null) {
111             timer.cancel(true);
112             refreshTimer = null;
113         }
114
115         if (refreshInterval == 0) {
116             return;
117         }
118
119         // This timer will restart the bridge connection periodically
120         logger.debug("restart bridge connection every {} min", refreshInterval);
121         refreshTimer = scheduler.scheduleWithFixedDelay(() -> {
122             logger.debug("restart communication at scheduled time");
123
124             NikoHomeControlCommunication comm = nhcComm;
125             if (comm != null) {
126                 comm.restartCommunication();
127                 if (!comm.communicationActive()) {
128                     bridgeOffline();
129                     return;
130                 }
131
132                 updateProperties();
133
134                 updateStatus(ThingStatus.ONLINE);
135             }
136         }, refreshInterval, refreshInterval, TimeUnit.MINUTES);
137     }
138
139     /**
140      * Take bridge offline when error in communication with Niko Home Control IP-interface.
141      */
142     protected void bridgeOffline() {
143         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
144                 "Error with bridge connection");
145     }
146
147     /**
148      * Put bridge online when error in communication resolved.
149      */
150     public void bridgeOnline() {
151         updateProperties();
152         updateStatus(ThingStatus.ONLINE);
153     }
154
155     @Override
156     public void controllerOffline(String message) {
157         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, message);
158     }
159
160     @Override
161     public void controllerOnline() {
162         bridgeOnline();
163
164         int refreshInterval = config.refresh;
165         if (refreshTimer == null) {
166             setupRefreshTimer(refreshInterval);
167         }
168     }
169
170     /**
171      * Update bridge properties with properties returned from Niko Home Control Controller.
172      */
173     protected abstract void updateProperties();
174
175     @Override
176     public void dispose() {
177         ScheduledFuture<?> timer = refreshTimer;
178         if (timer != null) {
179             timer.cancel(true);
180         }
181         refreshTimer = null;
182
183         NikoHomeControlCommunication comm = nhcComm;
184         if (comm != null) {
185             comm.stopCommunication();
186         }
187         nhcComm = null;
188     }
189
190     @Override
191     public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
192         NikoHomeControlCommunication comm = nhcComm;
193         // if the communication had not been started yet, just dispose and initialize again
194         if (comm == null) {
195             super.handleConfigurationUpdate(configurationParameters);
196             return;
197         }
198
199         Configuration configuration = editConfiguration();
200         for (Entry<String, Object> configurationParmeter : configurationParameters.entrySet()) {
201             configuration.put(configurationParmeter.getKey(), configurationParmeter.getValue());
202         }
203         updateConfiguration(configuration);
204
205         setConfig();
206
207         scheduler.submit(() -> {
208             comm.restartCommunication();
209             if (!comm.communicationActive()) {
210                 bridgeOffline();
211                 return;
212             }
213
214             updateProperties();
215
216             updateStatus(ThingStatus.ONLINE);
217
218             int refreshInterval = config.refresh;
219             setupRefreshTimer(refreshInterval);
220         });
221     }
222
223     /**
224      * Set discovery service handler to be able to start discovery after bridge initialization.
225      *
226      * @param nhcDiscovery
227      */
228     public void setNhcDiscovery(@Nullable NikoHomeControlDiscoveryService nhcDiscovery) {
229         this.nhcDiscovery = nhcDiscovery;
230     }
231
232     @Override
233     public void alarmEvent(String alarmText) {
234         logger.debug("triggering alarm channel with {}", alarmText);
235         triggerChannel(CHANNEL_ALARM, alarmText);
236         updateStatus(ThingStatus.ONLINE);
237     }
238
239     @Override
240     public void noticeEvent(String alarmText) {
241         logger.debug("triggering notice channel with {}", alarmText);
242         triggerChannel(CHANNEL_NOTICE, alarmText);
243         updateStatus(ThingStatus.ONLINE);
244     }
245
246     @Override
247     public void updatePropertiesEvent() {
248         updateProperties();
249     }
250
251     /**
252      * Get the Niko Home Control communication object.
253      *
254      * @return Niko Home Control communication object
255      */
256     public @Nullable NikoHomeControlCommunication getCommunication() {
257         return nhcComm;
258     }
259
260     @Override
261     public @Nullable InetAddress getAddr() {
262         InetAddress addr = null;
263         try {
264             addr = InetAddress.getByName(config.addr);
265         } catch (UnknownHostException e) {
266             logger.debug("Cannot resolve hostname {} to IP adress", config.addr);
267         }
268         return addr;
269     }
270
271     @Override
272     public int getPort() {
273         return config.port;
274     }
275
276     protected synchronized void setConfig() {
277         config = getConfig().as(NikoHomeControlBridgeConfig.class);
278     }
279 }