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.qbus.internal.handler;
15 import static org.openhab.binding.qbus.internal.QbusBindingConstants.*;
16 import static org.openhab.core.library.types.UpDownType.DOWN;
17 import static org.openhab.core.types.RefreshType.REFRESH;
19 import java.io.IOException;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.qbus.internal.QbusBridgeHandler;
25 import org.openhab.binding.qbus.internal.protocol.QbusCommunication;
26 import org.openhab.binding.qbus.internal.protocol.QbusRol;
27 import org.openhab.core.library.types.IncreaseDecreaseType;
28 import org.openhab.core.library.types.PercentType;
29 import org.openhab.core.library.types.UpDownType;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.types.Command;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * The {@link QbusRolHandler} is responsible for handling commands, which are
40 * sent to one of the channels.
42 * @author Koen Schockaert - Initial Contribution
46 public class QbusRolHandler extends QbusGlobalHandler {
48 private final Logger logger = LoggerFactory.getLogger(QbusRolHandler.class);
50 protected @Nullable QbusThingsConfig rolConfig = new QbusThingsConfig();
52 private @Nullable Integer rolId;
54 private @Nullable String sn;
56 public QbusRolHandler(Thing thing) {
64 public void initialize() {
71 scheduler.submit(() -> {
72 QbusCommunication controllerComm;
74 if (this.rolId != null) {
75 controllerComm = getCommunication("Screen/Store", this.rolId);
77 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "ID for Screen/Store no set! " + this.rolId);
81 if (controllerComm == null) {
82 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
83 "ID for Screen/Store not known in controller " + this.rolId);
87 Map<Integer, QbusRol> rolCommLocal = controllerComm.getRol();
89 QbusRol outputLocal = rolCommLocal.get(this.rolId);
91 if (outputLocal == null) {
92 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
93 "Bridge could not initialize Screen/Store ID " + this.rolId);
97 outputLocal.setThingHandler(this);
98 handleStateUpdate(outputLocal);
100 QbusBridgeHandler qBridgeHandler = getBridgeHandler("Screen/Store", this.rolId);
102 if (qBridgeHandler != null) {
103 if (qBridgeHandler.getStatus() == ThingStatus.ONLINE) {
104 updateStatus(ThingStatus.ONLINE);
106 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
107 "Bridge offline for SCREEN/STORE ID " + this.rolId);
114 * Handle the status update from the thing
117 public void handleCommand(ChannelUID channelUID, Command command) {
118 QbusCommunication qComm = getCommunication("Screen/Store", this.rolId);
121 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
122 "ID for ROLLERSHUTTER/SCREEN not known in controller " + this.rolId);
125 Map<Integer, QbusRol> rolComm = qComm.getRol();
127 QbusRol qRol = rolComm.get(this.rolId);
130 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
131 "ID for ROLLERSHUTTER/SCREEN not known in controller " + this.rolId);
134 scheduler.submit(() -> {
135 if (!qComm.communicationActive()) {
136 restartCommunication(qComm, "Screen/Store", this.rolId);
139 if (qComm.communicationActive()) {
140 if (command == REFRESH) {
141 handleStateUpdate(qRol);
145 switch (channelUID.getId()) {
146 case CHANNEL_ROLLERSHUTTER:
148 handleScreenposCommand(qRol, command);
149 } catch (IOException e) {
150 String message = e.getMessage();
151 logger.warn("Error on executing Rollershutter for screen ID {}. IOException: {}",
152 this.rolId, message);
153 } catch (InterruptedException e) {
154 String message = e.toString();
156 "Error on executing Rollershutter for screen ID {}. Interruptedexception {}",
157 this.rolId, message);
163 handleSlatsposCommand(qRol, command);
164 } catch (IOException e) {
165 String message = e.getMessage();
166 logger.warn("Error on executing Slats for screen ID {}. IOException: {}",
167 this.rolId, message);
168 } catch (InterruptedException e) {
169 String message = e.toString();
170 logger.warn("Error on executing Slats for screen ID {}. Interruptedexception {}",
171 this.rolId, message);
182 * Executes the command for screen up/down position
184 * @throws IOException
185 * @throws InterruptedException
187 private void handleScreenposCommand(QbusRol qRol, Command command) throws InterruptedException, IOException {
188 String snr = getSN();
190 if (command instanceof UpDownType) {
191 UpDownType upDown = (UpDownType) command;
192 if (upDown == DOWN) {
193 qRol.execute(0, snr);
195 qRol.execute(100, snr);
197 } else if (command instanceof IncreaseDecreaseType) {
198 IncreaseDecreaseType inc = (IncreaseDecreaseType) command;
199 int stepValue = ((Number) getConfig().get(CONFIG_STEP_VALUE)).intValue();
200 Integer currentValue = qRol.getState();
203 if (currentValue != null) {
204 if (inc == IncreaseDecreaseType.INCREASE) {
205 newValue = currentValue + stepValue;
206 // round down to step multiple
207 newValue = newValue - newValue % stepValue;
208 sendValue = newValue > 100 ? 100 : newValue;
209 qRol.execute(sendValue, snr);
211 newValue = currentValue - stepValue;
212 // round up to step multiple
213 newValue = newValue + newValue % stepValue;
214 sendValue = newValue > 100 ? 100 : newValue;
215 qRol.execute(sendValue, snr);
218 } else if (command instanceof PercentType) {
219 PercentType p = (PercentType) command;
220 int pp = p.intValue();
221 if (PercentType.ZERO.equals(p)) {
222 qRol.execute(0, snr);
224 qRol.execute(pp, snr);
231 * Executes the command for screen slats position
233 * @throws IOException
234 * @throws InterruptedException
236 private void handleSlatsposCommand(QbusRol qRol, Command command) throws InterruptedException, IOException {
237 String snr = getSN();
239 if (command instanceof UpDownType) {
240 if (command == DOWN) {
241 qRol.executeSlats(0, snr);
243 qRol.executeSlats(100, snr);
245 } else if (command instanceof IncreaseDecreaseType) {
246 int stepValue = ((Number) getConfig().get(CONFIG_STEP_VALUE)).intValue();
247 Integer currentValue = qRol.getState();
250 if (currentValue != null) {
251 if (command == IncreaseDecreaseType.INCREASE) {
252 newValue = currentValue + stepValue;
253 // round down to step multiple
254 newValue = newValue - newValue % stepValue;
255 sendValue = newValue > 100 ? 100 : newValue;
256 qRol.executeSlats(sendValue, snr);
258 newValue = currentValue - stepValue;
259 // round up to step multiple
260 newValue = newValue + newValue % stepValue;
261 sendValue = newValue > 100 ? 100 : newValue;
262 qRol.executeSlats(sendValue, snr);
265 } else if (command instanceof PercentType) {
266 int percentToInt = ((PercentType) command).intValue();
267 if (PercentType.ZERO.equals(command)) {
268 qRol.executeSlats(0, snr);
270 qRol.executeSlats(percentToInt, snr);
277 * Method to update state of channel, called from Qbus Screen/Store.
279 public void handleStateUpdate(QbusRol qRol) {
280 Integer rolState = qRol.getState();
281 Integer slatState = qRol.getStateSlats();
283 if (rolState != null) {
284 updateState(CHANNEL_ROLLERSHUTTER, new PercentType(rolState));
286 if (slatState != null) {
287 updateState(CHANNEL_SLATS, new PercentType(slatState));
292 * Returns the serial number of the controller
294 * @return the serial nr
296 public @Nullable String getSN() {
301 * Sets the serial number of the controller
303 public void setSN() {
304 QbusBridgeHandler qBridgeHandler = getBridgeHandler("Screen/Store", this.rolId);
305 if (qBridgeHandler == null) {
306 thingOffline(ThingStatusDetail.COMMUNICATION_ERROR,
307 "No communication with Qbus Bridge for ROLLERSHUTTER/SCREEN " + this.rolId);
310 sn = qBridgeHandler.getSn();
314 * Read the configuration
316 protected synchronized void readConfig() {
317 rolConfig = getConfig().as(QbusThingsConfig.class);
321 * Returns the Id from the configuration
325 public @Nullable Integer getId() {
326 QbusThingsConfig localConfig = rolConfig;
327 if (localConfig != null) {
328 return localConfig.rolId;