]> git.basschouten.com Git - openhab-addons.git/blob
03fc20a9a0aeeeb7a46d6f326b1cc2aaf3a5ce80
[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.tradfri.internal.handler;
14
15 import static org.openhab.binding.tradfri.internal.TradfriBindingConstants.*;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.tradfri.internal.TradfriCoapClient;
20 import org.openhab.binding.tradfri.internal.model.TradfriLightData;
21 import org.openhab.core.library.types.HSBType;
22 import org.openhab.core.library.types.IncreaseDecreaseType;
23 import org.openhab.core.library.types.OnOffType;
24 import org.openhab.core.library.types.PercentType;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.types.Command;
29 import org.openhab.core.types.RefreshType;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.gson.JsonElement;
34
35 /**
36  * The {@link TradfriLightHandler} is responsible for handling commands for individual lights.
37  *
38  * @author Kai Kreuzer - Initial contribution
39  * @author Holger Reichert - Support for color bulbs
40  * @author Christoph Weitkamp - Restructuring and refactoring of the binding
41  */
42 @NonNullByDefault
43 public class TradfriLightHandler extends TradfriThingHandler {
44
45     private final Logger logger = LoggerFactory.getLogger(TradfriLightHandler.class);
46
47     // step size for increase/decrease commands
48     private static final int STEP = 10;
49
50     // keeps track of the current state for handling of increase/decrease
51     private @Nullable TradfriLightData state;
52
53     public TradfriLightHandler(Thing thing) {
54         super(thing);
55     }
56
57     @Override
58     public void onUpdate(JsonElement data) {
59         if (active && !(data.isJsonNull())) {
60             TradfriLightData state = new TradfriLightData(data);
61             updateStatus(state.getReachabilityStatus() ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
62
63             if (!state.getOnOffState()) {
64                 logger.debug("Setting state to OFF");
65                 updateState(CHANNEL_BRIGHTNESS, PercentType.ZERO);
66                 if (lightHasColorSupport()) {
67                     updateState(CHANNEL_COLOR, HSBType.BLACK);
68                 }
69                 // if we are turned off, we do not set any brightness value
70                 return;
71             }
72
73             PercentType dimmer = state.getBrightness();
74             if (dimmer != null && !lightHasColorSupport()) { // color lights do not have brightness channel
75                 updateState(CHANNEL_BRIGHTNESS, dimmer);
76             }
77
78             PercentType colorTemp = state.getColorTemperature();
79             if (colorTemp != null) {
80                 updateState(CHANNEL_COLOR_TEMPERATURE, colorTemp);
81             }
82
83             HSBType color = null;
84             if (lightHasColorSupport()) {
85                 color = state.getColor();
86                 if (color != null) {
87                     updateState(CHANNEL_COLOR, color);
88                 }
89             }
90
91             updateDeviceProperties(state);
92
93             this.state = state;
94
95             logger.debug(
96                     "Updating thing for lightId {} to state {dimmer: {}, colorTemp: {}, color: {}, firmwareVersion: {}, modelId: {}, vendor: {}}",
97                     state.getDeviceId(), dimmer, colorTemp, color, state.getFirmwareVersion(), state.getModelId(),
98                     state.getVendor());
99         }
100     }
101
102     private void setBrightness(PercentType percent) {
103         TradfriLightData data = new TradfriLightData();
104         data.setBrightness(percent).setTransitionTime(DEFAULT_DIMMER_TRANSITION_TIME);
105         set(data.getJsonString());
106     }
107
108     private void setState(OnOffType onOff) {
109         TradfriLightData data = new TradfriLightData();
110         data.setOnOffState(onOff == OnOffType.ON);
111         set(data.getJsonString());
112     }
113
114     private void setColorTemperature(PercentType percent) {
115         TradfriLightData data = new TradfriLightData();
116         data.setColorTemperature(percent).setTransitionTime(DEFAULT_DIMMER_TRANSITION_TIME);
117         set(data.getJsonString());
118     }
119
120     private void setColor(HSBType hsb) {
121         TradfriLightData data = new TradfriLightData();
122         data.setColor(hsb).setTransitionTime(DEFAULT_DIMMER_TRANSITION_TIME);
123         set(data.getJsonString());
124     }
125
126     @Override
127     public void handleCommand(ChannelUID channelUID, Command command) {
128         if (active) {
129             if (command instanceof RefreshType) {
130                 TradfriCoapClient coapClient = this.coapClient;
131                 if (coapClient != null) {
132                     logger.debug("Refreshing channel {}", channelUID);
133                     coapClient.asyncGet(this);
134                 } else {
135                     logger.debug("coapClient is null!");
136                 }
137                 return;
138             }
139
140             switch (channelUID.getId()) {
141                 case CHANNEL_BRIGHTNESS:
142                     handleBrightnessCommand(command);
143                     break;
144                 case CHANNEL_COLOR_TEMPERATURE:
145                     handleColorTemperatureCommand(command);
146                     break;
147                 case CHANNEL_COLOR:
148                     handleColorCommand(command);
149                     break;
150                 default:
151                     logger.error("Unknown channel UID {}", channelUID);
152             }
153         }
154     }
155
156     private void handleBrightnessCommand(Command command) {
157         if (command instanceof PercentType percentCommand) {
158             setBrightness(percentCommand);
159         } else if (command instanceof OnOffType onOffCommand) {
160             setState(onOffCommand);
161         } else if (command instanceof IncreaseDecreaseType) {
162             final TradfriLightData state = this.state;
163             if (state != null && state.getBrightness() != null) {
164                 @SuppressWarnings("null")
165                 int current = state.getBrightness().intValue();
166                 if (IncreaseDecreaseType.INCREASE.equals(command)) {
167                     setBrightness(new PercentType(Math.min(current + STEP, PercentType.HUNDRED.intValue())));
168                 } else {
169                     setBrightness(new PercentType(Math.max(current - STEP, PercentType.ZERO.intValue())));
170                 }
171             } else {
172                 logger.debug("Cannot handle inc/dec as current state is not known.");
173             }
174         } else {
175             logger.debug("Cannot handle command {} for channel {}", command, CHANNEL_BRIGHTNESS);
176         }
177     }
178
179     private void handleColorTemperatureCommand(Command command) {
180         if (command instanceof PercentType percentCommand) {
181             setColorTemperature(percentCommand);
182         } else if (command instanceof IncreaseDecreaseType) {
183             final TradfriLightData state = this.state;
184             if (state != null && state.getColorTemperature() != null) {
185                 @SuppressWarnings("null")
186                 int current = state.getColorTemperature().intValue();
187                 if (IncreaseDecreaseType.INCREASE.equals(command)) {
188                     setColorTemperature(new PercentType(Math.min(current + STEP, PercentType.HUNDRED.intValue())));
189                 } else {
190                     setColorTemperature(new PercentType(Math.max(current - STEP, PercentType.ZERO.intValue())));
191                 }
192             } else {
193                 logger.debug("Cannot handle inc/dec as current state is not known.");
194             }
195         } else {
196             logger.debug("Can't handle command {} on channel {}", command, CHANNEL_COLOR_TEMPERATURE);
197         }
198     }
199
200     private void handleColorCommand(Command command) {
201         if (command instanceof HSBType hsbCommand) {
202             setColor(hsbCommand);
203             setBrightness(hsbCommand.getBrightness());
204         } else if (command instanceof OnOffType onOffCommand) {
205             setState(onOffCommand);
206         } else if (command instanceof PercentType percentCommand) {
207             setBrightness(percentCommand);
208         } else if (command instanceof IncreaseDecreaseType) {
209             final TradfriLightData state = this.state;
210             // increase or decrease only the brightness, but keep color
211             if (state != null && state.getBrightness() != null) {
212                 @SuppressWarnings("null")
213                 int current = state.getBrightness().intValue();
214                 if (IncreaseDecreaseType.INCREASE.equals(command)) {
215                     setBrightness(new PercentType(Math.min(current + STEP, PercentType.HUNDRED.intValue())));
216                 } else {
217                     setBrightness(new PercentType(Math.max(current - STEP, PercentType.ZERO.intValue())));
218                 }
219             } else {
220                 logger.debug("Cannot handle inc/dec for color as current brightness is not known.");
221             }
222         } else {
223             logger.debug("Can't handle command {} on channel {}", command, CHANNEL_COLOR);
224         }
225     }
226
227     /**
228      * Checks if this light supports full color.
229      *
230      * @return true if the light supports full color
231      */
232     private boolean lightHasColorSupport() {
233         return thing.getThingTypeUID().getId().equals(THING_TYPE_COLOR_LIGHT.getId());
234     }
235 }