]> git.basschouten.com Git - openhab-addons.git/blob
8f1c7ec39aad99c3e82627d749af48e67e02a444
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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
14 package org.openhab.binding.qbus.internal;
15
16 import java.io.IOException;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.qbus.internal.protocol.QbusCommunication;
23 import org.openhab.core.thing.Bridge;
24 import org.openhab.core.thing.ChannelUID;
25 import org.openhab.core.thing.ThingStatus;
26 import org.openhab.core.thing.ThingStatusDetail;
27 import org.openhab.core.thing.ThingStatusInfo;
28 import org.openhab.core.thing.binding.BaseBridgeHandler;
29 import org.openhab.core.types.Command;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * {@link QbusBridgeHandler} is the handler for a Qbus controller
35  *
36  * @author Koen Schockaert - Initial Contribution
37  */
38
39 @NonNullByDefault
40 public class QbusBridgeHandler extends BaseBridgeHandler {
41
42     private @Nullable QbusCommunication qbusComm;
43
44     protected @Nullable QbusConfiguration bridgeConfig = new QbusConfiguration();
45
46     private @Nullable ScheduledFuture<?> refreshTimer;
47
48     private final Logger logger = LoggerFactory.getLogger(QbusBridgeHandler.class);
49
50     public QbusBridgeHandler(Bridge Bridge) {
51         super(Bridge);
52     }
53
54     /**
55      * Initialize the bridge
56      */
57     @Override
58     public void initialize() {
59         readConfig();
60
61         Integer serverCheck = getServerCheck();
62
63         if (serverCheck != null) {
64             this.setupRefreshTimer(serverCheck);
65         }
66
67         createCommunicationObject();
68     }
69
70     /**
71      * Sets the Bridge call back
72      */
73     private void setBridgeCallBack() {
74         QbusCommunication qbusCommunication = getQbusCommunication();
75         if (qbusCommunication != null) {
76             qbusCommunication.setBridgeCallBack(this);
77         }
78     }
79
80     /**
81      * Create communication object to Qbus server and start communication.
82      *
83      * @param addr : IP address of Qbus server
84      * @param port : Communication port of QbusServer
85      */
86     private void createCommunicationObject() {
87         scheduler.submit(() -> {
88
89             setQbusCommunication(new QbusCommunication(thing));
90
91             QbusCommunication qbusCommunication = getQbusCommunication();
92
93             setBridgeCallBack();
94
95             Integer serverCheck = getServerCheck();
96             String sn = getSn();
97             if (serverCheck != null) {
98                 if (sn != null) {
99                     if (qbusCommunication != null) {
100                         try {
101                             qbusCommunication.startCommunication();
102                         } catch (InterruptedException e) {
103                             String msg = e.getMessage();
104                             bridgeOffline(ThingStatusDetail.COMMUNICATION_ERROR,
105                                     "Communication wit Qbus server could not be established, will try to reconnect every "
106                                             + serverCheck + " minutes. InterruptedException: " + msg);
107                             return;
108                         } catch (IOException e) {
109                             String msg = e.getMessage();
110                             bridgeOffline(ThingStatusDetail.COMMUNICATION_ERROR,
111                                     "Communication wit Qbus server could not be established, will try to reconnect every "
112                                             + serverCheck + " minutes. IOException: " + msg);
113                             return;
114                         }
115
116                         if (!qbusCommunication.communicationActive()) {
117                             bridgeOffline(ThingStatusDetail.COMMUNICATION_ERROR,
118                                     "No communication with Qbus Server, will try to reconnect every " + serverCheck
119                                             + " minutes");
120                             return;
121                         }
122
123                         if (!qbusCommunication.clientConnected()) {
124                             bridgePending("Waiting for Qbus client to come online");
125                             return;
126                         }
127
128                     }
129                 }
130             }
131         });
132     }
133
134     /**
135      * Updates offline status off the Bridge when an error occurs.
136      *
137      * @param status
138      * @param detail
139      * @param message
140      */
141     public void bridgeOffline(ThingStatusDetail detail, String message) {
142         updateStatus(ThingStatus.OFFLINE, detail, message);
143     }
144
145     /**
146      * Updates pending status off the Bridge (usualay when Qbus client id not connected)
147      *
148      * @param message
149      */
150     public void bridgePending(String message) {
151         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_CONFIGURATION_PENDING, message);
152     }
153
154     /**
155      * Put bridge online when error in communication resolved.
156      */
157     public void bridgeOnline() {
158         updateStatus(ThingStatus.ONLINE);
159     }
160
161     /**
162      * Initializes a timer that check the communication with Qbus server/client and tries to re-establish communication.
163      *
164      * @param refreshInterval Time before refresh in minutes.
165      */
166     private void setupRefreshTimer(int refreshInterval) {
167         ScheduledFuture<?> timer = refreshTimer;
168
169         if (timer != null) {
170             timer.cancel(true);
171             refreshTimer = null;
172         }
173
174         if (refreshInterval == 0) {
175             return;
176         }
177
178         refreshTimer = scheduler.scheduleWithFixedDelay(() -> {
179             logger.debug("Timer started");
180             QbusCommunication comm = getCommunication();
181             Integer serverCheck = getServerCheck();
182
183             if (comm != null) {
184                 if (serverCheck != null) {
185                     if (!comm.communicationActive()) {
186                         // Disconnected from Qbus Server, restart communication
187                         try {
188                             comm.startCommunication();
189                         } catch (InterruptedException e) {
190                             String msg = e.getMessage();
191                             bridgeOffline(ThingStatusDetail.COMMUNICATION_ERROR,
192                                     "Communication wit Qbus server could not be established, will try to reconnect every "
193                                             + serverCheck + " minutes. InterruptedException: " + msg);
194                         } catch (IOException e) {
195                             String msg = e.getMessage();
196                             bridgeOffline(ThingStatusDetail.COMMUNICATION_ERROR,
197                                     "Communication wit Qbus server could not be established, will try to reconnect every "
198                                             + serverCheck + " minutes. IOException: " + msg);
199                         }
200                     }
201                 }
202             }
203         }, refreshInterval, refreshInterval, TimeUnit.MINUTES);
204     }
205
206     /**
207      * Disposes the Bridge and stops communication with the Qbus server
208      */
209     @Override
210     public void dispose() {
211         ScheduledFuture<?> timer = refreshTimer;
212         if (timer != null) {
213             timer.cancel(true);
214         }
215
216         refreshTimer = null;
217
218         QbusCommunication comm = getCommunication();
219
220         if (comm != null) {
221             try {
222                 comm.stopCommunication();
223             } catch (IOException e) {
224                 String message = e.toString();
225                 logger.debug("Error on stopping communication.{} ", message);
226             }
227         }
228
229         comm = null;
230     }
231
232     /**
233      * Reconnect to Qbus server if controller is offline
234      */
235     public void ctdOffline() {
236         bridgePending("Waiting for CTD connection");
237     }
238
239     /**
240      * Get BridgeCommunication
241      *
242      * @return BridgeCommunication
243      */
244     public @Nullable QbusCommunication getQbusCommunication() {
245         if (this.qbusComm != null) {
246             return this.qbusComm;
247         } else {
248             return null;
249         }
250     }
251
252     /**
253      * Sets BridgeCommunication
254      *
255      * @param BridgeCommunication
256      */
257     void setQbusCommunication(QbusCommunication comm) {
258         this.qbusComm = comm;
259     }
260
261     /**
262      * Gets the status off the Bridge
263      *
264      * @return
265      */
266     public ThingStatus getStatus() {
267         return thing.getStatus();
268     }
269
270     /**
271      * Gets the status off the Bridge
272      *
273      * @return
274      */
275     public ThingStatusDetail getStatusDetails() {
276         ThingStatusInfo status = thing.getStatusInfo();
277         ThingStatusDetail detail = status.getStatusDetail();
278         return detail;
279     }
280
281     /**
282      * Sets the configuration parameters
283      */
284     protected void readConfig() {
285         bridgeConfig = getConfig().as(QbusConfiguration.class);
286     }
287
288     /**
289      * Get the Qbus communication object.
290      *
291      * @return Qbus communication object
292      */
293     public @Nullable QbusCommunication getCommunication() {
294         return this.qbusComm;
295     }
296
297     /**
298      * Get the ip address of the Qbus server.
299      *
300      * @return the ip address
301      */
302     public @Nullable String getAddress() {
303         QbusConfiguration localConfig = this.bridgeConfig;
304
305         if (localConfig != null) {
306             return localConfig.addr;
307         } else {
308             return null;
309         }
310     }
311
312     /**
313      * Get the listening port of the Qbus server.
314      *
315      * @return
316      */
317     public @Nullable Integer getPort() {
318         QbusConfiguration localConfig = this.bridgeConfig;
319
320         if (localConfig != null) {
321             return localConfig.port;
322         } else {
323             return null;
324         }
325     }
326
327     /**
328      * Get the serial nr of the Qbus server.
329      *
330      * @return the serial nr of the controller
331      */
332     public @Nullable String getSn() {
333         QbusConfiguration localConfig = this.bridgeConfig;
334
335         if (localConfig != null) {
336             return localConfig.sn;
337         } else {
338             return null;
339         }
340     }
341
342     /**
343      * Get the refresh interval.
344      *
345      * @return the refresh interval
346      */
347     public @Nullable Integer getServerCheck() {
348         QbusConfiguration localConfig = this.bridgeConfig;
349
350         if (localConfig != null) {
351             return localConfig.serverCheck;
352         } else {
353             return null;
354         }
355     }
356
357     @Override
358     public void handleCommand(ChannelUID channelUID, Command command) {
359     }
360 }