]> git.basschouten.com Git - openhab-addons.git/blob
d03a1ca7ea55e940370125172f11704b2e85b0ce
[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.qbus.internal.handler;
14
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;
18
19 import java.io.IOException;
20 import java.util.Map;
21
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;
37
38 /**
39  * The {@link QbusRolHandler} is responsible for handling commands, which are
40  * sent to one of the channels.
41  *
42  * @author Koen Schockaert - Initial Contribution
43  */
44
45 @NonNullByDefault
46 public class QbusRolHandler extends QbusGlobalHandler {
47
48     private final Logger logger = LoggerFactory.getLogger(QbusRolHandler.class);
49
50     protected @Nullable QbusThingsConfig rolConfig = new QbusThingsConfig();
51
52     private @Nullable Integer rolId;
53
54     private @Nullable String sn;
55
56     public QbusRolHandler(Thing thing) {
57         super(thing);
58     }
59
60     /**
61      * Main initialization
62      */
63     @Override
64     public void initialize() {
65         readConfig();
66
67         this.rolId = getId();
68
69         setSN();
70
71         scheduler.submit(() -> {
72             QbusCommunication controllerComm;
73
74             if (this.rolId != null) {
75                 controllerComm = getCommunication("Screen/Store", this.rolId);
76             } else {
77                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "ID for Screen/Store no set! " + this.rolId);
78                 return;
79             }
80
81             if (controllerComm == null) {
82                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
83                         "ID for Screen/Store not known in controller " + this.rolId);
84                 return;
85             }
86
87             Map<Integer, QbusRol> rolCommLocal = controllerComm.getRol();
88
89             QbusRol outputLocal = rolCommLocal.get(this.rolId);
90
91             if (outputLocal == null) {
92                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
93                         "Bridge could not initialize Screen/Store ID " + this.rolId);
94                 return;
95             }
96
97             outputLocal.setThingHandler(this);
98             handleStateUpdate(outputLocal);
99
100             QbusBridgeHandler qBridgeHandler = getBridgeHandler("Screen/Store", this.rolId);
101
102             if (qBridgeHandler != null) {
103                 if (qBridgeHandler.getStatus() == ThingStatus.ONLINE) {
104                     updateStatus(ThingStatus.ONLINE);
105                 } else {
106                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
107                             "Bridge offline for SCREEN/STORE ID " + this.rolId);
108                 }
109             }
110         });
111     }
112
113     /**
114      * Handle the status update from the thing
115      */
116     @Override
117     public void handleCommand(ChannelUID channelUID, Command command) {
118         QbusCommunication qComm = getCommunication("Screen/Store", this.rolId);
119
120         if (qComm == null) {
121             thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
122                     "ID for ROLLERSHUTTER/SCREEN not known in controller " + this.rolId);
123             return;
124         } else {
125             Map<Integer, QbusRol> rolComm = qComm.getRol();
126
127             QbusRol qRol = rolComm.get(this.rolId);
128
129             if (qRol == null) {
130                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
131                         "ID for ROLLERSHUTTER/SCREEN not known in controller " + this.rolId);
132                 return;
133             } else {
134                 scheduler.submit(() -> {
135                     if (!qComm.communicationActive()) {
136                         restartCommunication(qComm, "Screen/Store", this.rolId);
137                     }
138
139                     if (qComm.communicationActive()) {
140                         if (command == REFRESH) {
141                             handleStateUpdate(qRol);
142                             return;
143                         }
144
145                         switch (channelUID.getId()) {
146                             case CHANNEL_ROLLERSHUTTER:
147                                 try {
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();
155                                     logger.warn(
156                                             "Error on executing Rollershutter for screen ID {}. Interruptedexception {}",
157                                             this.rolId, message);
158                                 }
159                                 break;
160
161                             case CHANNEL_SLATS:
162                                 try {
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);
172                                 }
173                                 break;
174                         }
175                     }
176                 });
177             }
178         }
179     }
180
181     /**
182      * Executes the command for screen up/down position
183      *
184      * @throws IOException
185      * @throws InterruptedException
186      */
187     private void handleScreenposCommand(QbusRol qRol, Command command) throws InterruptedException, IOException {
188         String snr = getSN();
189         if (snr != null) {
190             if (command instanceof UpDownType) {
191                 UpDownType upDown = (UpDownType) command;
192                 if (upDown == DOWN) {
193                     qRol.execute(0, snr);
194                 } else {
195                     qRol.execute(100, snr);
196                 }
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();
201                 int newValue;
202                 int sendValue;
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);
210                     } else {
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);
216                     }
217                 }
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);
223                 } else {
224                     qRol.execute(pp, snr);
225                 }
226             }
227         }
228     }
229
230     /**
231      * Executes the command for screen slats position
232      *
233      * @throws IOException
234      * @throws InterruptedException
235      */
236     private void handleSlatsposCommand(QbusRol qRol, Command command) throws InterruptedException, IOException {
237         String snr = getSN();
238         if (snr != null) {
239             if (command instanceof UpDownType) {
240                 if (command == DOWN) {
241                     qRol.executeSlats(0, snr);
242                 } else {
243                     qRol.executeSlats(100, snr);
244                 }
245             } else if (command instanceof IncreaseDecreaseType) {
246                 int stepValue = ((Number) getConfig().get(CONFIG_STEP_VALUE)).intValue();
247                 Integer currentValue = qRol.getState();
248                 int newValue;
249                 int sendValue;
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);
257                     } else {
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);
263                     }
264                 }
265             } else if (command instanceof PercentType) {
266                 int percentToInt = ((PercentType) command).intValue();
267                 if (PercentType.ZERO.equals(command)) {
268                     qRol.executeSlats(0, snr);
269                 } else {
270                     qRol.executeSlats(percentToInt, snr);
271                 }
272             }
273         }
274     }
275
276     /**
277      * Method to update state of channel, called from Qbus Screen/Store.
278      */
279     public void handleStateUpdate(QbusRol qRol) {
280         Integer rolState = qRol.getState();
281         Integer slatState = qRol.getStateSlats();
282
283         if (rolState != null) {
284             updateState(CHANNEL_ROLLERSHUTTER, new PercentType(rolState));
285         }
286         if (slatState != null) {
287             updateState(CHANNEL_SLATS, new PercentType(slatState));
288         }
289     }
290
291     /**
292      * Returns the serial number of the controller
293      *
294      * @return the serial nr
295      */
296     public @Nullable String getSN() {
297         return sn;
298     }
299
300     /**
301      * Sets the serial number of the controller
302      */
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);
308             return;
309         }
310         sn = qBridgeHandler.getSn();
311     }
312
313     /**
314      * Read the configuration
315      */
316     protected synchronized void readConfig() {
317         rolConfig = getConfig().as(QbusThingsConfig.class);
318     }
319
320     /**
321      * Returns the Id from the configuration
322      *
323      * @return outputId
324      */
325     public @Nullable Integer getId() {
326         QbusThingsConfig localConfig = rolConfig;
327         if (localConfig != null) {
328             return localConfig.rolId;
329         } else {
330             return null;
331         }
332     }
333 }