2 * Copyright (c) 2010-2021 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.apache.commons.lang.StringUtils;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.satel.internal.command.NewStatesCommand;
24 import org.openhab.binding.satel.internal.command.SatelCommand;
25 import org.openhab.binding.satel.internal.config.SatelBridgeConfig;
26 import org.openhab.binding.satel.internal.event.ConnectionStatusEvent;
27 import org.openhab.binding.satel.internal.event.SatelEventListener;
28 import org.openhab.binding.satel.internal.protocol.SatelModule;
29 import org.openhab.binding.satel.internal.types.IntegraType;
30 import org.openhab.core.thing.Bridge;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.thing.binding.ConfigStatusBridgeHandler;
35 import org.openhab.core.types.Command;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * The {@link SatelBridgeHandler} is base class for all bridge handlers.
42 * @author Krzysztof Goworek - Initial contribution
45 public abstract class SatelBridgeHandler extends ConfigStatusBridgeHandler implements SatelEventListener {
47 private final Logger logger = LoggerFactory.getLogger(SatelBridgeHandler.class);
49 private SatelBridgeConfig config = new SatelBridgeConfig();
50 private @Nullable SatelModule satelModule;
51 private @Nullable ScheduledFuture<?> pollingJob;
52 private String userCodeOverride = "";
53 private final ZoneId integraZone = ZoneId.systemDefault();
55 public SatelBridgeHandler(Bridge bridge) {
60 public void incomingEvent(ConnectionStatusEvent event) {
61 final SatelModule satelModule = this.satelModule;
62 if (satelModule != null) {
63 // update bridge status and get new states from the system
64 if (event.isConnected()) {
65 updateStatus(ThingStatus.ONLINE);
66 satelModule.sendCommand(new NewStatesCommand(satelModule.hasExtPayloadSupport()));
68 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, event.getReason());
74 public void handleCommand(ChannelUID channelUID, Command command) {
75 // the bridge does not support any command at the moment
76 logger.debug("New command for {}: {}", channelUID, command);
79 protected void initialize(final SatelModule satelModule) {
80 logger.debug("Initializing bridge handler");
82 final SatelBridgeConfig config = getConfigAs(SatelBridgeConfig.class);
84 this.satelModule = satelModule;
85 satelModule.addEventListener(this);
87 logger.debug("Satel module opened");
89 final ScheduledFuture<?> pollingJob = this.pollingJob;
90 if (pollingJob == null || pollingJob.isCancelled()) {
91 Runnable pollingCommand = () -> {
92 if (!satelModule.isInitialized()) {
93 logger.debug("Module not initialized yet, skipping refresh");
97 // get list of states that have changed
98 logger.trace("Sending 'get new states' command");
99 satelModule.sendCommand(new NewStatesCommand(satelModule.hasExtPayloadSupport()));
101 this.pollingJob = scheduler.scheduleWithFixedDelay(pollingCommand, 0, config.getRefresh(),
102 TimeUnit.MILLISECONDS);
107 public void dispose() {
108 logger.debug("Disposing bridge handler.");
110 final ScheduledFuture<?> pollingJob = this.pollingJob;
111 if (pollingJob != null && !pollingJob.isCancelled()) {
112 pollingJob.cancel(true);
113 this.pollingJob = null;
116 final SatelModule satelModule = this.satelModule;
117 if (satelModule != null) {
119 this.satelModule = null;
120 logger.debug("Satel module closed.");
125 * Adds given listener to list of event receivers.
127 * @param listener listener object to add
129 public void addEventListener(SatelEventListener listener) {
130 final SatelModule satelModule = this.satelModule;
131 if (satelModule != null) {
132 satelModule.addEventListener(listener);
137 * Removes given listener from list of event receivers.
139 * @param listener listener object to remove
141 public void removeEventListener(SatelEventListener listener) {
142 final SatelModule satelModule = this.satelModule;
143 if (satelModule != null) {
144 satelModule.removeEventListener(listener);
149 public boolean isInitialized() {
150 final SatelModule satelModule = this.satelModule;
151 return satelModule != null && satelModule.isInitialized();
155 * @return type of Integra system
158 public IntegraType getIntegraType() {
159 final SatelModule satelModule = this.satelModule;
160 return satelModule != null ? satelModule.getIntegraType() : IntegraType.UNKNOWN;
164 * @return current user code, either from the configuration or set later using {@link #setUserCode(String)}
166 public String getUserCode() {
167 if (StringUtils.isNotEmpty(userCodeOverride)) {
168 return userCodeOverride;
170 return config.getUserCode();
175 * @param userCode new use code that overrides the one in the configuration
177 public void setUserCode(String userCode) {
178 this.userCodeOverride = userCode;
182 * @return encoding for texts
184 public Charset getEncoding() {
186 return config.getEncoding();
187 } catch (Exception e) {
188 logger.info("Invalid or unsupported encoding configured for {}", getThing().getUID());
189 return Charset.defaultCharset();
194 * @return zone for Integra date and time values
196 public ZoneId getZoneId() {
201 * Sends given command to communication module.
203 * @param command a command to send
204 * @param async if <code>false</code> method waits for the response
205 * @return <code>true</code> if send succeeded
207 public boolean sendCommand(SatelCommand command, boolean async) {
208 final SatelModule satelModule = this.satelModule;
209 if (satelModule == null) {
213 return satelModule.sendCommand(command);
214 } else if (!satelModule.sendCommand(command, true)) {
218 boolean interrupted = false;
219 while (!interrupted) {
220 // wait for command state change
222 synchronized (command) {
223 command.wait(satelModule.getTimeout());
225 } catch (InterruptedException e) {
226 // ignore, we will leave the loop on next interruption state check
229 // check current state
230 switch (command.getState()) {
236 // wait for next change unless interrupted