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