2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.cbus.handler;
15 import java.util.concurrent.ScheduledFuture;
16 import java.util.concurrent.TimeUnit;
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;
32 import com.daveoxley.cbus.CGateException;
33 import com.daveoxley.cbus.CGateSession;
34 import com.daveoxley.cbus.Network;
35 import com.daveoxley.cbus.Project;
38 * The {@link CBusNetworkHandler} is responsible for handling commands, which are
39 * sent to one of the channels.
41 * @author Scott Linton - Initial contribution
44 public class CBusNetworkHandler extends BaseBridgeHandler {
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;
53 public CBusNetworkHandler(Bridge thing) {
57 // This is abstract in base class so have to implement it.
59 public void handleCommand(ChannelUID channelUID, Command command) {
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);
73 logger.debug("Bridge online so init properly");
74 scheduler.execute(this::cgateOnline);
78 public void dispose() {
79 ScheduledFuture<?> networkSync = this.networkSync;
80 if (networkSync != null) {
81 networkSync.cancel(false);
83 ScheduledFuture<?> initNetwork = this.initNetwork;
84 if (initNetwork != null) {
85 initNetwork.cancel(false);
90 public void cgateStateChanged(boolean isOnline) {
91 logger.debug("CgateStateChanged {}", isOnline);
101 private void cgateOnline() {
102 CBusNetworkConfiguration configuration = this.configuration;
103 if (configuration == null) {
104 logger.debug("cgateOnline - NetworkHandler not initialised");
107 ThingStatus lastStatus = getThing().getStatus();
108 logger.debug("cgateOnline {}", lastStatus);
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");
122 if (projectObject == null) {
123 CGateSession session = cbusCGateHandler.getCGateSession();
124 if (session != null) {
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
132 if (projectObject == null) {
133 logger.debug("Cant get projectobject");
137 if (network == null) {
138 CGateSession session = cbusCGateHandler.getCGateSession();
139 if (session != null) {
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
147 if (network == null) {
148 logger.debug("cgateOnline: Cant get network");
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");
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,
165 logger.debug("Schedule a check every minute");
167 logger.debug("initNetwork alreadys started");
172 } catch (CGateException e) {
173 logger.warn("Cannot load C-Bus network {}", networkID, e);
174 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR);
179 private void checkNetworkOnline() {
180 Network network = getNetwork();
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;
190 ThingStatus lastStatus = getThing().getStatus();
191 logger.debug("Network still not online {}", lastStatus);
193 } catch (CGateException e) {
194 logger.warn("Cannot check if network is online {} ", network.getNetworkID());
199 private void updateStatus() {
200 CBusNetworkConfiguration configuration = this.configuration;
201 if (configuration == null) {
202 logger.debug("updateStatus - NetworkHandler not initialised");
205 ThingStatus lastStatus = getThing().getStatus();
206 Network network = getNetwork();
207 CBusCGateHandler cbusCGateHandler = getCBusCGateHandler();
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);
217 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
218 "Network is not reporting online");
220 } catch (CGateException e) {
221 logger.warn("Problem checking network state for network {}", network.getNetworkID(), e);
222 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
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);
232 if (networkSync != null) {
233 networkSync.cancel(false);
236 for (Thing thing : getThing().getThings()) {
237 ThingHandler handler = thing.getHandler();
238 if (handler instanceof CBusGroupHandler) {
239 ((CBusGroupHandler) handler).updateStatus();
245 private void doNetworkSync() {
246 Network network = getNetwork();
248 if (getThing().getStatus().equals(ThingStatus.ONLINE) && network != null) {
249 logger.info("Starting network sync on network {}", network.getNetworkID());
252 } catch (CGateException e) {
253 logger.warn("Cannot start network sync on network {} - {}", network.getNetworkID(), e.getMessage());
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.");
264 ThingHandler handler = bridge.getHandler();
265 if (handler instanceof CBusCGateHandler) {
266 return (CBusCGateHandler) handler;
268 logger.debug("No available bridge handler found for bridge: {}.", bridge.getUID());
273 public @Nullable Network getNetwork() {
277 public int getNetworkId() {
278 CBusNetworkConfiguration configuration = this.configuration;
279 if (configuration == null) {
280 logger.debug("getNetworkId - NetworkHandler not initialised");
283 return configuration.id;
286 private @Nullable Project getProjectObject() {
287 return projectObject;