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