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