mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[hue] Added LightActions to Hue light groups (#11452)
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
parent
a1b3f27964
commit
4d5fd84c49
@ -227,7 +227,7 @@ The `tap_switch_event` can trigger one of the following events:
|
||||
## Rule Actions
|
||||
|
||||
This binding includes a rule action, which allows to change a light channel with a specific fading time from within rules.
|
||||
There is a separate instance for each light, which can be retrieved e.g. through
|
||||
There is a separate instance for each light or light group, which can be retrieved e.g. through
|
||||
|
||||
```php
|
||||
val hueActions = getActions("hue","hue:0210:00178810d0dc:1")
|
||||
@ -244,7 +244,7 @@ hueActions.fadingLightCommand("color", new PercentType(100), new DecimalType(100
|
||||
|-----------|--------------------------------------------------------------------------------------------------|
|
||||
| channel | The following channels have fade time support: **brightness, color, color_temperature, switch** |
|
||||
| command | All commands supported by the channel can be used |
|
||||
| fadeTime | Fade time in Milliseconds to a new light value (min="0", step="100") |
|
||||
| fadeTime | Fade time in milliseconds to a new light value (min="0", step="100") |
|
||||
|
||||
## Full Example
|
||||
|
||||
|
@ -14,7 +14,7 @@ package org.openhab.binding.hue.internal.action;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.hue.internal.handler.HueLightHandler;
|
||||
import org.openhab.binding.hue.internal.handler.HueLightActionsHandler;
|
||||
import org.openhab.core.automation.annotation.ActionInput;
|
||||
import org.openhab.core.automation.annotation.RuleAction;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
@ -26,20 +26,19 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link LightActions} defines the thing actions for the hue binding.
|
||||
* The {@link LightActions} defines {@link ThingActions} for the hue lights.
|
||||
*
|
||||
* @author Jochen Leopold - Initial contribution
|
||||
* @author Laurent Garnier - new method invokeMethodOf + interface ILightActions
|
||||
*/
|
||||
@ThingActionsScope(name = "hue")
|
||||
@NonNullByDefault
|
||||
public class LightActions implements ThingActions {
|
||||
private final Logger logger = LoggerFactory.getLogger(LightActions.class);
|
||||
private @Nullable HueLightHandler handler;
|
||||
private @Nullable HueLightActionsHandler handler;
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
this.handler = (HueLightHandler) handler;
|
||||
this.handler = (HueLightActionsHandler) handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,8 +51,8 @@ public class LightActions implements ThingActions {
|
||||
@ActionInput(name = "channel", label = "@text/actionInputChannelLabel", description = "@text/actionInputChannelDesc") @Nullable String channel,
|
||||
@ActionInput(name = "command", label = "@text/actionInputCommandLabel", description = "@text/actionInputCommandDesc") @Nullable Command command,
|
||||
@ActionInput(name = "fadeTime", label = "@text/actionInputFadeTimeLabel", description = "@text/actionInputFadeTimeDesc") @Nullable DecimalType fadeTime) {
|
||||
HueLightHandler lightHandler = handler;
|
||||
if (lightHandler == null) {
|
||||
HueLightActionsHandler lightActionsHandler = handler;
|
||||
if (lightActionsHandler == null) {
|
||||
logger.warn("Hue Action service ThingHandler is null!");
|
||||
return;
|
||||
}
|
||||
@ -62,7 +61,6 @@ public class LightActions implements ThingActions {
|
||||
logger.debug("skipping Hue fadingLightCommand to channel '{}' due to null value.", channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command == null) {
|
||||
logger.debug("skipping Hue fadingLightCommand to command '{}' due to null value.", command);
|
||||
return;
|
||||
@ -72,8 +70,8 @@ public class LightActions implements ThingActions {
|
||||
return;
|
||||
}
|
||||
|
||||
lightHandler.handleCommand(channel, command, fadeTime.longValue());
|
||||
logger.debug("send LightAction to {} with {}ms of fadeTime", channel, fadeTime);
|
||||
lightActionsHandler.handleCommand(channel, command, fadeTime.longValue());
|
||||
logger.debug("send fadingLightCommand to channel '{}' with fadeTime of {}ms.", channel, fadeTime);
|
||||
}
|
||||
|
||||
public static void fadingLightCommand(ThingActions actions, @Nullable String channel, @Nullable Command command,
|
||||
|
@ -57,7 +57,8 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HueGroupHandler extends BaseThingHandler implements GroupStatusListener {
|
||||
public class HueGroupHandler extends BaseThingHandler implements HueLightActionsHandler, GroupStatusListener {
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_GROUP);
|
||||
public static final String PROPERTY_MEMBERS = "members";
|
||||
|
||||
@ -168,6 +169,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
|
||||
handleCommand(channelUID.getId(), command, defaultFadeTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(String channel, Command command, long fadeTime) {
|
||||
HueClient bridgeHandler = getHueClient();
|
||||
if (bridgeHandler == null) {
|
||||
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.hue.internal.action.LightActions;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* The {@link HueLightActionsHandler} defines interface handlers to handle {@link LightActions}.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface HueLightActionsHandler extends ThingHandler {
|
||||
|
||||
@Override
|
||||
default Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Set.of(LightActions.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a command for a given channel.
|
||||
*
|
||||
* @param channel the id of the channel to which the command was sent
|
||||
* @param command the {@link Command}
|
||||
* @param fadeTime duration for execution of the command
|
||||
*/
|
||||
void handleCommand(String channel, Command command, long fadeTime);
|
||||
}
|
@ -16,8 +16,6 @@ import static org.openhab.binding.hue.internal.HueBindingConstants.*;
|
||||
import static org.openhab.core.thing.Thing.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@ -29,7 +27,6 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.hue.internal.FullLight;
|
||||
import org.openhab.binding.hue.internal.State;
|
||||
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;
|
||||
@ -47,7 +44,6 @@ import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
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.StateDescriptionFragment;
|
||||
import org.openhab.core.types.StateDescriptionFragmentBuilder;
|
||||
@ -73,7 +69,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Jochen Leopold - Added support for custom fade times
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HueLightHandler extends BaseThingHandler implements LightStatusListener {
|
||||
public class HueLightHandler extends BaseThingHandler implements HueLightActionsHandler, LightStatusListener {
|
||||
|
||||
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,
|
||||
@ -218,6 +214,7 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
||||
handleCommand(channelUID.getId(), command, defaultFadeTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(String channel, Command command, long fadeTime) {
|
||||
HueClient bridgeHandler = getHueClient();
|
||||
if (bridgeHandler == null) {
|
||||
@ -234,95 +231,95 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
||||
}
|
||||
|
||||
Integer lastColorTemp;
|
||||
StateUpdate lightState = null;
|
||||
StateUpdate newState = null;
|
||||
switch (channel) {
|
||||
case CHANNEL_COLORTEMPERATURE:
|
||||
if (command instanceof PercentType) {
|
||||
lightState = LightStateConverter.toColorTemperatureLightStateFromPercentType((PercentType) command,
|
||||
newState = LightStateConverter.toColorTemperatureLightStateFromPercentType((PercentType) command,
|
||||
colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
} else if (command instanceof OnOffType) {
|
||||
lightState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
newState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
if (isOsramPar16) {
|
||||
lightState = addOsramSpecificCommands(lightState, (OnOffType) command);
|
||||
newState = addOsramSpecificCommands(newState, (OnOffType) command);
|
||||
}
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
lightState = convertColorTempChangeToStateUpdate((IncreaseDecreaseType) command, light);
|
||||
if (lightState != null) {
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState = convertColorTempChangeToStateUpdate((IncreaseDecreaseType) command, light);
|
||||
if (newState != null) {
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_COLORTEMPERATURE_ABS:
|
||||
if (command instanceof DecimalType) {
|
||||
lightState = LightStateConverter.toColorTemperatureLightState((DecimalType) command,
|
||||
newState = LightStateConverter.toColorTemperatureLightState((DecimalType) command,
|
||||
colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_BRIGHTNESS:
|
||||
if (command instanceof PercentType) {
|
||||
lightState = LightStateConverter.toBrightnessLightState((PercentType) command);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState = LightStateConverter.toBrightnessLightState((PercentType) command);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
} else if (command instanceof OnOffType) {
|
||||
lightState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
newState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
if (isOsramPar16) {
|
||||
lightState = addOsramSpecificCommands(lightState, (OnOffType) command);
|
||||
newState = addOsramSpecificCommands(newState, (OnOffType) command);
|
||||
}
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
lightState = convertBrightnessChangeToStateUpdate((IncreaseDecreaseType) command, light);
|
||||
if (lightState != null) {
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState = convertBrightnessChangeToStateUpdate((IncreaseDecreaseType) command, light);
|
||||
if (newState != null) {
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
}
|
||||
lastColorTemp = lastSentColorTemp;
|
||||
if (lightState != null && lastColorTemp != null) {
|
||||
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
|
||||
lightState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_SWITCH:
|
||||
if (command instanceof OnOffType) {
|
||||
lightState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
newState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
if (isOsramPar16) {
|
||||
lightState = addOsramSpecificCommands(lightState, (OnOffType) command);
|
||||
newState = addOsramSpecificCommands(newState, (OnOffType) command);
|
||||
}
|
||||
}
|
||||
lastColorTemp = lastSentColorTemp;
|
||||
if (lightState != null && lastColorTemp != null) {
|
||||
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
|
||||
lightState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState.setColorTemperature(lastColorTemp, colorTemperatureCapabilties);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_COLOR:
|
||||
if (command instanceof HSBType) {
|
||||
HSBType hsbCommand = (HSBType) command;
|
||||
if (hsbCommand.getBrightness().intValue() == 0) {
|
||||
lightState = LightStateConverter.toOnOffLightState(OnOffType.OFF);
|
||||
newState = LightStateConverter.toOnOffLightState(OnOffType.OFF);
|
||||
} else {
|
||||
lightState = LightStateConverter.toColorLightState(hsbCommand, light.getState());
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState = LightStateConverter.toColorLightState(hsbCommand, light.getState());
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
} else if (command instanceof PercentType) {
|
||||
lightState = LightStateConverter.toBrightnessLightState((PercentType) command);
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState = LightStateConverter.toBrightnessLightState((PercentType) command);
|
||||
newState.setTransitionTime(fadeTime);
|
||||
} else if (command instanceof OnOffType) {
|
||||
lightState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
newState = LightStateConverter.toOnOffLightState((OnOffType) command);
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
lightState = convertBrightnessChangeToStateUpdate((IncreaseDecreaseType) command, light);
|
||||
if (lightState != null) {
|
||||
lightState.setTransitionTime(fadeTime);
|
||||
newState = convertBrightnessChangeToStateUpdate((IncreaseDecreaseType) command, light);
|
||||
if (newState != null) {
|
||||
newState.setTransitionTime(fadeTime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_ALERT:
|
||||
if (command instanceof StringType) {
|
||||
lightState = LightStateConverter.toAlertState((StringType) command);
|
||||
if (lightState == null) {
|
||||
newState = LightStateConverter.toAlertState((StringType) command);
|
||||
if (newState == null) {
|
||||
// Unsupported StringType is passed. Log a warning
|
||||
// message and return.
|
||||
logger.warn("Unsupported String command: {}. Supported commands are: {}, {}, {} ", command,
|
||||
@ -336,21 +333,21 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
||||
break;
|
||||
case CHANNEL_EFFECT:
|
||||
if (command instanceof OnOffType) {
|
||||
lightState = LightStateConverter.toOnOffEffectState((OnOffType) command);
|
||||
newState = LightStateConverter.toOnOffEffectState((OnOffType) command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (lightState != null) {
|
||||
if (newState != null) {
|
||||
// Cache values which we have sent
|
||||
Integer tmpBrightness = lightState.getBrightness();
|
||||
Integer tmpBrightness = newState.getBrightness();
|
||||
if (tmpBrightness != null) {
|
||||
lastSentBrightness = tmpBrightness;
|
||||
}
|
||||
Integer tmpColorTemp = lightState.getColorTemperature();
|
||||
Integer tmpColorTemp = newState.getColorTemperature();
|
||||
if (tmpColorTemp != null) {
|
||||
lastSentColorTemp = tmpColorTemp;
|
||||
}
|
||||
bridgeHandler.updateLightState(this, light, lightState, fadeTime);
|
||||
bridgeHandler.updateLightState(this, light, newState, fadeTime);
|
||||
} else {
|
||||
logger.warn("Command sent to an unknown channel id: {}:{}", getThing().getUID(), channel);
|
||||
}
|
||||
@ -601,11 +598,6 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
|
||||
return delay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return List.of(LightActions.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLightId() {
|
||||
return lightId;
|
||||
|
@ -19,7 +19,8 @@ import static org.openhab.binding.hue.internal.HueBindingConstants.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.openhab.binding.hue.internal.FullConfig;
|
||||
@ -56,6 +57,7 @@ import com.google.gson.JsonParser;
|
||||
* @author Simon Kaufmann - migrated to plain Java test
|
||||
* @author Christoph Weitkamp - Added support for bulbs using CIE XY colormode only
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HueLightHandlerTest {
|
||||
|
||||
private static final int MIN_COLOR_TEMPERATURE = 153;
|
||||
@ -66,12 +68,7 @@ public class HueLightHandlerTest {
|
||||
private static final String OSRAM_MODEL_TYPE = HueLightHandler.OSRAM_PAR16_50_TW_MODEL_ID;
|
||||
private static final String OSRAM_MODEL_TYPE_ID = HueLightHandler.OSRAM_PAR16_50_TW_MODEL_ID;
|
||||
|
||||
private Gson gson;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
gson = new Gson();
|
||||
}
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
@Test
|
||||
public void assertCommandForOsramPar1650ForColorTemperatureChannelOn() {
|
||||
@ -402,12 +399,12 @@ public class HueLightHandlerTest {
|
||||
|
||||
HueLightHandler hueLightHandler = new HueLightHandler(mockThing, mock(HueStateDescriptionProvider.class)) {
|
||||
@Override
|
||||
protected synchronized HueClient getHueClient() {
|
||||
protected synchronized @Nullable HueClient getHueClient() {
|
||||
return mockClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bridge getBridge() {
|
||||
protected @Nullable Bridge getBridge() {
|
||||
return mockBridge;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user