]> git.basschouten.com Git - openhab-addons.git/blob
d035c9d543565caf381eca645598b31d0766edb0
[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         updateStatus(ThingStatus.UNKNOWN);
81
82         scheduler.submit(() -> {
83             comm.startCommunication();
84             if (!comm.communicationActive()) {
85                 bridgeOffline();
86                 return;
87             }
88
89             updateProperties();
90
91             updateStatus(ThingStatus.ONLINE);
92
93             int refreshInterval = config.refresh;
94             setupRefreshTimer(refreshInterval);
95
96             NikoHomeControlDiscoveryService discovery = nhcDiscovery;
97             if (discovery != null) {
98                 discovery.discoverDevices();
99             } else {
100                 logger.debug("cannot discover devices, discovery service not started");
101             }
102         });
103     }
104
105     /**
106      * Schedule future communication refresh.
107      *
108      * @param interval_config Time before refresh in minutes.
109      */
110     private void setupRefreshTimer(int refreshInterval) {
111         ScheduledFuture<?> timer = refreshTimer;
112         if (timer != null) {
113             timer.cancel(true);
114             refreshTimer = null;
115         }
116
117         if (refreshInterval == 0) {
118             return;
119         }
120
121         // This timer will restart the bridge connection periodically
122         logger.debug("restart bridge connection every {} min", refreshInterval);
123         refreshTimer = scheduler.scheduleWithFixedDelay(() -> {
124             logger.debug("restart communication at scheduled time");
125
126             NikoHomeControlCommunication comm = nhcComm;
127             if (comm != null) {
128                 comm.restartCommunication();
129                 if (!comm.communicationActive()) {
130                     bridgeOffline();
131                     return;
132                 }
133
134                 updateProperties();
135
136                 updateStatus(ThingStatus.ONLINE);
137             }
138         }, refreshInterval, refreshInterval, TimeUnit.MINUTES);
139     }
140
141     /**
142      * Take bridge offline when error in communication with Niko Home Control IP-interface.
143      */
144     protected void bridgeOffline() {
145         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
146                 "@text/offline.communication-error");
147     }
148
149     /**
150      * Put bridge online when error in communication resolved.
151      */
152     public void bridgeOnline() {
153         updateProperties();
154         updateStatus(ThingStatus.ONLINE);
155     }
156
157     @Override
158     public void controllerOffline(String message) {
159         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, message);
160     }
161
162     @Override
163     public void controllerOnline() {
164         bridgeOnline();
165
166         int refreshInterval = config.refresh;
167         if (refreshTimer == null) {
168             setupRefreshTimer(refreshInterval);
169         }
170     }
171
172     /**
173      * Update bridge properties with properties returned from Niko Home Control Controller.
174      */
175     protected abstract void updateProperties();
176
177     @Override
178     public void dispose() {
179         ScheduledFuture<?> timer = refreshTimer;
180         if (timer != null) {
181             timer.cancel(true);
182         }
183         refreshTimer = null;
184
185         NikoHomeControlCommunication comm = nhcComm;
186         if (comm != null) {
187             comm.stopCommunication();
188         }
189         nhcComm = null;
190     }
191
192     @Override
193     public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
194         NikoHomeControlCommunication comm = nhcComm;
195         // if the communication had not been started yet, just dispose and initialize again
196         if (comm == null) {
197             super.handleConfigurationUpdate(configurationParameters);
198             return;
199         }
200
201         Configuration configuration = editConfiguration();
202         for (Entry<String, Object> configurationParmeter : configurationParameters.entrySet()) {
203             configuration.put(configurationParmeter.getKey(), configurationParmeter.getValue());
204         }
205         updateConfiguration(configuration);
206
207         setConfig();
208
209         scheduler.submit(() -> {
210             comm.restartCommunication();
211             if (!comm.communicationActive()) {
212                 bridgeOffline();
213                 return;
214             }
215
216             updateProperties();
217
218             updateStatus(ThingStatus.ONLINE);
219
220             int refreshInterval = config.refresh;
221             setupRefreshTimer(refreshInterval);
222         });
223     }
224
225     /**
226      * Set discovery service handler to be able to start discovery after bridge initialization.
227      *
228      * @param nhcDiscovery
229      */
230     public void setNhcDiscovery(@Nullable NikoHomeControlDiscoveryService nhcDiscovery) {
231         this.nhcDiscovery = nhcDiscovery;
232     }
233
234     @Override
235     public void alarmEvent(String alarmText) {
236         logger.debug("triggering alarm channel with {}", alarmText);
237         triggerChannel(CHANNEL_ALARM, alarmText);
238         updateStatus(ThingStatus.ONLINE);
239     }
240
241     @Override
242     public void noticeEvent(String alarmText) {
243         logger.debug("triggering notice channel with {}", alarmText);
244         triggerChannel(CHANNEL_NOTICE, alarmText);
245         updateStatus(ThingStatus.ONLINE);
246     }
247
248     @Override
249     public void updatePropertiesEvent() {
250         updateProperties();
251     }
252
253     /**
254      * Get the Niko Home Control communication object.
255      *
256      * @return Niko Home Control communication object
257      */
258     public @Nullable NikoHomeControlCommunication getCommunication() {
259         return nhcComm;
260     }
261
262     @Override
263     public @Nullable InetAddress getAddr() {
264         InetAddress addr = null;
265         try {
266             addr = InetAddress.getByName(config.addr);
267         } catch (UnknownHostException e) {
268             logger.debug("Cannot resolve hostname {} to IP adress", config.addr);
269         }
270         return addr;
271     }
272
273     @Override
274     public int getPort() {
275         return config.port;
276     }
277
278     protected synchronized void setConfig() {
279         config = getConfig().as(NikoHomeControlBridgeConfig.class);
280     }
281 }