]> git.basschouten.com Git - openhab-addons.git/blob
8699ef857e814577fb20770844e9c43b8c585d91
[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 package org.openhab.binding.cbus.handler;
14
15 import java.util.concurrent.ScheduledFuture;
16 import java.util.concurrent.TimeUnit;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.binding.cbus.internal.CBusNetworkConfiguration;
21 import org.openhab.core.thing.Bridge;
22 import org.openhab.core.thing.ChannelUID;
23 import org.openhab.core.thing.Thing;
24 import org.openhab.core.thing.ThingStatus;
25 import org.openhab.core.thing.ThingStatusDetail;
26 import org.openhab.core.thing.binding.BaseBridgeHandler;
27 import org.openhab.core.thing.binding.ThingHandler;
28 import org.openhab.core.types.Command;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.daveoxley.cbus.CGateException;
33 import com.daveoxley.cbus.CGateSession;
34 import com.daveoxley.cbus.Network;
35 import com.daveoxley.cbus.Project;
36
37 /**
38  * The {@link CBusNetworkHandler} is responsible for handling commands, which are
39  * sent to one of the channels.
40  *
41  * @author Scott Linton - Initial contribution
42  */
43 @NonNullByDefault
44 public class CBusNetworkHandler extends BaseBridgeHandler {
45
46     private final Logger logger = LoggerFactory.getLogger(CBusNetworkHandler.class);
47     private @Nullable CBusNetworkConfiguration configuration;
48     private @Nullable Network network;
49     private @Nullable Project projectObject;
50     private @Nullable ScheduledFuture<?> initNetwork;
51     private @Nullable ScheduledFuture<?> networkSync;
52
53     public CBusNetworkHandler(Bridge thing) {
54         super(thing);
55     }
56
57     // This is abstract in base class so have to implement it.
58     @Override
59     public void handleCommand(ChannelUID channelUID, Command command) {
60     }
61
62     @Override
63     public void initialize() {
64         logger.debug("initialize ");
65         configuration = getConfigAs(CBusNetworkConfiguration.class);
66         logger.debug("Using configuration {}", configuration);
67         CBusCGateHandler bridgeHandler = getCBusCGateHandler();
68         if (bridgeHandler == null || !bridgeHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
69             logger.debug("bridge not online");
70             updateStatus(ThingStatus.OFFLINE);
71             return;
72         }
73         logger.debug("Bridge online so init properly");
74         scheduler.execute(this::cgateOnline);
75     }
76
77     @Override
78     public void dispose() {
79         ScheduledFuture<?> networkSync = this.networkSync;
80         if (networkSync != null) {
81             networkSync.cancel(false);
82         }
83         ScheduledFuture<?> initNetwork = this.initNetwork;
84         if (initNetwork != null) {
85             initNetwork.cancel(false);
86         }
87         super.dispose();
88     }
89
90     public void cgateStateChanged(boolean isOnline) {
91         logger.debug("CgateStateChanged {}", isOnline);
92         if (!isOnline) {
93             network = null;
94             projectObject = null;
95             updateStatus();
96         } else {
97             cgateOnline();
98         }
99     }
100
101     private void cgateOnline() {
102         CBusNetworkConfiguration configuration = this.configuration;
103         if (configuration == null) {
104             logger.debug("cgateOnline - NetworkHandler not initialised");
105             return;
106         }
107         ThingStatus lastStatus = getThing().getStatus();
108         logger.debug("cgateOnline {}", lastStatus);
109
110         Integer networkID = configuration.id;
111         String project = configuration.project;
112         logger.debug("cgateOnline netid {} project {}", networkID, project);
113         Project projectObject = getProjectObject();
114         Network network = getNetwork();
115         logger.debug("network {}", network);
116         CBusCGateHandler cbusCGateHandler = getCBusCGateHandler();
117         if (cbusCGateHandler == null) {
118             logger.debug("NoCGateHandler");
119             return;
120         }
121         try {
122             if (projectObject == null) {
123                 CGateSession session = cbusCGateHandler.getCGateSession();
124                 if (session != null) {
125                     try {
126                         projectObject = (Project) session.getCGateObject("//" + project);
127                         this.projectObject = projectObject;
128                     } catch (CGateException ignore) {
129                         // We dont need to do anything other than stop this propagating
130                     }
131                 }
132                 if (projectObject == null) {
133                     logger.debug("Cant get projectobject");
134                     return;
135                 }
136             }
137             if (network == null) {
138                 CGateSession session = cbusCGateHandler.getCGateSession();
139                 if (session != null) {
140                     try {
141                         network = (Network) session.getCGateObject("//" + project + "/" + networkID);
142                         this.network = network;
143                     } catch (CGateException ignore) {
144                         // We dont need to do anything other than stop this propagating
145                     }
146                 }
147                 if (network == null) {
148                     logger.debug("cgateOnline: Cant get network");
149                     return;
150                 }
151             }
152             String state = network.getState();
153             logger.debug("Network state is {}", state);
154             if ("new".equals(state)) {
155                 projectObject.start();
156                 logger.debug("Need to wait for it to be synced");
157             } else if ("sync".equals(state)) {
158                 logger.debug("Network is syncing so wait for it to be ok");
159             }
160             if (!"ok".equals(state)) {
161                 ScheduledFuture<?> initNetwork = this.initNetwork;
162                 if (initNetwork == null || initNetwork.isCancelled()) {
163                     this.initNetwork = scheduler.scheduleWithFixedDelay(this::checkNetworkOnline, 30, 30,
164                             TimeUnit.SECONDS);
165                     logger.debug("Schedule a check every minute");
166                 } else {
167                     logger.debug("initNetwork alreadys started");
168                 }
169                 updateStatus();
170                 return;
171             }
172         } catch (CGateException e) {
173             logger.warn("Cannot load C-Bus network {}", networkID, e);
174             updateStatus(ThingStatus.UNINITIALIZED, ThingStatusDetail.COMMUNICATION_ERROR);
175         }
176         updateStatus();
177     }
178
179     private void checkNetworkOnline() {
180         Network network = getNetwork();
181         try {
182             if (network != null && network.isOnline()) {
183                 logger.debug("Network is online");
184                 ScheduledFuture<?> initNetwork = this.initNetwork;
185                 if (initNetwork != null) {
186                     initNetwork.cancel(false);
187                     this.initNetwork = null;
188                 }
189             } else {
190                 ThingStatus lastStatus = getThing().getStatus();
191                 logger.debug("Network still not online {}", lastStatus);
192             }
193         } catch (CGateException e) {
194             logger.warn("Cannot check if network is online {} ", network.getNetworkID());
195         }
196         updateStatus();
197     }
198
199     private void updateStatus() {
200         CBusNetworkConfiguration configuration = this.configuration;
201         if (configuration == null) {
202             logger.debug("updateStatus - NetworkHandler not initialised");
203             return;
204         }
205         ThingStatus lastStatus = getThing().getStatus();
206         Network network = getNetwork();
207         CBusCGateHandler cbusCGateHandler = getCBusCGateHandler();
208         try {
209             if (cbusCGateHandler == null || !cbusCGateHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
210                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "CGate connection offline");
211             } else if (network == null) {
212                 logger.debug("No network - set configuration error");
213                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No Network object available");
214             } else if (network.isOnline()) {
215                 updateStatus(ThingStatus.ONLINE);
216             } else {
217                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
218                         "Network is not reporting online");
219             }
220         } catch (CGateException e) {
221             logger.warn("Problem checking network state for network {}", network.getNetworkID(), e);
222             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
223         }
224         if (!getThing().getStatus().equals(lastStatus)) {
225             ScheduledFuture<?> networkSync = this.networkSync;
226             if (lastStatus == ThingStatus.OFFLINE) {
227                 if (networkSync == null || networkSync.isCancelled()) {
228                     this.networkSync = scheduler.scheduleWithFixedDelay(this::doNetworkSync, 10,
229                             configuration.syncInterval, TimeUnit.SECONDS);
230                 }
231             } else {
232                 if (networkSync != null) {
233                     networkSync.cancel(false);
234                 }
235             }
236             for (Thing thing : getThing().getThings()) {
237                 ThingHandler handler = thing.getHandler();
238                 if (handler instanceof CBusGroupHandler) {
239                     ((CBusGroupHandler) handler).updateStatus();
240                 }
241             }
242         }
243     }
244
245     private void doNetworkSync() {
246         Network network = getNetwork();
247         try {
248             if (getThing().getStatus().equals(ThingStatus.ONLINE) && network != null) {
249                 logger.info("Starting network sync on network {}", network.getNetworkID());
250                 network.startSync();
251             }
252         } catch (CGateException e) {
253             logger.warn("Cannot start network sync on network {} - {}", network.getNetworkID(), e.getMessage());
254         }
255     }
256
257     private @Nullable CBusCGateHandler getCBusCGateHandler() {
258         logger.debug("getCBusCGateHandler");
259         Bridge bridge = getBridge();
260         if (bridge == null) {
261             logger.debug("Required bridge not defined for device.");
262             return null;
263         }
264         ThingHandler handler = bridge.getHandler();
265         if (handler instanceof CBusCGateHandler) {
266             return (CBusCGateHandler) handler;
267         } else {
268             logger.debug("No available bridge handler found for bridge: {}.", bridge.getUID());
269             return null;
270         }
271     }
272
273     public @Nullable Network getNetwork() {
274         return network;
275     }
276
277     public int getNetworkId() {
278         CBusNetworkConfiguration configuration = this.configuration;
279         if (configuration == null) {
280             logger.debug("getNetworkId - NetworkHandler not initialised");
281             return -1;
282         }
283         return configuration.id;
284     }
285
286     private @Nullable Project getProjectObject() {
287         return projectObject;
288     }
289 }