[hue] Added support for different color temperature capabilities and added Channel to set value in Kelvin (#9939)
* Added support for color temperature capabilities and set value in Kelvin * Use system default channel type Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>pull/9977/head
parent
7ce7228a85
commit
7141a091ff
|
@ -158,28 +158,29 @@ The group type also have an optional configuration value to specify the fade tim
|
|||
|
||||
The devices support some of the following channels:
|
||||
|
||||
| Channel Type ID | Item Type | Description | Thing types supporting this channel |
|
||||
|-------------------|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------|
|
||||
| switch | Switch | This channel supports switching the device on and off. | 0000, 0010, group |
|
||||
| color | Color | This channel supports full color control with hue, saturation and brightness values. | 0200, 0210, group |
|
||||
| brightness | Dimmer | This channel supports adjusting the brightness value. Note that this is not available, if the color channel is supported. | 0100, 0110, 0220, group |
|
||||
| color_temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | 0210, 0220, group |
|
||||
| alert | String | This channel supports displaying alerts by flashing the bulb either once or multiple times. Valid values are: NONE, SELECT and LSELECT. | 0000, 0100, 0200, 0210, 0220, group |
|
||||
| effect | Switch | This channel supports color looping. | 0200, 0210, 0220 |
|
||||
| dimmer_switch | Number | This channel shows which button was last pressed on the dimmer switch. | 0820 |
|
||||
| illuminance | Number:Illuminance | This channel shows the current illuminance measured by the sensor. | 0106 |
|
||||
| light_level | Number | This channel shows the current light level measured by the sensor. **Advanced** | 0106 |
|
||||
| dark | Switch | This channel indicates whether the light level is below the darkness threshold or not. | 0106 |
|
||||
| daylight | Switch | This channel indicates whether the light level is below the daylight threshold or not. | 0106 |
|
||||
| presence | Switch | This channel indicates whether a motion is detected by the sensor or not. | 0107 |
|
||||
| enabled | Switch | This channel activated or deactivates the sensor | 0107 |
|
||||
| temperature | Number:Temperature | This channel shows the current temperature measured by the sensor. | 0302 |
|
||||
| flag | Switch | This channel save flag state for a CLIP sensor. | 0850 |
|
||||
| status | Number | This channel save status state for a CLIP sensor. | 0840 |
|
||||
| last_updated | DateTime | This channel the date and time when the sensor was last updated. | 0820, 0830, 0840, 0850, 0106, 0107, 0302 |
|
||||
| battery_level | Number | This channel shows the battery level. | 0820, 0106, 0107, 0302 |
|
||||
| battery_low | Switch | This channel indicates whether the battery is low or not. | 0820, 0106, 0107, 0302 |
|
||||
| scene | String | This channel activates the scene with the given ID String. The ID String of each scene is assigned by the Hue bridge. | bridge, group |
|
||||
| Channel Type ID | Item Type | Description | Thing types supporting this channel |
|
||||
|-----------------------|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------|
|
||||
| switch | Switch | This channel supports switching the device on and off. | 0000, 0010, group |
|
||||
| color | Color | This channel supports full color control with hue, saturation and brightness values. | 0200, 0210, group |
|
||||
| brightness | Dimmer | This channel supports adjusting the brightness value. Note that this is not available, if the color channel is supported. | 0100, 0110, 0220, group |
|
||||
| color_temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | 0210, 0220, group |
|
||||
| color_temperature_abs | Number | This channel supports adjusting the color temperature in Kelvin. **Advanced** | 0210, 0220, group |
|
||||
| alert | String | This channel supports displaying alerts by flashing the bulb either once or multiple times. Valid values are: NONE, SELECT and LSELECT. | 0000, 0100, 0200, 0210, 0220, group |
|
||||
| effect | Switch | This channel supports color looping. | 0200, 0210, 0220 |
|
||||
| dimmer_switch | Number | This channel shows which button was last pressed on the dimmer switch. | 0820 |
|
||||
| illuminance | Number:Illuminance | This channel shows the current illuminance measured by the sensor. | 0106 |
|
||||
| light_level | Number | This channel shows the current light level measured by the sensor. **Advanced** | 0106 |
|
||||
| dark | Switch | This channel indicates whether the light level is below the darkness threshold or not. | 0106 |
|
||||
| daylight | Switch | This channel indicates whether the light level is below the daylight threshold or not. | 0106 |
|
||||
| presence | Switch | This channel indicates whether a motion is detected by the sensor or not. | 0107 |
|
||||
| enabled | Switch | This channel activated or deactivates the sensor | 0107 |
|
||||
| temperature | Number:Temperature | This channel shows the current temperature measured by the sensor. | 0302 |
|
||||
| flag | Switch | This channel save flag state for a CLIP sensor. | 0850 |
|
||||
| status | Number | This channel save status state for a CLIP sensor. | 0840 |
|
||||
| last_updated | DateTime | This channel the date and time when the sensor was last updated. | 0820, 0830, 0840, 0850, 0106, 0107, 0302 |
|
||||
| battery_level | Number | This channel shows the battery level. | 0820, 0106, 0107, 0302 |
|
||||
| battery_low | Switch | This channel indicates whether the battery is low or not. | 0820, 0106, 0107, 0302 |
|
||||
| scene | String | This channel activates the scene with the given ID String. The ID String of each scene is assigned by the Hue bridge. | bridge, group |
|
||||
|
||||
To load a hue scene inside a rule for example, the ID of the scene will be required.
|
||||
You can list all the scene IDs with the following console commands: `hue <bridgeUID> scenes` and `hue <groupThingUID> scenes`.
|
||||
|
|
|
@ -17,6 +17,8 @@ import java.time.Duration;
|
|||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.hue.internal.dto.Capabilities;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
|
@ -33,6 +35,7 @@ public class FullLight extends FullHueObject {
|
|||
public static final Type GSON_TYPE = new TypeToken<Map<String, FullLight>>() {
|
||||
}.getType();
|
||||
|
||||
public @Nullable Capabilities capabilities;
|
||||
private @NonNullByDefault({}) State state;
|
||||
private final long fadetime = 400; // milliseconds
|
||||
|
||||
|
|
|
@ -93,7 +93,8 @@ public class HttpClient {
|
|||
synchronized (commandsQueue) {
|
||||
if (commandsQueue.isEmpty()) {
|
||||
commandsQueue.offer(asyncPutParameters);
|
||||
if (job == null || job.isDone()) {
|
||||
Future<?> localJob = job;
|
||||
if (localJob == null || localJob.isDone()) {
|
||||
job = scheduler.submit(this::executeCommands);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -58,6 +58,7 @@ public class HueBindingConstants {
|
|||
|
||||
// List all channels
|
||||
public static final String CHANNEL_COLORTEMPERATURE = "color_temperature";
|
||||
public static final String CHANNEL_COLORTEMPERATURE_ABS = "color_temperature_abs";
|
||||
public static final String CHANNEL_COLOR = "color";
|
||||
public static final String CHANNEL_BRIGHTNESS = "brightness";
|
||||
public static final String CHANNEL_ALERT = "alert";
|
||||
|
|
|
@ -144,7 +144,7 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory {
|
|||
if (HueBridgeHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
return new HueBridgeHandler((Bridge) thing, stateOptionProvider);
|
||||
} else if (HueLightHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
return new HueLightHandler(thing);
|
||||
return new HueLightHandler(thing, stateOptionProvider);
|
||||
} else if (DimmerSwitchHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
return new DimmerSwitchHandler(thing);
|
||||
} else if (TapSwitchHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
|
|
|
@ -27,7 +27,7 @@ public class State {
|
|||
int hue;
|
||||
int sat;
|
||||
private float[] xy;
|
||||
private int ct;
|
||||
int ct;
|
||||
private String alert;
|
||||
private String effect;
|
||||
String colormode;
|
||||
|
|
|
@ -14,6 +14,7 @@ package org.openhab.binding.hue.internal;
|
|||
|
||||
import org.openhab.binding.hue.internal.State.AlertMode;
|
||||
import org.openhab.binding.hue.internal.State.Effect;
|
||||
import org.openhab.binding.hue.internal.dto.ColorTemperature;
|
||||
|
||||
/**
|
||||
* Collection of updates to the state of a light.
|
||||
|
@ -139,12 +140,13 @@ public class StateUpdate extends ConfigUpdate {
|
|||
/**
|
||||
* Switch to CT color mode and set color temperature in mired.
|
||||
*
|
||||
* @param colorTemperature color temperature [153..500]
|
||||
* @param colorTemperature color temperature
|
||||
* @return this object for chaining calls
|
||||
*/
|
||||
public StateUpdate setColorTemperature(int colorTemperature) {
|
||||
if (colorTemperature < 153 || colorTemperature > 500) {
|
||||
throw new IllegalArgumentException("Color temperature out of range");
|
||||
public StateUpdate setColorTemperature(int colorTemperature, ColorTemperature capabilities) {
|
||||
if (colorTemperature < capabilities.min || colorTemperature > capabilities.max) {
|
||||
throw new IllegalArgumentException(String.format("Color temperature %d is out of range [%d..%d]",
|
||||
colorTemperature, capabilities.min, capabilities.max));
|
||||
}
|
||||
|
||||
commands.add(new Command("ct", colorTemperature));
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hue.internal.dto;
|
||||
|
||||
/**
|
||||
* Collection of capabilities for lights.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class Capabilities {
|
||||
public Control control;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hue.internal.dto;
|
||||
|
||||
/**
|
||||
* Collection of color temperature capabilities to control lights.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class ColorTemperature {
|
||||
public int max = 500;
|
||||
public int min = 153;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.hue.internal.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Collection of capabilities to control lights.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class Control {
|
||||
public @Nullable ColorTemperature ct;
|
||||
}
|
|
@ -15,8 +15,6 @@ package org.openhab.binding.hue.internal.handler;
|
|||
import static org.openhab.binding.hue.internal.HueBindingConstants.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
@ -31,6 +29,8 @@ import org.openhab.binding.hue.internal.Scene;
|
|||
import org.openhab.binding.hue.internal.State;
|
||||
import org.openhab.binding.hue.internal.State.ColorMode;
|
||||
import org.openhab.binding.hue.internal.StateUpdate;
|
||||
import org.openhab.binding.hue.internal.dto.ColorTemperature;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -59,7 +59,7 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
@NonNullByDefault
|
||||
public class HueGroupHandler extends BaseThingHandler implements GroupStatusListener {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_GROUP);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_GROUP);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HueGroupHandler.class);
|
||||
private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
|
||||
|
@ -69,6 +69,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
private @Nullable Integer lastSentColorTemp;
|
||||
private @Nullable Integer lastSentBrightness;
|
||||
|
||||
private ColorTemperature colorTemperatureCapabilties = new ColorTemperature();
|
||||
private long defaultFadeTime = 400;
|
||||
|
||||
private @Nullable HueClient hueClient;
|
||||
|
@ -76,7 +77,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
private @Nullable ScheduledFuture<?> scheduledFuture;
|
||||
private @Nullable FullGroup lastFullGroup;
|
||||
|
||||
private List<String> consoleScenesList = new ArrayList<>();
|
||||
private List<String> consoleScenesList = List.of();
|
||||
|
||||
public HueGroupHandler(Thing thing, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
|
||||
super(thing);
|
||||
|
@ -201,7 +202,8 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
break;
|
||||
case CHANNEL_COLORTEMPERATURE:
|
||||
if (command instanceof PercentType) {
|
||||
newState = LightStateConverter.toColorTemperatureLightState((PercentType) command);
|
||||
newState = LightStateConverter.toColorTemperatureLightStateFromPercentType((PercentType) command,
|
||||
colorTemperatureCapabilties);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
} else if (command instanceof OnOffType) {
|
||||
newState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
|
@ -212,6 +214,13 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_COLORTEMPERATURE_ABS:
|
||||
if (command instanceof DecimalType) {
|
||||
newState = LightStateConverter.toColorTemperatureLightState((DecimalType) command,
|
||||
colorTemperatureCapabilties);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_BRIGHTNESS:
|
||||
if (command instanceof PercentType) {
|
||||
newState = LightStateConverter.toBrightnessLightState((PercentType) command);
|
||||
|
@ -228,7 +237,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
if (newState != null && lastColorTemp != null) {
|
||||
// make sure that the light also has the latest color temp
|
||||
// this might not have been yet set in the light, if it was off
|
||||
newState.setColorTemperature(lastColorTemp);
|
||||
newState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
|
@ -240,7 +249,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
if (newState != null && lastColorTemp != null) {
|
||||
// make sure that the light also has the latest color temp
|
||||
// this might not have been yet set in the light, if it was off
|
||||
newState.setColorTemperature(lastColorTemp);
|
||||
newState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
|
@ -296,8 +305,9 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
StateUpdate stateUpdate = null;
|
||||
Integer currentColorTemp = getCurrentColorTemp(group.getState());
|
||||
if (currentColorTemp != null) {
|
||||
int newColorTemp = LightStateConverter.toAdjustedColorTemp(command, currentColorTemp);
|
||||
stateUpdate = new StateUpdate().setColorTemperature(newColorTemp);
|
||||
int newColorTemp = LightStateConverter.toAdjustedColorTemp(command, currentColorTemp,
|
||||
colorTemperatureCapabilties);
|
||||
stateUpdate = new StateUpdate().setColorTemperature(newColorTemp, colorTemperatureCapabilties);
|
||||
}
|
||||
return stateUpdate;
|
||||
}
|
||||
|
@ -380,25 +390,27 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
|
||||
HSBType hsbType = LightStateConverter.toHSBType(state);
|
||||
if (!state.isOn()) {
|
||||
hsbType = new HSBType(hsbType.getHue(), hsbType.getSaturation(), new PercentType(0));
|
||||
hsbType = new HSBType(hsbType.getHue(), hsbType.getSaturation(), PercentType.ZERO);
|
||||
}
|
||||
updateState(CHANNEL_COLOR, hsbType);
|
||||
|
||||
ColorMode colorMode = state.getColorMode();
|
||||
if (ColorMode.CT.equals(colorMode)) {
|
||||
PercentType colorTempPercentType = LightStateConverter.toColorTemperaturePercentType(state);
|
||||
updateState(CHANNEL_COLORTEMPERATURE, colorTempPercentType);
|
||||
updateState(CHANNEL_COLORTEMPERATURE,
|
||||
LightStateConverter.toColorTemperaturePercentType(state, colorTemperatureCapabilties));
|
||||
updateState(CHANNEL_COLORTEMPERATURE_ABS, LightStateConverter.toColorTemperature(state));
|
||||
} else {
|
||||
updateState(CHANNEL_COLORTEMPERATURE, UnDefType.NULL);
|
||||
updateState(CHANNEL_COLORTEMPERATURE, UnDefType.UNDEF);
|
||||
updateState(CHANNEL_COLORTEMPERATURE_ABS, UnDefType.UNDEF);
|
||||
}
|
||||
|
||||
PercentType brightnessPercentType = LightStateConverter.toBrightnessPercentType(state);
|
||||
if (!state.isOn()) {
|
||||
brightnessPercentType = new PercentType(0);
|
||||
brightnessPercentType = PercentType.ZERO;
|
||||
}
|
||||
updateState(CHANNEL_BRIGHTNESS, brightnessPercentType);
|
||||
|
||||
updateState(CHANNEL_SWITCH, state.isOn() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(CHANNEL_SWITCH, OnOffType.from(state.isOn()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -423,8 +435,8 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
|||
*/
|
||||
@Override
|
||||
public void onScenesUpdated(List<Scene> updatedScenes) {
|
||||
List<StateOption> stateOptions = Collections.emptyList();
|
||||
consoleScenesList = new ArrayList<>();
|
||||
List<StateOption> stateOptions = List.of();
|
||||
consoleScenesList = List.of();
|
||||
HueClient handler = getHueClient();
|
||||
if (handler != null) {
|
||||
FullGroup group = handler.getGroupById(groupId);
|
||||
|
|
|
@ -16,18 +16,13 @@ import static org.openhab.binding.hue.internal.HueBindingConstants.*;
|
|||
import static org.openhab.core.thing.Thing.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
@ -36,6 +31,9 @@ import org.openhab.binding.hue.internal.State;
|
|||
import org.openhab.binding.hue.internal.State.ColorMode;
|
||||
import org.openhab.binding.hue.internal.StateUpdate;
|
||||
import org.openhab.binding.hue.internal.action.LightActions;
|
||||
import org.openhab.binding.hue.internal.dto.Capabilities;
|
||||
import org.openhab.binding.hue.internal.dto.ColorTemperature;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -52,6 +50,8 @@ import org.openhab.core.thing.binding.BaseThingHandler;
|
|||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.StateDescription;
|
||||
import org.openhab.core.types.StateDescriptionFragmentBuilder;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -77,24 +77,20 @@ import org.slf4j.LoggerFactory;
|
|||
@NonNullByDefault
|
||||
public class HueLightHandler extends BaseThingHandler implements LightStatusListener {
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Stream.of(THING_TYPE_COLOR_LIGHT,
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_COLOR_LIGHT,
|
||||
THING_TYPE_COLOR_TEMPERATURE_LIGHT, THING_TYPE_DIMMABLE_LIGHT, THING_TYPE_EXTENDED_COLOR_LIGHT,
|
||||
THING_TYPE_ON_OFF_LIGHT, THING_TYPE_ON_OFF_PLUG, THING_TYPE_DIMMABLE_PLUG).collect(Collectors.toSet());
|
||||
THING_TYPE_ON_OFF_LIGHT, THING_TYPE_ON_OFF_PLUG, THING_TYPE_DIMMABLE_PLUG);
|
||||
|
||||
// @formatter:off
|
||||
private static final Map<String, List<String>> VENDOR_MODEL_MAP = Stream.of(
|
||||
new SimpleEntry<>("Philips",
|
||||
Arrays.asList("LCT001", "LCT002", "LCT003", "LCT007", "LLC001", "LLC006", "LLC007", "LLC010",
|
||||
"LLC011", "LLC012", "LLC013", "LLC020", "LST001", "LST002", "LWB004", "LWB006", "LWB007",
|
||||
"LWL001")),
|
||||
new SimpleEntry<>("OSRAM",
|
||||
Arrays.asList("Classic_A60_RGBW", "PAR16_50_TW", "Surface_Light_TW", "Plug_01")))
|
||||
.collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()));
|
||||
// @formatter:on
|
||||
private static final Map<String, List<String>> VENDOR_MODEL_MAP = Map.of( //
|
||||
"Philips", List.of("LCT001", "LCT002", "LCT003", "LCT007", "LLC001", "LLC006", "LLC007", "LLC010", //
|
||||
"LLC011", "LLC012", "LLC013", "LLC020", "LST001", "LST002", "LWB004", "LWB006", "LWB007", //
|
||||
"LWL001"),
|
||||
"OSRAM", List.of("Classic_A60_RGBW", "PAR16_50_TW", "Surface_Light_TW", "Plug_01"));
|
||||
|
||||
private static final String OSRAM_PAR16_50_TW_MODEL_ID = "PAR16_50_TW";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HueLightHandler.class);
|
||||
private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
|
||||
|
||||
private @NonNullByDefault({}) String lightId;
|
||||
|
||||
|
@ -108,14 +104,17 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
private boolean isOsramPar16 = false;
|
||||
|
||||
private boolean propertiesInitializedSuccessfully = false;
|
||||
private boolean capabilitiesInitializedSuccessfully = false;
|
||||
private ColorTemperature colorTemperatureCapabilties = new ColorTemperature();
|
||||
private long defaultFadeTime = 400;
|
||||
|
||||
private @Nullable HueClient hueClient;
|
||||
|
||||
private @Nullable ScheduledFuture<?> scheduledFuture;
|
||||
|
||||
public HueLightHandler(Thing hueLight) {
|
||||
public HueLightHandler(Thing hueLight, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
|
||||
super(hueLight);
|
||||
this.stateDescriptionOptionProvider = stateDescriptionOptionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -145,7 +144,9 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
HueClient bridgeHandler = getHueClient();
|
||||
if (bridgeHandler != null) {
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
initializeProperties(bridgeHandler.getLightById(lightId));
|
||||
FullLight fullLight = bridgeHandler.getLightById(lightId);
|
||||
initializeProperties(fullLight);
|
||||
initializeCapabilities(fullLight);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
|
@ -187,6 +188,33 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
}
|
||||
}
|
||||
|
||||
private void initializeCapabilities(@Nullable FullLight fullLight) {
|
||||
if (!capabilitiesInitializedSuccessfully && fullLight != null) {
|
||||
Capabilities capabilities = fullLight.capabilities;
|
||||
if (capabilities != null) {
|
||||
ColorTemperature ct = capabilities.control.ct;
|
||||
if (ct != null) {
|
||||
colorTemperatureCapabilties = ct;
|
||||
|
||||
// minimum and maximum are inverted due to mired/Kelvin conversion!
|
||||
StateDescription stateDescription = StateDescriptionFragmentBuilder.create()
|
||||
.withMinimum(new BigDecimal(LightStateConverter.miredToKelvin(ct.max))) //
|
||||
.withMaximum(new BigDecimal(LightStateConverter.miredToKelvin(ct.min))) //
|
||||
.withStep(new BigDecimal(100)) //
|
||||
.withPattern("%.0f K") //
|
||||
.build().toStateDescription();
|
||||
if (stateDescription != null) {
|
||||
stateDescriptionOptionProvider.setDescription(
|
||||
new ChannelUID(thing.getUID(), CHANNEL_COLORTEMPERATURE_ABS), stateDescription);
|
||||
} else {
|
||||
logger.warn("Failed to create state description in thing {}", thing.getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
capabilitiesInitializedSuccessfully = true;
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable String getVendor(String modelId) {
|
||||
for (String vendor : VENDOR_MODEL_MAP.keySet()) {
|
||||
if (VENDOR_MODEL_MAP.get(vendor).contains(modelId)) {
|
||||
|
@ -235,7 +263,8 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
switch (channel) {
|
||||
case CHANNEL_COLORTEMPERATURE:
|
||||
if (command instanceof PercentType) {
|
||||
lightState = LightStateConverter.toColorTemperatureLightState((PercentType) command);
|
||||
lightState = LightStateConverter.toColorTemperatureLightStateFromPercentType((PercentType) command,
|
||||
colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
} else if (command instanceof OnOffType) {
|
||||
lightState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
|
@ -248,7 +277,13 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
lightState.setTransitionTime(fadeTime);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case CHANNEL_COLORTEMPERATURE_ABS:
|
||||
if (command instanceof DecimalType) {
|
||||
lightState = LightStateConverter.toColorTemperatureLightState((DecimalType) command,
|
||||
colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_BRIGHTNESS:
|
||||
if (command instanceof PercentType) {
|
||||
|
@ -269,7 +304,7 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
if (lightState != null && lastColorTemp != null) {
|
||||
// make sure that the light also has the latest color temp
|
||||
// this might not have been yet set in the light, if it was off
|
||||
lightState.setColorTemperature(lastColorTemp);
|
||||
lightState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
|
@ -285,7 +320,7 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
if (lightState != null && lastColorTemp != null) {
|
||||
// make sure that the light also has the latest color temp
|
||||
// this might not have been yet set in the light, if it was off
|
||||
lightState.setColorTemperature(lastColorTemp);
|
||||
lightState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
|
@ -365,8 +400,9 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
StateUpdate stateUpdate = null;
|
||||
Integer currentColorTemp = getCurrentColorTemp(light.getState());
|
||||
if (currentColorTemp != null) {
|
||||
int newColorTemp = LightStateConverter.toAdjustedColorTemp(command, currentColorTemp);
|
||||
stateUpdate = new StateUpdate().setColorTemperature(newColorTemp);
|
||||
int newColorTemp = LightStateConverter.toAdjustedColorTemp(command, currentColorTemp,
|
||||
colorTemperatureCapabilties);
|
||||
stateUpdate = new StateUpdate().setColorTemperature(newColorTemp, colorTemperatureCapabilties);
|
||||
}
|
||||
return stateUpdate;
|
||||
}
|
||||
|
@ -482,29 +518,27 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
|
||||
HSBType hsbType = LightStateConverter.toHSBType(state);
|
||||
if (!state.isOn()) {
|
||||
hsbType = new HSBType(hsbType.getHue(), hsbType.getSaturation(), new PercentType(0));
|
||||
hsbType = new HSBType(hsbType.getHue(), hsbType.getSaturation(), PercentType.ZERO);
|
||||
}
|
||||
updateState(CHANNEL_COLOR, hsbType);
|
||||
|
||||
ColorMode colorMode = state.getColorMode();
|
||||
if (ColorMode.CT.equals(colorMode)) {
|
||||
PercentType colorTempPercentType = LightStateConverter.toColorTemperaturePercentType(state);
|
||||
updateState(CHANNEL_COLORTEMPERATURE, colorTempPercentType);
|
||||
updateState(CHANNEL_COLORTEMPERATURE,
|
||||
LightStateConverter.toColorTemperaturePercentType(state, colorTemperatureCapabilties));
|
||||
updateState(CHANNEL_COLORTEMPERATURE_ABS, LightStateConverter.toColorTemperature(state));
|
||||
} else {
|
||||
updateState(CHANNEL_COLORTEMPERATURE, UnDefType.NULL);
|
||||
updateState(CHANNEL_COLORTEMPERATURE, UnDefType.UNDEF);
|
||||
updateState(CHANNEL_COLORTEMPERATURE_ABS, UnDefType.UNDEF);
|
||||
}
|
||||
|
||||
PercentType brightnessPercentType = LightStateConverter.toBrightnessPercentType(state);
|
||||
if (!state.isOn()) {
|
||||
brightnessPercentType = new PercentType(0);
|
||||
brightnessPercentType = PercentType.ZERO;
|
||||
}
|
||||
updateState(CHANNEL_BRIGHTNESS, brightnessPercentType);
|
||||
|
||||
if (state.isOn()) {
|
||||
updateState(CHANNEL_SWITCH, OnOffType.ON);
|
||||
} else {
|
||||
updateState(CHANNEL_SWITCH, OnOffType.OFF);
|
||||
}
|
||||
updateState(CHANNEL_SWITCH, OnOffType.from(state.isOn()));
|
||||
|
||||
StringType stringType = LightStateConverter.toAlertStringType(state);
|
||||
if (!"NULL".equals(stringType.toString())) {
|
||||
|
@ -609,7 +643,7 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
|||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singletonList(LightActions.class);
|
||||
return List.of(LightActions.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,10 +12,19 @@
|
|||
*/
|
||||
package org.openhab.binding.hue.internal.handler;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
|
||||
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
|
||||
import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
|
||||
import org.openhab.core.types.StateDescription;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
|
@ -29,14 +38,23 @@ import org.osgi.service.component.annotations.Reference;
|
|||
@NonNullByDefault
|
||||
public class HueStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider {
|
||||
|
||||
@Reference
|
||||
protected void setChannelTypeI18nLocalizationService(
|
||||
final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
|
||||
private final Map<ChannelUID, StateDescription> descriptions = new ConcurrentHashMap<>();
|
||||
|
||||
@Activate
|
||||
public HueStateDescriptionOptionProvider(
|
||||
final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
|
||||
this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
|
||||
}
|
||||
|
||||
protected void unsetChannelTypeI18nLocalizationService(
|
||||
final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
|
||||
this.channelTypeI18nLocalizationService = null;
|
||||
public void setDescription(ChannelUID channelUID, StateDescription description) {
|
||||
descriptions.put(channelUID, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable StateDescription getStateDescription(Channel channel,
|
||||
@Nullable StateDescription originalStateDescription, @Nullable Locale locale) {
|
||||
StateDescription stateDescription = descriptions.get(channel.getUID());
|
||||
return stateDescription != null ? stateDescription
|
||||
: super.getStateDescription(channel, originalStateDescription, locale);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.openhab.binding.hue.internal.State.AlertMode;
|
|||
import org.openhab.binding.hue.internal.State.ColorMode;
|
||||
import org.openhab.binding.hue.internal.State.Effect;
|
||||
import org.openhab.binding.hue.internal.StateUpdate;
|
||||
import org.openhab.binding.hue.internal.dto.ColorTemperature;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
|
@ -44,10 +45,6 @@ public class LightStateConverter {
|
|||
private static final double SATURATION_FACTOR = 2.54;
|
||||
private static final double BRIGHTNESS_FACTOR = 2.54;
|
||||
|
||||
private static final int MIN_COLOR_TEMPERATURE = 153;
|
||||
private static final int MAX_COLOR_TEMPERATURE = 500;
|
||||
private static final int COLOR_TEMPERATURE_RANGE = MAX_COLOR_TEMPERATURE - MIN_COLOR_TEMPERATURE;
|
||||
|
||||
/**
|
||||
* {@value #ALERT_MODE_NONE}. The light is not performing an alert effect.
|
||||
*/
|
||||
|
@ -150,10 +147,26 @@ public class LightStateConverter {
|
|||
* @param percentType color temperature represented as {@link PercentType}
|
||||
* @return light state containing the color temperature
|
||||
*/
|
||||
public static StateUpdate toColorTemperatureLightState(PercentType percentType) {
|
||||
int colorTemperature = MIN_COLOR_TEMPERATURE
|
||||
+ Math.round((COLOR_TEMPERATURE_RANGE * percentType.floatValue()) / 100);
|
||||
return new StateUpdate().setColorTemperature(colorTemperature);
|
||||
public static StateUpdate toColorTemperatureLightStateFromPercentType(PercentType percentType,
|
||||
ColorTemperature capabilities) {
|
||||
int colorTemperature = capabilities.min
|
||||
+ Math.round(((capabilities.max - capabilities.min) * percentType.floatValue()) / 100);
|
||||
return new StateUpdate().setColorTemperature(colorTemperature, capabilities);
|
||||
}
|
||||
|
||||
public static int kelvinToMired(int kelvinValue) {
|
||||
return (int) (1000000.0 / kelvinValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given {@link DecimalType} into a light state containing
|
||||
* the color temperature in Kelvin.
|
||||
*
|
||||
* @param decimalType color temperature in Kelvin
|
||||
* @return light state containing the color temperature
|
||||
*/
|
||||
public static StateUpdate toColorTemperatureLightState(DecimalType decimalType, ColorTemperature capabilities) {
|
||||
return new StateUpdate().setColorTemperature(kelvinToMired(decimalType.intValue()), capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,12 +176,13 @@ public class LightStateConverter {
|
|||
* @param currentColorTemp The current color temperature
|
||||
* @return The adjusted color temperature value
|
||||
*/
|
||||
public static int toAdjustedColorTemp(IncreaseDecreaseType type, int currentColorTemp) {
|
||||
public static int toAdjustedColorTemp(IncreaseDecreaseType type, int currentColorTemp,
|
||||
ColorTemperature capabilities) {
|
||||
int newColorTemp;
|
||||
if (type == IncreaseDecreaseType.DECREASE) {
|
||||
newColorTemp = Math.max(currentColorTemp - DIM_STEPSIZE, MIN_COLOR_TEMPERATURE);
|
||||
newColorTemp = Math.max(currentColorTemp - DIM_STEPSIZE, capabilities.min);
|
||||
} else {
|
||||
newColorTemp = Math.min(currentColorTemp + DIM_STEPSIZE, MAX_COLOR_TEMPERATURE);
|
||||
newColorTemp = Math.min(currentColorTemp + DIM_STEPSIZE, capabilities.max);
|
||||
}
|
||||
return newColorTemp;
|
||||
}
|
||||
|
@ -180,12 +194,27 @@ public class LightStateConverter {
|
|||
* @param lightState light state
|
||||
* @return percent type representing the color temperature
|
||||
*/
|
||||
public static PercentType toColorTemperaturePercentType(State lightState) {
|
||||
int percent = (int) Math
|
||||
.round(((lightState.getColorTemperature() - MIN_COLOR_TEMPERATURE) * 100.0) / COLOR_TEMPERATURE_RANGE);
|
||||
public static PercentType toColorTemperaturePercentType(State lightState, ColorTemperature capabilities) {
|
||||
int percent = (int) Math.round(((lightState.getColorTemperature() - capabilities.min) * 100.0)
|
||||
/ (capabilities.max - capabilities.min));
|
||||
return new PercentType(restrictToBounds(percent));
|
||||
}
|
||||
|
||||
public static int miredToKelvin(int miredValue) {
|
||||
return (int) (1000000.0 / miredValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms Hue Light {@link State} into {@link DecimalType} representing
|
||||
* the color temperature in Kelvin.
|
||||
*
|
||||
* @param lightState light state
|
||||
* @return percent type representing the color temperature in Kelvin
|
||||
*/
|
||||
public static DecimalType toColorTemperature(State lightState) {
|
||||
return new DecimalType(miredToKelvin(lightState.getColorTemperature()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms Hue Light {@link State} into {@link PercentType} representing
|
||||
* the brightness.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
<channels>
|
||||
<channel id="color_temperature" typeId="system.color-temperature"/>
|
||||
<channel id="color_temperature_abs" typeId="system.color-temperature-abs"/>
|
||||
<channel id="brightness" typeId="system.brightness"/>
|
||||
<channel id="alert" typeId="alert"/>
|
||||
<channel id="effect" typeId="effect"/>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<channels>
|
||||
<channel id="color" typeId="system.color"/>
|
||||
<channel id="color_temperature" typeId="system.color-temperature"/>
|
||||
<channel id="color_temperature_abs" typeId="system.color-temperature-abs"/>
|
||||
<channel id="alert" typeId="alert"/>
|
||||
<channel id="effect" typeId="effect"/>
|
||||
</channels>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<channels>
|
||||
<channel id="switch" typeId="system.power"/>
|
||||
<channel id="color_temperature" typeId="system.color-temperature"/>
|
||||
<channel id="color_temperature_abs" typeId="system.color-temperature-abs"/>
|
||||
<channel id="brightness" typeId="system.brightness"/>
|
||||
<channel id="color" typeId="system.color"/>
|
||||
<channel id="alert" typeId="alert"/>
|
||||
|
|
|
@ -14,10 +14,12 @@ package org.openhab.binding.hue.internal;
|
|||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.hue.internal.State.ColorMode;
|
||||
import org.openhab.binding.hue.internal.dto.ColorTemperature;
|
||||
import org.openhab.binding.hue.internal.handler.LightStateConverter;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
|
@ -31,6 +33,38 @@ import org.openhab.core.library.types.PercentType;
|
|||
*/
|
||||
public class LightStateConverterTest {
|
||||
|
||||
@Test
|
||||
public void colorTemperatureLightStateConverterConversionIsBijectiveDefaultColorTemperatureCapabilities() {
|
||||
final State lightState = new State();
|
||||
final ColorTemperature colorTemperature = new ColorTemperature();
|
||||
for (int percent = 1; percent <= 100; ++percent) {
|
||||
StateUpdate stateUpdate = LightStateConverter
|
||||
.toColorTemperatureLightStateFromPercentType(new PercentType(percent), colorTemperature);
|
||||
assertThat(stateUpdate.commands, hasSize(1));
|
||||
assertThat(stateUpdate.commands.get(0).key, is("ct"));
|
||||
lightState.ct = Integer.parseInt(stateUpdate.commands.get(0).value.toString());
|
||||
assertThat(LightStateConverter.toColorTemperaturePercentType(lightState, colorTemperature).intValue(),
|
||||
is(percent));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void colorTemperatureLightStateConverterConversionIsBijectiveIndividualColorTemperatureCapabilities() {
|
||||
final State lightState = new State();
|
||||
final ColorTemperature colorTemperature = new ColorTemperature();
|
||||
colorTemperature.min = 250;
|
||||
colorTemperature.max = 454;
|
||||
for (int percent = 1; percent <= 100; ++percent) {
|
||||
StateUpdate stateUpdate = LightStateConverter
|
||||
.toColorTemperatureLightStateFromPercentType(new PercentType(percent), colorTemperature);
|
||||
assertThat(stateUpdate.commands, hasSize(1));
|
||||
assertThat(stateUpdate.commands.get(0).key, is("ct"));
|
||||
lightState.ct = Integer.parseInt(stateUpdate.commands.get(0).value.toString());
|
||||
assertThat(LightStateConverter.toColorTemperaturePercentType(lightState, colorTemperature).intValue(),
|
||||
is(percent));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void brightnessOfZeroIsZero() {
|
||||
final State lightState = new State();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
package org.openhab.binding.hue.internal.handler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.openhab.binding.hue.internal.HueBindingConstants.*;
|
||||
|
@ -27,6 +27,7 @@ import org.openhab.binding.hue.internal.FullLight;
|
|||
import org.openhab.binding.hue.internal.State.ColorMode;
|
||||
import org.openhab.binding.hue.internal.StateUpdate;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -37,6 +38,7 @@ import org.openhab.core.thing.ChannelUID;
|
|||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
@ -136,6 +138,24 @@ public class HueLightHandlerTest {
|
|||
assertSendCommandForColorTemp(new PercentType(100), new HueLightState(), expectedReply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertCommandForColorTemperatureAbsChannel6500Kelvin() {
|
||||
String expectedReply = "{\"ct\" : 153, \"transitiontime\" : 4}";
|
||||
assertSendCommandForColorTempAbs(new DecimalType(6500), new HueLightState(), expectedReply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertCommandForColorTemperatureAbsChannel4500Kelvin() {
|
||||
String expectedReply = "{\"ct\" : 222, \"transitiontime\" : 4}";
|
||||
assertSendCommandForColorTempAbs(new DecimalType(4500), new HueLightState(), expectedReply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertCommandForColorTemperatureAbsChannel2000Kelvin() {
|
||||
String expectedReply = "{\"ct\" : 500, \"transitiontime\" : 4}";
|
||||
assertSendCommandForColorTempAbs(new DecimalType(2000), new HueLightState(), expectedReply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertPercentageValueOfColorTemperatureWhenCt153() {
|
||||
int expectedReply = 0;
|
||||
|
@ -337,6 +357,10 @@ public class HueLightHandlerTest {
|
|||
assertSendCommand(CHANNEL_COLORTEMPERATURE, command, currentState, expectedReply);
|
||||
}
|
||||
|
||||
private void assertSendCommandForColorTempAbs(Command command, HueLightState currentState, String expectedReply) {
|
||||
assertSendCommand(CHANNEL_COLORTEMPERATURE_ABS, command, currentState, expectedReply);
|
||||
}
|
||||
|
||||
private void asserttoColorTemperaturePercentType(int ctValue, int expectedPercent) {
|
||||
int percent = (int) Math.round(((ctValue - MIN_COLOR_TEMPERATURE) * 100.0) / COLOR_TEMPERATURE_RANGE);
|
||||
assertEquals(percent, expectedPercent);
|
||||
|
@ -373,7 +397,8 @@ public class HueLightHandlerTest {
|
|||
|
||||
long fadeTime = 400;
|
||||
|
||||
HueLightHandler hueLightHandler = new HueLightHandler(mockThing) {
|
||||
HueLightHandler hueLightHandler = new HueLightHandler(mockThing,
|
||||
new HueStateDescriptionOptionProvider(mock(ChannelTypeI18nLocalizationService.class))) {
|
||||
@Override
|
||||
protected synchronized HueClient getHueClient() {
|
||||
return mockClient;
|
||||
|
|
Loading…
Reference in New Issue