Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[hue] Added LightActions to Hue light groups #11452

Merged
merged 1 commit into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bundles/org.openhab.binding.hue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

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;
Expand All @@ -26,20 +26,19 @@
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
Expand All @@ -52,8 +51,8 @@ public void fadingLightCommand(
@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;
}
Expand All @@ -62,7 +61,6 @@ public void fadingLightCommand(
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;
Expand All @@ -72,8 +70,8 @@ public void fadingLightCommand(
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
* @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";

Expand Down Expand Up @@ -168,6 +169,7 @@ public void handleCommand(ChannelUID channelUID, Command command) {
handleCommand(channelUID.getId(), command, defaultFadeTime);
}

@Override
public void handleCommand(String channel, Command command, long fadeTime) {
HueClient bridgeHandler = getHueClient();
if (bridgeHandler == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
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;
Expand All @@ -29,7 +27,6 @@
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;
Expand All @@ -47,7 +44,6 @@
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;
Expand All @@ -73,7 +69,7 @@
* @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,
Expand Down Expand Up @@ -218,6 +214,7 @@ public void handleCommand(ChannelUID channelUID, Command command) {
handleCommand(channelUID.getId(), command, defaultFadeTime);
}

@Override
public void handleCommand(String channel, Command command, long fadeTime) {
HueClient bridgeHandler = getHueClient();
if (bridgeHandler == null) {
Expand All @@ -234,95 +231,95 @@ public void handleCommand(String channel, Command command, long fadeTime) {
}

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,
Expand All @@ -336,21 +333,21 @@ public void handleCommand(String channel, Command command, long fadeTime) {
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);
}
Expand Down Expand Up @@ -601,11 +598,6 @@ private int getAlertDuration(Command command) {
return delay;
}

@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return List.of(LightActions.class);
}

@Override
public String getLightId() {
return lightId;
Expand Down
Loading