]> git.basschouten.com Git - openhab-addons.git/blob
3daa280be1b769ad0f7f6dd1ca41e76910c39199
[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.types.RefreshType.REFRESH;
17
18 import java.io.IOException;
19 import java.util.Map;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.qbus.internal.QbusBridgeHandler;
24 import org.openhab.binding.qbus.internal.protocol.QbusCommunication;
25 import org.openhab.binding.qbus.internal.protocol.QbusDimmer;
26 import org.openhab.core.library.types.IncreaseDecreaseType;
27 import org.openhab.core.library.types.OnOffType;
28 import org.openhab.core.library.types.PercentType;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingStatusDetail;
33 import org.openhab.core.types.Command;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * The {@link QbusDimmerHandler} is responsible for handling the dimmable outputs of Qbus
39  *
40  * @author Koen Schockaert - Initial Contribution
41  */
42
43 @NonNullByDefault
44 public class QbusDimmerHandler extends QbusGlobalHandler {
45
46     private final Logger logger = LoggerFactory.getLogger(QbusDimmerHandler.class);
47
48     protected @Nullable QbusThingsConfig dimmerConfig = new QbusThingsConfig();
49
50     private @Nullable Integer dimmerId;
51
52     private @Nullable String sn;
53
54     public QbusDimmerHandler(Thing thing) {
55         super(thing);
56     }
57
58     /**
59      * Main initialization
60      */
61     @Override
62     public void initialize() {
63         readConfig();
64
65         this.dimmerId = getId();
66
67         setSN();
68
69         scheduler.submit(() -> {
70             QbusCommunication controllerComm;
71
72             if (this.dimmerId != null) {
73                 controllerComm = getCommunication("Dimmer", this.dimmerId);
74             } else {
75                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "ID for DIMMER no set!  " + this.dimmerId);
76                 return;
77             }
78
79             if (controllerComm == null) {
80                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
81                         "ID for DIMMER not known in controller " + this.dimmerId);
82                 return;
83             }
84
85             Map<Integer, QbusDimmer> dimmerCommLocal = controllerComm.getDimmer();
86
87             QbusDimmer outputLocal = dimmerCommLocal.get(this.dimmerId);
88
89             if (outputLocal == null) {
90                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
91                         "Bridge could not initialize DIMMER ID " + this.dimmerId);
92                 return;
93             }
94
95             outputLocal.setThingHandler(this);
96             handleStateUpdate(outputLocal);
97
98             QbusBridgeHandler qBridgeHandler = getBridgeHandler("Dimmer", this.dimmerId);
99
100             if (qBridgeHandler != null) {
101                 if (qBridgeHandler.getStatus() == ThingStatus.ONLINE) {
102                     updateStatus(ThingStatus.ONLINE);
103                 } else {
104                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
105                             "Bridge offline for DIMMER ID " + this.dimmerId);
106                 }
107             }
108         });
109     }
110
111     /**
112      * Handle the status update from the dimmer
113      */
114     @Override
115     public void handleCommand(ChannelUID channelUID, Command command) {
116         QbusCommunication qComm = getCommunication("Dimmer", this.dimmerId);
117
118         if (qComm == null) {
119             thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
120                     "ID for DIMMER not known in controller " + this.dimmerId);
121             return;
122         } else {
123             Map<Integer, QbusDimmer> dimmerComm = qComm.getDimmer();
124
125             QbusDimmer qDimmer = dimmerComm.get(this.dimmerId);
126
127             if (qDimmer == null) {
128                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
129                         "ID for DIMMER not known in controller " + this.dimmerId);
130                 return;
131             } else {
132                 scheduler.submit(() -> {
133                     if (!qComm.communicationActive()) {
134                         restartCommunication(qComm, "Dimmer", this.dimmerId);
135                     }
136
137                     if (qComm.communicationActive()) {
138                         if (command == REFRESH) {
139                             handleStateUpdate(qDimmer);
140                             return;
141                         }
142
143                         switch (channelUID.getId()) {
144                             case CHANNEL_SWITCH:
145                                 try {
146                                     handleSwitchCommand(qDimmer, command);
147                                 } catch (IOException e) {
148                                     String message = e.getMessage();
149                                     logger.warn("Error on executing Switch for dimmer ID {}. IOException: {}",
150                                             this.dimmerId, message);
151                                 } catch (InterruptedException e) {
152                                     String message = e.getMessage();
153                                     logger.warn("Error on executing Switch for dimmer ID {}. Interruptedexception {}",
154                                             this.dimmerId, message);
155                                 }
156                                 break;
157
158                             case CHANNEL_BRIGHTNESS:
159                                 try {
160                                     handleBrightnessCommand(qDimmer, command);
161                                 } catch (IOException e) {
162                                     String message = e.getMessage();
163                                     logger.warn("Error on executing Brightness for dimmer ID {}. IOException: {}",
164                                             this.dimmerId, message);
165                                 } catch (InterruptedException e) {
166                                     String message = e.getMessage();
167                                     logger.warn(
168                                             "Error on executing Brightness for dimmer ID {}. Interruptedexception {}",
169                                             this.dimmerId, message);
170                                 }
171                                 break;
172
173                             default:
174                                 thingOffline(ThingStatusDetail.COMMUNICATION_ERROR,
175                                         "Unknown Channel " + channelUID.getId());
176                         }
177                     }
178                 });
179             }
180         }
181     }
182
183     /**
184      * Executes the switch command
185      *
186      * @throws IOException
187      * @throws InterruptedException
188      */
189     private void handleSwitchCommand(QbusDimmer qDimmer, Command command) throws InterruptedException, IOException {
190         if (command instanceof OnOffType) {
191             String snr = getSN();
192             if (snr != null) {
193                 if (command == OnOffType.OFF) {
194                     qDimmer.execute(0, snr);
195                 } else {
196                     qDimmer.execute(1000, snr);
197                 }
198             } else {
199                 thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
200                         "No serial number configured for DIMMER " + this.dimmerId);
201             }
202         }
203     }
204
205     /**
206      * Executes the brightness command
207      *
208      * @throws IOException
209      * @throws InterruptedException
210      */
211     private void handleBrightnessCommand(QbusDimmer qDimmer, Command command) throws InterruptedException, IOException {
212         String snr = getSN();
213
214         if (snr == null) {
215             thingOffline(ThingStatusDetail.CONFIGURATION_ERROR,
216                     "No serial number configured for DIMMER " + this.dimmerId);
217             return;
218         } else {
219             if (command instanceof OnOffType) {
220                 if (command == OnOffType.OFF) {
221                     qDimmer.execute(0, snr);
222                 } else {
223                     qDimmer.execute(100, snr);
224                 }
225             } else if (command instanceof IncreaseDecreaseType) {
226                 int stepValue = ((Number) getConfig().get(CONFIG_STEP_VALUE)).intValue();
227                 Integer currentValue = qDimmer.getState();
228                 Integer newValue;
229                 Integer sendvalue;
230                 if (currentValue != null) {
231                     if (command == IncreaseDecreaseType.INCREASE) {
232                         newValue = currentValue + stepValue;
233                         // round down to step multiple
234                         newValue = newValue - newValue % stepValue;
235                         sendvalue = newValue > 100 ? 100 : newValue;
236                         qDimmer.execute(sendvalue, snr);
237                     } else {
238                         newValue = currentValue - stepValue;
239                         // round up to step multiple
240                         newValue = newValue + newValue % stepValue;
241                         sendvalue = newValue < 0 ? 0 : newValue;
242                         qDimmer.execute(sendvalue, snr);
243                     }
244                 }
245             } else if (command instanceof PercentType percentCommand) {
246                 int percentToInt = percentCommand.intValue();
247                 if (PercentType.ZERO.equals(command)) {
248                     qDimmer.execute(0, snr);
249                 } else {
250                     qDimmer.execute(percentToInt, snr);
251                 }
252             }
253         }
254     }
255
256     /**
257      * Method to update state of channel, called from Qbus Dimmer.
258      *
259      * @param qDimmer
260      */
261     public void handleStateUpdate(QbusDimmer qDimmer) {
262         Integer dimmerState = qDimmer.getState();
263         if (dimmerState != null) {
264             updateState(CHANNEL_BRIGHTNESS, new PercentType(dimmerState));
265         }
266     }
267
268     /**
269      * Returns the serial number of the controller
270      *
271      * @return the serial number
272      */
273     public @Nullable String getSN() {
274         return sn;
275     }
276
277     /**
278      * Sets the serial number of the controller
279      */
280     public void setSN() {
281         QbusBridgeHandler qBridgeHandler = getBridgeHandler("Dimmer", this.dimmerId);
282         if (qBridgeHandler == null) {
283             thingOffline(ThingStatusDetail.COMMUNICATION_ERROR,
284                     "No communication with Qbus Bridge for DIMMER " + this.dimmerId);
285             return;
286         }
287         this.sn = qBridgeHandler.getSn();
288     }
289
290     /**
291      * Read the configuration
292      */
293     protected synchronized void readConfig() {
294         dimmerConfig = getConfig().as(QbusThingsConfig.class);
295     }
296
297     /**
298      * Returns the Id from the configuration
299      *
300      * @return outputId
301      */
302     public @Nullable Integer getId() {
303         QbusThingsConfig localConfig = dimmerConfig;
304         if (localConfig != null) {
305             return localConfig.dimmerId;
306         } else {
307             return null;
308         }
309     }
310 }