[hue] Support timed effects (#15408)
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>pull/15756/head
parent
4b0c551065
commit
247c0973b6
|
@ -87,7 +87,13 @@ Device things support some of the following channels:
|
|||
The exact list of channels in a given device is determined at run time when the system is started.
|
||||
Each device reports its own live list of capabilities, and the respective list of channels is created accordingly.
|
||||
|
||||
The channels `color-xy-only`, `dimming-only` and `on-off-only` are *advanced* channels - see [below](###advanced-channels-for-devices-,-rooms-and-zones) for more details.
|
||||
The channels `color-xy-only`, `dimming-only` and `on-off-only` are *advanced* channels - see [below](#advanced-channels-for-devices-rooms-and-zones) for more details.
|
||||
|
||||
The `effect` channel is an amalgamation of 'normal' and 'timed' effects.
|
||||
To activate a 'normal' effect, the binding sends a single command to activate the respective effect.
|
||||
To activate a 'timed' effect, the binding sends a first command to set the timing followed a second command to activate the effect.
|
||||
You can explicitly send the timing command via the [dynamics channel](#the-dynamics-channel) before you send the effect command.
|
||||
Or otherwise the binding will send a default timing command of 15 minutes.
|
||||
|
||||
The `button-last-event` channel is a trigger channel.
|
||||
When the button is pressed the channel receives a number as calculated by the following formula:
|
||||
|
@ -140,6 +146,7 @@ When you set a value for the `dynamics` channel (e.g. 2000 milliseconds) and the
|
|||
When the `dynamics` channel value is changed, it triggers a time window of ten seconds during which the value is active.
|
||||
If the second command is sent within the active time window, it will be executed gradually according to the `dynamics` channel value.
|
||||
However, if the second command is sent after the active time window has expired, then it will be executed immediately.
|
||||
If the second command is a 'timed' effect, then the dynamics duration will be applied to that effect.
|
||||
|
||||
### Advanced Channels for Devices, Rooms and Zones
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ public class HueBindingConstants {
|
|||
|
||||
// channel IDs that (optionally) support dynamics
|
||||
public static final Set<String> DYNAMIC_CHANNELS = Set.of(CHANNEL_2_BRIGHTNESS, CHANNEL_2_COLOR,
|
||||
CHANNEL_2_COLOR_TEMP_PERCENT, CHANNEL_2_COLOR_TEMP_ABSOLUTE, CHANNEL_2_SCENE);
|
||||
CHANNEL_2_COLOR_TEMP_PERCENT, CHANNEL_2_COLOR_TEMP_ABSOLUTE, CHANNEL_2_SCENE, CHANNEL_2_EFFECT);
|
||||
|
||||
/*
|
||||
* Map of API v1 channel IDs against API v2 channel IDs where, if the v1 channel exists in the system, then we
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Optional;
|
|||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.RecallAction;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ZigbeeStatus;
|
||||
|
@ -320,13 +321,33 @@ public class Resource {
|
|||
return UnDefType.NULL;
|
||||
}
|
||||
|
||||
public @Nullable Effects getEffects() {
|
||||
public @Nullable Effects getFixedEffects() {
|
||||
return effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amalgamated effect state. The result may be either from an 'effects' field or from a 'timedEffects'
|
||||
* field. If both fields are missing it returns UnDefType.NULL, otherwise if either field is present and has an
|
||||
* active value (other than EffectType.NO_EFFECT) it returns a StringType of the name of the respective active
|
||||
* effect; and if none of the above apply, it returns a StringType of 'NO_EFFECT'.
|
||||
*
|
||||
* @return either a StringType value or UnDefType.NULL
|
||||
*/
|
||||
public State getEffectState() {
|
||||
Effects effects = this.effects;
|
||||
return Objects.nonNull(effects) ? new StringType(effects.getStatus().name()) : UnDefType.NULL;
|
||||
TimedEffects timedEffects = this.timedEffects;
|
||||
if (Objects.isNull(effects) && Objects.isNull(timedEffects)) {
|
||||
return UnDefType.NULL;
|
||||
}
|
||||
EffectType effect = Objects.nonNull(effects) ? effects.getStatus() : null;
|
||||
if (Objects.nonNull(effect) && effect != EffectType.NO_EFFECT) {
|
||||
return new StringType(effect.name());
|
||||
}
|
||||
EffectType timedEffect = Objects.nonNull(timedEffects) ? timedEffects.getStatus() : null;
|
||||
if (Objects.nonNull(timedEffect) && timedEffect != EffectType.NO_EFFECT) {
|
||||
return new StringType(timedEffect.name());
|
||||
}
|
||||
return new StringType(EffectType.NO_EFFECT.name());
|
||||
}
|
||||
|
||||
public @Nullable Boolean getEnabled() {
|
||||
|
@ -517,7 +538,7 @@ public class Resource {
|
|||
return Objects.nonNull(temperature) ? temperature.getTemperatureValidState() : UnDefType.NULL;
|
||||
}
|
||||
|
||||
public @Nullable Effects getTimedEffects() {
|
||||
public @Nullable TimedEffects getTimedEffects() {
|
||||
return timedEffects;
|
||||
}
|
||||
|
||||
|
@ -577,7 +598,7 @@ public class Resource {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Resource setEffects(Effects effect) {
|
||||
public Resource setFixedEffects(Effects effect) {
|
||||
this.effects = effect;
|
||||
return this;
|
||||
}
|
||||
|
@ -640,6 +661,19 @@ public class Resource {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Resource setTimedEffects(TimedEffects timedEffects) {
|
||||
this.timedEffects = timedEffects;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Resource setTimedEffectsDuration(Duration dynamicsDuration) {
|
||||
TimedEffects timedEffects = this.timedEffects;
|
||||
if (Objects.nonNull(timedEffects)) {
|
||||
timedEffects.setDuration(dynamicsDuration);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Resource setType(ResourceType resourceType) {
|
||||
this.type = resourceType.name().toLowerCase();
|
||||
return this;
|
||||
|
|
|
@ -25,11 +25,13 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||
*/
|
||||
@NonNullByDefault
|
||||
public class TimedEffects extends Effects {
|
||||
public static final Duration DEFAULT_DURATION = Duration.ofMinutes(15);
|
||||
|
||||
private @Nullable Long duration;
|
||||
|
||||
public @Nullable Duration getDuration() {
|
||||
Long duration = this.duration;
|
||||
return Objects.nonNull(duration) ? Duration.ofMillis(duration) : Duration.ZERO;
|
||||
return Objects.nonNull(duration) ? Duration.ofMillis(duration) : null;
|
||||
}
|
||||
|
||||
public TimedEffects setDuration(Duration duration) {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package org.openhab.binding.hue.internal.dto.clip2.helper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -29,6 +30,7 @@ import org.openhab.binding.hue.internal.dto.clip2.MetaData;
|
|||
import org.openhab.binding.hue.internal.dto.clip2.MirekSchema;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.OnState;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.Resource;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.TimedEffects;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
@ -198,9 +200,9 @@ public class Setters {
|
|||
}
|
||||
|
||||
/**
|
||||
* Setter for Effect field:
|
||||
* Use the given command value to set the target resource DTO value based on the attributes of the source resource
|
||||
* (if any).
|
||||
* Setter for fixed or timed effect field:
|
||||
* Use the given command value to set the target fixed or timed effects resource DTO value based on the attributes
|
||||
* of the source resource (if any).
|
||||
*
|
||||
* @param target the target resource.
|
||||
* @param command the new state command should be a StringType.
|
||||
|
@ -210,12 +212,16 @@ public class Setters {
|
|||
*/
|
||||
public static Resource setEffect(Resource target, Command command, @Nullable Resource source) {
|
||||
if ((command instanceof StringType) && Objects.nonNull(source)) {
|
||||
Effects otherEffects = source.getEffects();
|
||||
if (Objects.nonNull(otherEffects)) {
|
||||
EffectType effectType = EffectType.of(((StringType) command).toString());
|
||||
if (otherEffects.allows(effectType)) {
|
||||
target.setEffects(new Effects().setEffect(effectType));
|
||||
}
|
||||
EffectType commandEffectType = EffectType.of(((StringType) command).toString());
|
||||
Effects sourceFixedEffects = source.getFixedEffects();
|
||||
if (Objects.nonNull(sourceFixedEffects) && sourceFixedEffects.allows(commandEffectType)) {
|
||||
target.setFixedEffects(new Effects().setEffect(commandEffectType));
|
||||
}
|
||||
TimedEffects sourceTimedEffects = source.getTimedEffects();
|
||||
if (Objects.nonNull(sourceTimedEffects) && sourceTimedEffects.allows(commandEffectType)) {
|
||||
Duration duration = sourceTimedEffects.getDuration();
|
||||
target.setTimedEffects(((TimedEffects) new TimedEffects().setEffect(commandEffectType))
|
||||
.setDuration(Objects.nonNull(duration) ? duration : TimedEffects.DEFAULT_DURATION));
|
||||
}
|
||||
}
|
||||
return target;
|
||||
|
@ -239,6 +245,7 @@ public class Setters {
|
|||
if (Objects.isNull(targetOnOff) && Objects.nonNull(sourceOnOff)) {
|
||||
target.setOnState(sourceOnOff);
|
||||
}
|
||||
|
||||
// dimming
|
||||
Dimming targetDimming = target.getDimming();
|
||||
Dimming sourceDimming = source.getDimming();
|
||||
|
@ -246,13 +253,15 @@ public class Setters {
|
|||
target.setDimming(sourceDimming);
|
||||
targetDimming = target.getDimming();
|
||||
}
|
||||
|
||||
// minimum dimming level
|
||||
Double targetMinDimmingLevel = Objects.nonNull(targetDimming) ? targetDimming.getMinimumDimmingLevel() : null;
|
||||
Double sourceMinDimmingLevel = Objects.nonNull(sourceDimming) ? sourceDimming.getMinimumDimmingLevel() : null;
|
||||
if (Objects.isNull(targetMinDimmingLevel) && Objects.nonNull(sourceMinDimmingLevel)) {
|
||||
targetDimming = Objects.nonNull(targetDimming) ? targetDimming : new Dimming();
|
||||
targetDimming.setMinimumDimmingLevel(sourceMinDimmingLevel);
|
||||
if (Objects.nonNull(targetDimming)) {
|
||||
Double sourceMinDimLevel = Objects.isNull(sourceDimming) ? null : sourceDimming.getMinimumDimmingLevel();
|
||||
if (Objects.nonNull(sourceMinDimLevel)) {
|
||||
targetDimming.setMinimumDimmingLevel(sourceMinDimLevel);
|
||||
}
|
||||
}
|
||||
|
||||
// color
|
||||
ColorXy targetColor = target.getColorXy();
|
||||
ColorXy sourceColor = source.getColorXy();
|
||||
|
@ -260,13 +269,13 @@ public class Setters {
|
|||
target.setColorXy(sourceColor);
|
||||
targetColor = target.getColorXy();
|
||||
}
|
||||
|
||||
// color gamut
|
||||
Gamut targetGamut = Objects.nonNull(targetColor) ? targetColor.getGamut() : null;
|
||||
Gamut sourceGamut = Objects.nonNull(sourceColor) ? sourceColor.getGamut() : null;
|
||||
if (Objects.isNull(targetGamut) && Objects.nonNull(sourceGamut)) {
|
||||
targetColor = Objects.nonNull(targetColor) ? targetColor : new ColorXy();
|
||||
Gamut sourceGamut = Objects.isNull(sourceColor) ? null : sourceColor.getGamut();
|
||||
if (Objects.nonNull(targetColor) && Objects.nonNull(sourceGamut)) {
|
||||
targetColor.setGamut(sourceGamut);
|
||||
}
|
||||
|
||||
// color temperature
|
||||
ColorTemperature targetColorTemp = target.getColorTemperature();
|
||||
ColorTemperature sourceColorTemp = source.getColorTemperature();
|
||||
|
@ -274,40 +283,65 @@ public class Setters {
|
|||
target.setColorTemperature(sourceColorTemp);
|
||||
targetColorTemp = target.getColorTemperature();
|
||||
}
|
||||
|
||||
// mirek schema
|
||||
MirekSchema targetMirekSchema = Objects.nonNull(targetColorTemp) ? targetColorTemp.getMirekSchema() : null;
|
||||
MirekSchema sourceMirekSchema = Objects.nonNull(sourceColorTemp) ? sourceColorTemp.getMirekSchema() : null;
|
||||
if (Objects.isNull(targetMirekSchema) && Objects.nonNull(sourceMirekSchema)) {
|
||||
targetColorTemp = Objects.nonNull(targetColorTemp) ? targetColorTemp : new ColorTemperature();
|
||||
targetColorTemp.setMirekSchema(sourceMirekSchema);
|
||||
if (Objects.nonNull(targetColorTemp)) {
|
||||
MirekSchema sourceMirekSchema = Objects.isNull(sourceColorTemp) ? null : sourceColorTemp.getMirekSchema();
|
||||
if (Objects.nonNull(sourceMirekSchema)) {
|
||||
targetColorTemp.setMirekSchema(sourceMirekSchema);
|
||||
}
|
||||
}
|
||||
|
||||
// metadata
|
||||
MetaData targetMetaData = target.getMetaData();
|
||||
MetaData sourceMetaData = source.getMetaData();
|
||||
if (Objects.isNull(targetMetaData) && Objects.nonNull(sourceMetaData)) {
|
||||
target.setMetadata(sourceMetaData);
|
||||
}
|
||||
|
||||
// alerts
|
||||
Alerts targetAlerts = target.getAlerts();
|
||||
Alerts sourceAlerts = source.getAlerts();
|
||||
if (Objects.isNull(targetAlerts) && Objects.nonNull(sourceAlerts)) {
|
||||
target.setAlerts(sourceAlerts);
|
||||
}
|
||||
// effects
|
||||
Effects targetEffects = target.getEffects();
|
||||
Effects sourceEffects = source.getEffects();
|
||||
if (Objects.isNull(targetEffects) && Objects.nonNull(sourceEffects)) {
|
||||
targetEffects = sourceEffects;
|
||||
target.setEffects(sourceEffects);
|
||||
targetEffects = target.getEffects();
|
||||
|
||||
// fixed effects
|
||||
Effects targetFixedEffects = target.getFixedEffects();
|
||||
Effects sourceFixedEffects = source.getFixedEffects();
|
||||
if (Objects.isNull(targetFixedEffects) && Objects.nonNull(sourceFixedEffects)) {
|
||||
target.setFixedEffects(sourceFixedEffects);
|
||||
targetFixedEffects = target.getFixedEffects();
|
||||
}
|
||||
// effects values
|
||||
List<String> targetStatusValues = Objects.nonNull(targetEffects) ? targetEffects.getStatusValues() : null;
|
||||
List<String> sourceStatusValues = Objects.nonNull(sourceEffects) ? sourceEffects.getStatusValues() : null;
|
||||
if (Objects.isNull(targetStatusValues) && Objects.nonNull(sourceStatusValues)) {
|
||||
targetEffects = Objects.nonNull(targetEffects) ? targetEffects : new Effects();
|
||||
targetEffects.setStatusValues(sourceStatusValues);
|
||||
|
||||
// fixed effects allowed values
|
||||
if (Objects.nonNull(targetFixedEffects)) {
|
||||
List<String> values = Objects.isNull(sourceFixedEffects) ? List.of() : sourceFixedEffects.getStatusValues();
|
||||
if (!values.isEmpty()) {
|
||||
targetFixedEffects.setStatusValues(values);
|
||||
}
|
||||
}
|
||||
|
||||
// timed effects
|
||||
TimedEffects targetTimedEffects = target.getTimedEffects();
|
||||
TimedEffects sourceTimedEffects = source.getTimedEffects();
|
||||
if (Objects.isNull(targetTimedEffects) && Objects.nonNull(sourceTimedEffects)) {
|
||||
target.setTimedEffects(sourceTimedEffects);
|
||||
targetTimedEffects = target.getTimedEffects();
|
||||
}
|
||||
|
||||
// timed effects allowed values and duration
|
||||
if (Objects.nonNull(targetTimedEffects)) {
|
||||
List<String> values = Objects.isNull(sourceTimedEffects) ? List.of() : sourceTimedEffects.getStatusValues();
|
||||
if (!values.isEmpty()) {
|
||||
targetTimedEffects.setStatusValues(values);
|
||||
}
|
||||
Duration duration = Objects.isNull(sourceTimedEffects) ? null : sourceTimedEffects.getDuration();
|
||||
if (Objects.nonNull(duration)) {
|
||||
targetTimedEffects.setDuration(duration);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
import java.util.concurrent.Future;
|
||||
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;
|
||||
|
@ -45,6 +46,7 @@ import org.openhab.binding.hue.internal.dto.clip2.ProductData;
|
|||
import org.openhab.binding.hue.internal.dto.clip2.Resource;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.Resources;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.TimedEffects;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.RecallAction;
|
||||
|
@ -337,8 +339,7 @@ public class Clip2ThingHandler extends BaseThingHandler {
|
|||
break;
|
||||
|
||||
case CHANNEL_2_EFFECT:
|
||||
putResource = Setters.setEffect(new Resource(lightResourceType), command, cache);
|
||||
putResource.setOnOff(OnOffType.ON);
|
||||
putResource = Setters.setEffect(new Resource(lightResourceType), command, cache).setOnOff(OnOffType.ON);
|
||||
break;
|
||||
|
||||
case CHANNEL_2_COLOR_TEMP_PERCENT:
|
||||
|
@ -487,6 +488,8 @@ public class Clip2ThingHandler extends BaseThingHandler {
|
|||
&& !dynamicsDuration.isNegative()) {
|
||||
if (ResourceType.SCENE == putResource.getType()) {
|
||||
putResource.setRecallDuration(dynamicsDuration);
|
||||
} else if (CHANNEL_2_EFFECT == channelId) {
|
||||
putResource.setTimedEffectsDuration(dynamicsDuration);
|
||||
} else {
|
||||
putResource.setDynamicsDuration(dynamicsDuration);
|
||||
}
|
||||
|
@ -945,21 +948,23 @@ public class Clip2ThingHandler extends BaseThingHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* Process the incoming Resource to initialize the effects channel.
|
||||
* Process the incoming Resource to initialize the fixed resp. timed effects channel.
|
||||
*
|
||||
* @param resource a Resource possibly with an Effects element.
|
||||
* @param resource a Resource possibly containing a fixed and/or timed effects element.
|
||||
*/
|
||||
public void updateEffectChannel(Resource resource) {
|
||||
Effects effects = resource.getEffects();
|
||||
if (Objects.nonNull(effects)) {
|
||||
List<StateOption> stateOptions = effects.getStatusValues().stream()
|
||||
.map(effect -> EffectType.of(effect).name()).map(effectId -> new StateOption(effectId, effectId))
|
||||
.collect(Collectors.toList());
|
||||
if (!stateOptions.isEmpty()) {
|
||||
stateDescriptionProvider.setStateOptions(new ChannelUID(thing.getUID(), CHANNEL_2_EFFECT),
|
||||
stateOptions);
|
||||
logger.debug("{} -> updateEffects() found {} effects", resourceId, stateOptions.size());
|
||||
}
|
||||
Effects fixedEffects = resource.getFixedEffects();
|
||||
TimedEffects timedEffects = resource.getTimedEffects();
|
||||
List<StateOption> stateOptions = Stream
|
||||
.concat(Objects.nonNull(fixedEffects) ? fixedEffects.getStatusValues().stream() : Stream.empty(),
|
||||
Objects.nonNull(timedEffects) ? timedEffects.getStatusValues().stream() : Stream.empty())
|
||||
.map(effect -> {
|
||||
String effectName = EffectType.of(effect).name();
|
||||
return new StateOption(effectName, effectName);
|
||||
}).distinct().collect(Collectors.toList());
|
||||
if (!stateOptions.isEmpty()) {
|
||||
stateDescriptionProvider.setStateOptions(new ChannelUID(thing.getUID(), CHANNEL_2_EFFECT), stateOptions);
|
||||
logger.debug("{} -> updateEffects() found {} effects", resourceId, stateOptions.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.io.BufferedReader;
|
|||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
@ -28,6 +29,7 @@ import org.openhab.binding.hue.internal.dto.clip2.ActionEntry;
|
|||
import org.openhab.binding.hue.internal.dto.clip2.Alerts;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.Button;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.Dimming;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.Effects;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.Event;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.LightLevel;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.MetaData;
|
||||
|
@ -42,11 +44,13 @@ import org.openhab.binding.hue.internal.dto.clip2.Resources;
|
|||
import org.openhab.binding.hue.internal.dto.clip2.Rotation;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.RotationEvent;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.Temperature;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.TimedEffects;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.BatteryStateType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ButtonEventType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.DirectionType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.RotationEventType;
|
||||
import org.openhab.binding.hue.internal.dto.clip2.enums.ZigbeeStatus;
|
||||
|
@ -597,4 +601,115 @@ class Clip2DtoTest {
|
|||
assertEquals("db4fd630-3798-40de-b642-c1ef464bf770", service.getId());
|
||||
assertEquals(ResourceType.GROUPED_LIGHT, service.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFixedEffectSetter() {
|
||||
Resource source;
|
||||
Resource target;
|
||||
Effects resultEffect;
|
||||
|
||||
// no source effects
|
||||
source = new Resource(ResourceType.LIGHT);
|
||||
target = new Resource(ResourceType.LIGHT);
|
||||
Setters.setResource(target, source);
|
||||
assertNull(target.getFixedEffects());
|
||||
|
||||
// valid source fixed effects
|
||||
source = new Resource(ResourceType.LIGHT).setFixedEffects(
|
||||
new Effects().setStatusValues(List.of("NO_EFFECT", "SPARKLE", "CANDLE")).setEffect(EffectType.SPARKLE));
|
||||
target = new Resource(ResourceType.LIGHT);
|
||||
Setters.setResource(target, source);
|
||||
resultEffect = target.getFixedEffects();
|
||||
assertNotNull(resultEffect);
|
||||
assertEquals(EffectType.SPARKLE, resultEffect.getEffect());
|
||||
assertEquals(3, resultEffect.getStatusValues().size());
|
||||
|
||||
// valid but different source and target fixed effects
|
||||
source = new Resource(ResourceType.LIGHT).setFixedEffects(
|
||||
new Effects().setStatusValues(List.of("NO_EFFECT", "SPARKLE", "CANDLE")).setEffect(EffectType.SPARKLE));
|
||||
target = new Resource(ResourceType.LIGHT).setFixedEffects(
|
||||
new Effects().setStatusValues(List.of("NO_EFFECT", "FIRE")).setEffect(EffectType.FIRE));
|
||||
Setters.setResource(target, source);
|
||||
resultEffect = target.getFixedEffects();
|
||||
assertNotNull(resultEffect);
|
||||
assertNotEquals(EffectType.SPARKLE, resultEffect.getEffect());
|
||||
assertEquals(3, resultEffect.getStatusValues().size());
|
||||
|
||||
// partly valid source fixed effects
|
||||
source = new Resource(ResourceType.LIGHT).setFixedEffects(new Effects().setStatusValues(List.of("SPARKLE"))
|
||||
.setEffect(EffectType.SPARKLE).setStatusValues(List.of()));
|
||||
target = new Resource(ResourceType.LIGHT);
|
||||
Setters.setResource(target, source);
|
||||
resultEffect = target.getFixedEffects();
|
||||
assertNotNull(resultEffect);
|
||||
assertEquals(EffectType.SPARKLE, resultEffect.getEffect());
|
||||
assertEquals(0, resultEffect.getStatusValues().size());
|
||||
assertFalse(resultEffect.allows(EffectType.SPARKLE));
|
||||
assertFalse(resultEffect.allows(EffectType.NO_EFFECT));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTimedEffectSetter() {
|
||||
Resource source;
|
||||
Resource target;
|
||||
Effects resultEffect;
|
||||
|
||||
// no source effects
|
||||
source = new Resource(ResourceType.LIGHT);
|
||||
target = new Resource(ResourceType.LIGHT);
|
||||
Setters.setResource(target, source);
|
||||
assertNull(target.getTimedEffects());
|
||||
|
||||
// valid source timed effects
|
||||
source = new Resource(ResourceType.LIGHT).setTimedEffects((TimedEffects) new TimedEffects()
|
||||
.setStatusValues(List.of("NO_EFFECT", "SUNRISE")).setEffect(EffectType.NO_EFFECT));
|
||||
target = new Resource(ResourceType.LIGHT);
|
||||
Setters.setResource(target, source);
|
||||
resultEffect = target.getTimedEffects();
|
||||
assertNotNull(resultEffect);
|
||||
assertEquals(EffectType.NO_EFFECT, resultEffect.getEffect());
|
||||
assertEquals(2, resultEffect.getStatusValues().size());
|
||||
|
||||
// valid but different source and target timed effects
|
||||
source = new Resource(ResourceType.LIGHT)
|
||||
.setTimedEffects((TimedEffects) new TimedEffects().setDuration(Duration.ofMinutes(11))
|
||||
.setStatusValues(List.of("NO_EFFECT", "SPARKLE", "CANDLE")).setEffect(EffectType.SPARKLE));
|
||||
target = new Resource(ResourceType.LIGHT).setTimedEffects((TimedEffects) new TimedEffects()
|
||||
.setStatusValues(List.of("NO_EFFECT", "FIRE")).setEffect(EffectType.FIRE));
|
||||
Setters.setResource(target, source);
|
||||
resultEffect = target.getTimedEffects();
|
||||
assertNotNull(resultEffect);
|
||||
assertNotEquals(EffectType.SPARKLE, resultEffect.getEffect());
|
||||
assertEquals(3, resultEffect.getStatusValues().size());
|
||||
assertTrue(resultEffect instanceof TimedEffects);
|
||||
assertEquals(Duration.ofMinutes(11), ((TimedEffects) resultEffect).getDuration());
|
||||
|
||||
// partly valid source timed effects
|
||||
source = new Resource(ResourceType.LIGHT).setTimedEffects((TimedEffects) new TimedEffects()
|
||||
.setStatusValues(List.of("SUNRISE")).setEffect(EffectType.SUNRISE).setStatusValues(List.of()));
|
||||
target = new Resource(ResourceType.LIGHT);
|
||||
Setters.setResource(target, source);
|
||||
resultEffect = target.getTimedEffects();
|
||||
assertNotNull(resultEffect);
|
||||
assertEquals(EffectType.SUNRISE, resultEffect.getEffect());
|
||||
assertEquals(0, resultEffect.getStatusValues().size());
|
||||
assertFalse(resultEffect.allows(EffectType.SPARKLE));
|
||||
assertFalse(resultEffect.allows(EffectType.NO_EFFECT));
|
||||
assertTrue(resultEffect instanceof TimedEffects);
|
||||
assertNull(((TimedEffects) resultEffect).getDuration());
|
||||
|
||||
target.setTimedEffectsDuration(Duration.ofSeconds(22));
|
||||
assertEquals(Duration.ofSeconds(22), ((TimedEffects) resultEffect).getDuration());
|
||||
|
||||
// source timed effect with duration
|
||||
source = new Resource(ResourceType.LIGHT)
|
||||
.setTimedEffects((TimedEffects) new TimedEffects().setDuration(Duration.ofMillis(44))
|
||||
.setStatusValues(List.of("SUNRISE")).setEffect(EffectType.SUNRISE).setStatusValues(List.of()));
|
||||
target = new Resource(ResourceType.LIGHT);
|
||||
Setters.setResource(target, source);
|
||||
resultEffect = target.getTimedEffects();
|
||||
assertNotNull(resultEffect);
|
||||
assertTrue(resultEffect instanceof TimedEffects);
|
||||
assertEquals(Duration.ofMillis(44), ((TimedEffects) resultEffect).getDuration());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue