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.satel.internal.handler;
15 import java.nio.charset.Charset;
16 import java.time.ZoneId;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.satel.internal.command.NewStatesCommand;
23 import org.openhab.binding.satel.internal.command.SatelCommand;
24 import org.openhab.binding.satel.internal.config.SatelBridgeConfig;
25 import org.openhab.binding.satel.internal.event.ConnectionStatusEvent;
26 import org.openhab.binding.satel.internal.event.SatelEventListener;
27 import org.openhab.binding.satel.internal.protocol.SatelModule;
28 import org.openhab.binding.satel.internal.types.IntegraType;
29 import org.openhab.core.thing.Bridge;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingStatusDetail;
33 import org.openhab.core.thing.binding.ConfigStatusBridgeHandler;
34 import org.openhab.core.types.Command;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * The {@link SatelBridgeHandler} is base class for all bridge handlers.
41 * @author Krzysztof Goworek - Initial contribution
44 public abstract class SatelBridgeHandler extends ConfigStatusBridgeHandler implements SatelEventListener {
46 private final Logger logger = LoggerFactory.getLogger(SatelBridgeHandler.class);
48 private SatelBridgeConfig config = new SatelBridgeConfig();
49 private @Nullable SatelModule satelModule;
50 private @Nullable ScheduledFuture<?> pollingJob;
51 private String userCodeOverride = "";
52 private final ZoneId integraZone = ZoneId.systemDefault();
54 public SatelBridgeHandler(Bridge bridge) {
59 public void incomingEvent(ConnectionStatusEvent event) {
60 final SatelModule satelModule = this.satelModule;
61 if (satelModule != null) {
62 // update bridge status and get new states from the system
63 if (event.isConnected()) {
64 updateStatus(ThingStatus.ONLINE);
65 satelModule.sendCommand(new NewStatesCommand(satelModule.hasExtPayloadSupport()));
67 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, event.getReason());
73 public void handleCommand(ChannelUID channelUID, Command command) {
74 // the bridge does not support any command at the moment
75 logger.debug("New command for {}: {}", channelUID, command);
78 protected void initialize(final SatelModule satelModule) {
79 logger.debug("Initializing bridge handler");
81 final SatelBridgeConfig config = getConfigAs(SatelBridgeConfig.class);
83 this.satelModule = satelModule;
84 satelModule.addEventListener(this);
86 logger.debug("Satel module opened");
88 final ScheduledFuture<?> pollingJob = this.pollingJob;
89 if (pollingJob == null || pollingJob.isCancelled()) {
90 Runnable pollingCommand = () -> {
91 if (!satelModule.isInitialized()) {
92 logger.debug("Module not initialized yet, skipping refresh");
96 // get list of states that have changed
97 logger.trace("Sending 'get new states' command");
98 satelModule.sendCommand(new NewStatesCommand(satelModule.hasExtPayloadSupport()));
100 this.pollingJob = scheduler.scheduleWithFixedDelay(pollingCommand, 0, config.getRefresh(),
101 TimeUnit.MILLISECONDS);
106 public void dispose() {
107 logger.debug("Disposing bridge handler.");
109 final ScheduledFuture<?> pollingJob = this.pollingJob;
110 if (pollingJob != null && !pollingJob.isCancelled()) {
111 pollingJob.cancel(true);
112 this.pollingJob = null;
115 final SatelModule satelModule = this.satelModule;
116 if (satelModule != null) {
118 this.satelModule = null;
119 logger.debug("Satel module closed.");
124 * Adds given listener to list of event receivers.
126 * @param listener listener object to add
128 public void addEventListener(SatelEventListener listener) {
129 final SatelModule satelModule = this.satelModule;
130 if (satelModule != null) {
131 satelModule.addEventListener(listener);
136 * Removes given listener from list of event receivers.
138 * @param listener listener object to remove
140 public void removeEventListener(SatelEventListener listener) {
141 final SatelModule satelModule = this.satelModule;
142 if (satelModule != null) {
143 satelModule.removeEventListener(listener);
148 public boolean isInitialized() {
149 final SatelModule satelModule = this.satelModule;
150 return satelModule != null && satelModule.isInitialized();
154 * @return type of Integra system
157 public IntegraType getIntegraType() {
158 final SatelModule satelModule = this.satelModule;
159 return satelModule != null ? satelModule.getIntegraType() : IntegraType.UNKNOWN;
163 * @return current user code, either from the configuration or set later using {@link #setUserCode(String)}
165 public String getUserCode() {
166 if (!userCodeOverride.isEmpty()) {
167 return userCodeOverride;
169 return config.getUserCode();
174 * @param userCode new use code that overrides the one in the configuration
176 public void setUserCode(String userCode) {
177 this.userCodeOverride = userCode;
181 * @return encoding for texts
183 public Charset getEncoding() {
185 return config.getEncoding();
186 } catch (Exception e) {
187 logger.info("Invalid or unsupported encoding configured for {}", getThing().getUID());
188 return Charset.defaultCharset();
193 * @return zone for Integra date and time values
195 public ZoneId getZoneId() {
200 * Sends given command to communication module.
202 * @param command a command to send
203 * @param async if <code>false</code> method waits for the response
204 * @return <code>true</code> if send succeeded
206 public boolean sendCommand(SatelCommand command, boolean async) {
207 final SatelModule satelModule = this.satelModule;
208 if (satelModule == null) {
212 return satelModule.sendCommand(command);
213 } else if (!satelModule.sendCommand(command, true)) {
217 boolean interrupted = false;
218 while (!interrupted) {
219 // wait for command state change
221 synchronized (command) {
222 command.wait(satelModule.getTimeout());
224 } catch (InterruptedException e) {
225 // ignore, we will leave the loop on next interruption state check
228 // check current state
229 switch (command.getState()) {
235 // wait for next change unless interrupted