]> git.basschouten.com Git - openhab-addons.git/blob
41b67f57eec3b437496e971f371dd67db235bb6c
[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("Niko Home Control: 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("Niko Home Control: restart bridge connection every {} min", refreshInterval);
121         refreshTimer = scheduler.scheduleWithFixedDelay(() -> {
122             logger.debug("Niko Home Control: 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                 "Niko Home Control: error starting 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() {
157         bridgeOffline();
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, so they can be made visible
172      * in PaperUI.
173      */
174     protected abstract void updateProperties();
175
176     @Override
177     public void dispose() {
178         ScheduledFuture<?> timer = refreshTimer;
179         if (timer != null) {
180             timer.cancel(true);
181         }
182         refreshTimer = null;
183
184         NikoHomeControlCommunication comm = nhcComm;
185         if (comm != null) {
186             comm.stopCommunication();
187         }
188         nhcComm = null;
189     }
190
191     @Override
192     public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
193         NikoHomeControlCommunication comm = nhcComm;
194         // if the communication had not been started yet, just dispose and initialize again
195         if (comm == null) {
196             super.handleConfigurationUpdate(configurationParameters);
197             return;
198         }
199
200         Configuration configuration = editConfiguration();
201         for (Entry<String, Object> configurationParmeter : configurationParameters.entrySet()) {
202             configuration.put(configurationParmeter.getKey(), configurationParmeter.getValue());
203         }
204         updateConfiguration(configuration);
205
206         setConfig();
207
208         scheduler.submit(() -> {
209             comm.restartCommunication();
210             if (!comm.communicationActive()) {
211                 bridgeOffline();
212                 return;
213             }
214
215             updateProperties();
216
217             updateStatus(ThingStatus.ONLINE);
218
219             int refreshInterval = config.refresh;
220             setupRefreshTimer(refreshInterval);
221         });
222     }
223
224     /**
225      * Set discovery service handler to be able to start discovery after bridge initialization.
226      *
227      * @param nhcDiscovery
228      */
229     public void setNhcDiscovery(@Nullable NikoHomeControlDiscoveryService nhcDiscovery) {
230         this.nhcDiscovery = nhcDiscovery;
231     }
232
233     @Override
234     public void alarmEvent(String alarmText) {
235         logger.debug("Niko Home Control: triggering alarm channel with {}", alarmText);
236         triggerChannel(CHANNEL_ALARM, alarmText);
237         updateStatus(ThingStatus.ONLINE);
238     }
239
240     @Override
241     public void noticeEvent(String alarmText) {
242         logger.debug("Niko Home Control: triggering notice channel with {}", alarmText);
243         triggerChannel(CHANNEL_NOTICE, alarmText);
244         updateStatus(ThingStatus.ONLINE);
245     }
246
247     @Override
248     public void updatePropertiesEvent() {
249         updateProperties();
250     }
251
252     /**
253      * Get the Niko Home Control communication object.
254      *
255      * @return Niko Home Control communication object
256      */
257     public @Nullable NikoHomeControlCommunication getCommunication() {
258         return nhcComm;
259     }
260
261     @Override
262     public @Nullable InetAddress getAddr() {
263         InetAddress addr = null;
264         try {
265             addr = InetAddress.getByName(config.addr);
266         } catch (UnknownHostException e) {
267             logger.debug("Niko Home Control: Cannot resolve hostname {} to IP adress", config.addr);
268         }
269         return addr;
270     }
271
272     @Override
273     public int getPort() {
274         return config.port;
275     }
276
277     protected synchronized void setConfig() {
278         config = getConfig().as(NikoHomeControlBridgeConfig.class);
279     }
280 }