diff --git a/bundles/org.openhab.binding.lifx/README.md b/bundles/org.openhab.binding.lifx/README.md index c3cdc9ac16d80..ab5d4f0c7c67f 100644 --- a/bundles/org.openhab.binding.lifx/README.md +++ b/bundles/org.openhab.binding.lifx/README.md @@ -9,46 +9,48 @@ All LIFX lights are directly connected to the WLAN and the binding communicates The following table lists the thing types of the supported LIFX devices: -| Device Type | Thing Type | -|------------------------------|--------------| -| Original 1000 | colorlight | -| Color 650 | colorlight | -| Color 1000 | colorlight | -| Color 1000 BR30 | colorlight | -| LIFX A19 | colorlight | -| LIFX BR30 | colorlight | -| LIFX Candle | colorlight | -| LIFX Clean | colorlight | -| LIFX Downlight | colorlight | -| LIFX GU10 | colorlight | -| LIFX Mini Color | colorlight | -| | | -| LIFX+ A19 | colorirlight | -| LIFX+ BR30 | colorirlight | -| | | -| LIFX Beam | colormzlight | -| LIFX Z | colormzlight | -| | | -| LIFX Tile | tilelight | -| | | -| White 800 (Low Voltage) | whitelight | -| White 800 (High Voltage) | whitelight | -| White 900 BR30 (Low Voltage) | whitelight | -| LIFX Candle Warm to White | whitelight | -| LIFX Filament | whitelight | -| LIFX Mini Day and Dusk | whitelight | -| LIFX Mini White | whitelight | +| Device Type | Thing Type | +|------------------------------|---------------| +| Original 1000 | colorlight | +| Color 650 | colorlight | +| Color 1000 | colorlight | +| Color 1000 BR30 | colorlight | +| LIFX A19 | colorlight | +| LIFX BR30 | colorlight | +| LIFX Candle | colorlight | +| LIFX Downlight | colorlight | +| LIFX GU10 | colorlight | +| LIFX Mini Color | colorlight | +| | | +| LIFX Clean | colorhevlight | +| | | +| LIFX+ A19 | colorirlight | +| LIFX+ BR30 | colorirlight | +| | | +| LIFX Beam | colormzlight | +| LIFX Z | colormzlight | +| | | +| LIFX Tile | tilelight | +| | | +| White 800 (Low Voltage) | whitelight | +| White 800 (High Voltage) | whitelight | +| White 900 BR30 (Low Voltage) | whitelight | +| LIFX Candle Warm to White | whitelight | +| LIFX Filament | whitelight | +| LIFX Mini Day and Dusk | whitelight | +| LIFX Mini White | whitelight | The thing type determines the capability of a device and with that the possible ways of interacting with it. The following matrix lists the capabilities (channels) for each type: -| Thing Type | On/Off | Brightness | Color | Color Zone | Color Temperature | Color Temperature Zone | Infrared | Tile Effects | -|--------------|:------:|:----------:|:-----:|:----------:|:-----------------:|:----------------------:|:--------:|:------------:| -| colorlight | X | | X | | X | | | | -| colorirlight | X | | X | | X | | X | | -| colormzlight | X | | X | X | X | X | | | -| tilelight | X | X | X | | X | | | X | -| whitelight | X | X | | | X | | | | +| Thing Type | On/Off | Brightness | Color | Color Zone | Color Temperature | Color Temperature Zone | HEV Cycle | Infrared | Tile Effects | +|---------------|:------:|:----------:|:-----:|:----------:|:-----------------:|:----------------------:|:---------:|:--------:|:------------:| +| colorlight | X | | X | | X | | | | | +| colorhevlight | X | | X | | X | | X | | | +| colorirlight | X | | X | | X | | | X | | +| colormzlight | X | | X | X | X | X | | | | +| tilelight | X | X | X | | X | | | | X | +| whitelight | X | X | | | X | | | | | ## Discovery @@ -83,39 +85,44 @@ Thing lifx:colorirlight:porch [ host="10.120.130.4", fadetime=0 ] All devices support some of the following channels: -| Channel Type ID | Item Type | Description | Thing Types | -|-----------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------| -| brightness | Dimmer | This channel supports adjusting the brightness value. | whitelight | -| color | Color | This channel supports full color control with hue, saturation and brightness values. | colorlight, colorirlight, colormzlight, tile | -| colorzone | Color | This channel supports full zone color control with hue, saturation and brightness values. | colormzlight | -| effect | String | This channel represents a type of light effect (e.g. for tile light: off, morph, flame) | tilelight | -| infrared | Dimmer | This channel supports adjusting the infrared value. *Note:* IR capable lights only activate their infrared LEDs when the brightness drops below a certain level. | colorirlight | -| signalstrength | Number | This channel represents signal strength with values 0, 1, 2, 3 or 4; 0 being worst strength and 4 being best strength. | colorlight, colorirlight, colormzlight, whitelight, tile | -| temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | colorlight, colorirlight, colormzlight, whitelight, tile | -| temperaturezone | Dimmer | This channel supports adjusting the zone color temperature from cold (0%) to warm (100%). | colormzlight | - -The *color* and *brightness* channels have a "Power on brightness" configuration option that is used to determine the brightness when a light is switched on. +| Channel Type ID | Item Type | Description | Thing Types | +|-----------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------| +| brightness | Dimmer | This channel supports adjusting the brightness value. | whitelight | +| color | Color | This channel supports full color control with hue, saturation and brightness values. | colorlight, colorhevlight, colorirlight, colormzlight, tilelight | +| colorzone | Color | This channel supports full zone color control with hue, saturation and brightness values. | colormzlight | +| effect | String | This channel represents a type of light effect (e.g. for tile light: off, morph, flame) | tilelight | +| hevcycle | Switch | This channel supports starting and stopping the HEV clean cycle. | colorhevlight | +| infrared | Dimmer | This channel supports adjusting the infrared value. *Note:* IR capable lights only activate their infrared LEDs when the brightness drops below a certain level. | colorirlight | +| signalstrength | Number | This channel represents signal strength with values 0, 1, 2, 3 or 4; 0 being worst strength and 4 being best strength. | colorlight, colorhevlight, colorirlight, colormzlight, tilelight, whitelight | +| temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | colorlight, colorhevlight, colorirlight, colormzlight, tilelight, whitelight | +| temperaturezone | Dimmer | This channel supports adjusting the zone color temperature from cold (0%) to warm (100%). | colormzlight | + +The *color* and *brightness* channels have a "Power On Brightness" configuration option that is used to determine the brightness when a light is switched on. When it is left empty, the brightness of a light remains unchanged when a light is switched on or off. -The *color* channels have a "Power on color" configuration option that is used to determine the hue, saturation, brightness levels when a light is switched on. +The *color* channels have a "Power On Color" configuration option that is used to determine the hue, saturation, brightness levels when a light is switched on. When it is left empty, the color of a light remains unchanged when a light is switched on or off. Configuration options contains 3 comma separated values, where first value is hue (0-360), second saturation (0-100) and third brightness (0-100). -If both "Power on brightness" and "Power on color" configuration options are defined, "Power on brightness" option overrides the brightness level defined on the "Power on color" configuration option. +If both "Power on brightness" and "Power On Color" configuration options are defined, "Power on brightness" option overrides the brightness level defined on the "Power on color" configuration option. -The *temperature* channels have a "Power on temperature" configuration option that is used to determine the color temperature when a light is switched on. When it is left empty, the color temperature of a light remains unchanged when a light is switched on or off. +The *temperature* channels have a "Power On Temperature" configuration option that is used to determine the color temperature when a light is switched on. When it is left empty, the color temperature of a light remains unchanged when a light is switched on or off. -MultiZone lights (*colormzlight*) have serveral channels (e.g. *colorzone0*, *temperaturezone0*, etc.) that allow for controlling specific zones of the light. +MultiZone lights (*colormzlight*) have several channels (e.g. *colorzone0*, *temperaturezone0*, etc.) that allow for controlling specific zones of the light. Changing the *color* and *temperature* channels will update the states of all zones. The *color* and *temperature* channels of MultiZone lights always return the same state as *colorzone0*, *temperaturezone0*. +The *hevcycle* channels have an optional "HEV Cycle Duration" configuration option that can be used to override the cycle duration configured in the light. + LIFX Tile (*tilelight*) supports special tile effects: morph and flame. These effects are predefined to their appearance using LIFX application. -Each effect has a separate speed configurable. +Each effect has a separate speed configuration option. ## Full Example In this example **living** is a Color 1000 light that has a *colorlight* thing type which supports *color* and *temperature* channels. +The **desk** light is a LIFX Clean that has a *colorhevlight* thing type which supports *color*, *temperature* and *hevcycle* channels. + The **porch** light is a LIFX+ BR30 that has a *colorirlight* thing type which supports *color*, *temperature* and *infrared* channels. The **ceiling** light is a LIFX Z with 2 strips (16 zones) that has a *colormzlight* thing type which supports *color*, *colorzone*, *temperature* and *temperaturezone* channels. @@ -136,6 +143,11 @@ Thing lifx:colorlight:living2 [ deviceId="D073D5A2A2A2" ] { Type color : color [ powerOnBrightness=50 ] } +Thing lifx:colorhevlight:desk [ deviceId="D073D5A3A3A3" ] { + Channels: + Type hevcycle : hevcycle [ hevCycleDuration=3600 ] +} + Thing lifx:colorirlight:porch [ deviceId="D073D5B2B2B2", host="10.120.130.4", fadetime=0 ] { Channels: Type color : color [ powerOnBrightness=75 ] @@ -169,6 +181,11 @@ Switch Living2_Switch { channel="lifx:colorlight:living2:color" } Dimmer Living2_Dimmer { channel="lifx:colorlight:living2:color" } Dimmer Living2_Temperature { channel="lifx:colorlight:living2:temperature" } +// Desk +Color Desk_Color { channel="lifx:colorhevlight:desk:color" } +Dimmer Desk_Temperature { channel="lifx:colorhevlight:desk:temperature" } +Switch Desk_HEV_Cycle { channel="lifx:colorhevlight:desk:hevcycle" } + // Porch Color Porch_Color { channel="lifx:colorirlight:porch:color" } Dimmer Porch_Infrared { channel="lifx:colorirlight:porch:infrared" } @@ -208,6 +225,14 @@ sitemap demo label="Main Menu" Slider item=Living2_Temperature } + Frame label="Desk" { + Switch item=Desk_Color + Slider item=Desk_Color + Colorpicker item=Desk_Color + Slider item=Desk_Temperature + Switch item=Desk_HEV_Cycle + } + Frame label="Porch" { Switch item=Porch_Color Slider item=Porch_Color diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java index 7478fd52db23c..1274479961de9 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java @@ -13,8 +13,6 @@ package org.openhab.binding.lifx.internal; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.lifx.internal.fields.HSBK; @@ -55,6 +53,7 @@ public class LifxBindingConstants { public static final String CHANNEL_COLOR = "color"; public static final String CHANNEL_COLOR_ZONE = "colorzone"; public static final String CHANNEL_EFFECT = "effect"; + public static final String CHANNEL_HEV_CYCLE = "hevcycle"; public static final String CHANNEL_INFRARED = "infrared"; public static final String CHANNEL_SIGNAL_STRENGTH = "signalstrength"; public static final String CHANNEL_TEMPERATURE = "temperature"; @@ -80,11 +79,12 @@ public class LifxBindingConstants { public static final String CONFIG_PROPERTY_FADETIME = "fadetime"; // Config property for channel configuration + public static final String CONFIG_PROPERTY_HEV_CYCLE_DURATION = "hevCycleDuration"; + public static final String CONFIG_PROPERTY_EFFECT_FLAME_SPEED = "effectFlameSpeed"; + public static final String CONFIG_PROPERTY_EFFECT_MORPH_SPEED = "effectMorphSpeed"; public static final String CONFIG_PROPERTY_POWER_ON_BRIGHTNESS = "powerOnBrightness"; public static final String CONFIG_PROPERTY_POWER_ON_COLOR = "powerOnColor"; public static final String CONFIG_PROPERTY_POWER_ON_TEMPERATURE = "powerOnTemperature"; - public static final String CONFIG_PROPERTY_EFFECT_MORPH_SPEED = "effectMorphSpeed"; - public static final String CONFIG_PROPERTY_EFFECT_FLAME_SPEED = "effectFlameSpeed"; // Property keys public static final String PROPERTY_HOST = "host"; @@ -100,12 +100,13 @@ public class LifxBindingConstants { // List of all Thing Type UIDs public static final ThingTypeUID THING_TYPE_COLORLIGHT = new ThingTypeUID(BINDING_ID, "colorlight"); + public static final ThingTypeUID THING_TYPE_COLORHEVLIGHT = new ThingTypeUID(BINDING_ID, "colorhevlight"); public static final ThingTypeUID THING_TYPE_COLORIRLIGHT = new ThingTypeUID(BINDING_ID, "colorirlight"); public static final ThingTypeUID THING_TYPE_COLORMZLIGHT = new ThingTypeUID(BINDING_ID, "colormzlight"); - public static final ThingTypeUID THING_TYPE_WHITELIGHT = new ThingTypeUID(BINDING_ID, "whitelight"); public static final ThingTypeUID THING_TYPE_TILELIGHT = new ThingTypeUID(BINDING_ID, "tilelight"); + public static final ThingTypeUID THING_TYPE_WHITELIGHT = new ThingTypeUID(BINDING_ID, "whitelight"); - public static final Set SUPPORTED_THING_TYPES = Stream.of(THING_TYPE_COLORLIGHT, - THING_TYPE_COLORIRLIGHT, THING_TYPE_COLORMZLIGHT, THING_TYPE_WHITELIGHT, THING_TYPE_TILELIGHT) - .collect(Collectors.toSet()); + public static final Set SUPPORTED_THING_TYPES = Set.of(THING_TYPE_COLORLIGHT, + THING_TYPE_COLORHEVLIGHT, THING_TYPE_COLORIRLIGHT, THING_TYPE_COLORMZLIGHT, THING_TYPE_TILELIGHT, + THING_TYPE_WHITELIGHT); } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCurrentStateUpdater.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCurrentStateUpdater.java index ef6ad12b69152..5e42fb2fd946a 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCurrentStateUpdater.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCurrentStateUpdater.java @@ -25,11 +25,14 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.lifx.internal.LifxProduct.Features; import org.openhab.binding.lifx.internal.dto.GetColorZonesRequest; +import org.openhab.binding.lifx.internal.dto.GetHevCycleRequest; import org.openhab.binding.lifx.internal.dto.GetLightInfraredRequest; import org.openhab.binding.lifx.internal.dto.GetRequest; import org.openhab.binding.lifx.internal.dto.GetTileEffectRequest; import org.openhab.binding.lifx.internal.dto.GetWifiInfoRequest; +import org.openhab.binding.lifx.internal.dto.HevCycleState; import org.openhab.binding.lifx.internal.dto.Packet; +import org.openhab.binding.lifx.internal.dto.StateHevCycleResponse; import org.openhab.binding.lifx.internal.dto.StateLightInfraredResponse; import org.openhab.binding.lifx.internal.dto.StateLightPowerResponse; import org.openhab.binding.lifx.internal.dto.StateMultiZoneResponse; @@ -133,6 +136,9 @@ public void stop() { private void sendLightStateRequests() { communicationHandler.sendPacket(new GetRequest()); + if (features.hasFeature(HEV)) { + communicationHandler.sendPacket(new GetHevCycleRequest()); + } if (features.hasFeature(INFRARED)) { communicationHandler.sendPacket(new GetLightInfraredRequest()); } @@ -157,14 +163,16 @@ public void handleResponsePacket(Packet packet) { handlePowerStatus((StatePowerResponse) packet); } else if (packet instanceof StateLightPowerResponse) { handleLightPowerStatus((StateLightPowerResponse) packet); + } else if (packet instanceof StateHevCycleResponse) { + handleHevCycleStatus((StateHevCycleResponse) packet); } else if (packet instanceof StateLightInfraredResponse) { handleInfraredStatus((StateLightInfraredResponse) packet); } else if (packet instanceof StateMultiZoneResponse) { handleMultiZoneStatus((StateMultiZoneResponse) packet); - } else if (packet instanceof StateWifiInfoResponse) { - handleWifiInfoStatus((StateWifiInfoResponse) packet); } else if (packet instanceof StateTileEffectResponse) { handleTileEffectStatus((StateTileEffectResponse) packet); + } else if (packet instanceof StateWifiInfoResponse) { + handleWifiInfoStatus((StateWifiInfoResponse) packet); } currentLightState.setOnline(); @@ -192,6 +200,11 @@ private void handleLightPowerStatus(StateLightPowerResponse packet) { currentLightState.setPowerState(packet.getState()); } + private void handleHevCycleStatus(StateHevCycleResponse packet) { + HevCycleState hevCycleState = new HevCycleState(!packet.getRemaining().isZero(), packet.getDuration()); + currentLightState.setHevCycleState(hevCycleState); + } + private void handleInfraredStatus(StateLightInfraredResponse packet) { PercentType infrared = infraredToPercentType(packet.getInfrared()); currentLightState.setInfrared(infrared); @@ -209,11 +222,11 @@ private void handleMultiZoneStatus(StateMultiZoneResponse packet) { currentLightState.setColors(colors); } - private void handleWifiInfoStatus(StateWifiInfoResponse packet) { - currentLightState.setSignalStrength(packet.getSignalStrength()); - } - private void handleTileEffectStatus(StateTileEffectResponse packet) { currentLightState.setTileEffect(packet.getEffect()); } + + private void handleWifiInfoStatus(StateWifiInfoResponse packet) { + currentLightState.setSignalStrength(packet.getSignalStrength()); + } } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java index b3bbefaf201a7..0d52ba0c757ad 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java @@ -23,6 +23,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.lifx.internal.dto.Effect; +import org.openhab.binding.lifx.internal.dto.HevCycleState; import org.openhab.binding.lifx.internal.dto.PowerState; import org.openhab.binding.lifx.internal.dto.SignalStrength; import org.openhab.binding.lifx.internal.fields.HSBK; @@ -40,6 +41,7 @@ public class LifxLightState { private HSBK[] colors = new HSBK[] { new HSBK(DEFAULT_COLOR) }; + private @Nullable HevCycleState hevCycleState; private @Nullable PercentType infrared; private @Nullable PowerState powerState; private @Nullable SignalStrength signalStrength; @@ -51,6 +53,7 @@ public class LifxLightState { public void copy(LifxLightState other) { this.powerState = other.getPowerState(); this.colors = other.getColors(); + this.hevCycleState = other.getHevCycleState(); this.infrared = other.getInfrared(); this.signalStrength = other.getSignalStrength(); this.tileEffect = other.getTileEffect(); @@ -76,6 +79,10 @@ public HSBK[] getColors() { return colorsCopy; } + public @Nullable HevCycleState getHevCycleState() { + return hevCycleState; + } + public @Nullable PercentType getInfrared() { return infrared; } @@ -158,6 +165,13 @@ public void setTemperature(int kelvin, int zoneIndex) { setColor(newColor, zoneIndex); } + public void setHevCycleState(HevCycleState newHevCycleState) { + HevCycleState oldHevCycleState = this.hevCycleState; + this.hevCycleState = newHevCycleState; + updateLastChange(); + listeners.forEach(listener -> listener.handleHevCycleStateChange(oldHevCycleState, newHevCycleState)); + } + public void setInfrared(PercentType newInfrared) { PercentType oldInfrared = this.infrared; this.infrared = newInfrared; diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java index dbccb2113b5d7..2a7bc6b569faa 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java @@ -34,13 +34,16 @@ import org.openhab.binding.lifx.internal.dto.ApplicationRequest; import org.openhab.binding.lifx.internal.dto.Effect; import org.openhab.binding.lifx.internal.dto.GetColorZonesRequest; +import org.openhab.binding.lifx.internal.dto.GetHevCycleRequest; import org.openhab.binding.lifx.internal.dto.GetLightInfraredRequest; import org.openhab.binding.lifx.internal.dto.GetLightPowerRequest; import org.openhab.binding.lifx.internal.dto.GetRequest; +import org.openhab.binding.lifx.internal.dto.HevCycleState; import org.openhab.binding.lifx.internal.dto.Packet; import org.openhab.binding.lifx.internal.dto.PowerState; import org.openhab.binding.lifx.internal.dto.SetColorRequest; import org.openhab.binding.lifx.internal.dto.SetColorZonesRequest; +import org.openhab.binding.lifx.internal.dto.SetHevCycleRequest; import org.openhab.binding.lifx.internal.dto.SetLightInfraredRequest; import org.openhab.binding.lifx.internal.dto.SetLightPowerRequest; import org.openhab.binding.lifx.internal.dto.SetPowerRequest; @@ -308,6 +311,17 @@ public void handlePowerStateChange(@Nullable PowerState oldPowerState, PowerStat } } + @Override + public void handleHevCycleStateChange(@Nullable HevCycleState oldHevCycleState, HevCycleState newHevCycleState) { + // The change should be ignored when both the old and new state are disabled regardless of the cycle duration + if (!newHevCycleState.equals(oldHevCycleState) + && (oldHevCycleState == null || oldHevCycleState.isEnable() || newHevCycleState.isEnable())) { + SetHevCycleRequest packet = new SetHevCycleRequest(newHevCycleState.isEnable(), + newHevCycleState.getDuration()); + replacePacketsInMap(packet); + } + } + @Override public void handleInfraredChange(@Nullable PercentType oldInfrared, PercentType newInfrared) { PercentType infrared = pendingLightState.getInfrared(); @@ -325,7 +339,7 @@ public void handleSignalStrengthChange(@Nullable SignalStrength oldSignalStrengt @Override public void handleTileEffectChange(@Nullable Effect oldEffect, Effect newEffect) { - if (oldEffect == null || !oldEffect.equals(newEffect)) { + if (!newEffect.equals(oldEffect)) { SetTileEffectRequest packet = new SetTileEffectRequest(newEffect); replacePacketsInMap(packet); } @@ -360,6 +374,13 @@ public void handleResponsePacket(Packet packet) { getZonesIfZonesAreSet(); } else if (sentPacket instanceof SetColorZonesRequest) { getZonesIfZonesAreSet(); + } else if (sentPacket instanceof SetHevCycleRequest) { + scheduler.schedule(() -> { + GetHevCycleRequest hevCyclePacket = new GetHevCycleRequest(); + communicationHandler.sendPacket(hevCyclePacket); + GetLightPowerRequest powerPacket = new GetLightPowerRequest(); + communicationHandler.sendPacket(powerPacket); + }, 600, TimeUnit.MILLISECONDS); } else if (sentPacket instanceof SetLightInfraredRequest) { GetLightInfraredRequest infraredPacket = new GetLightInfraredRequest(); communicationHandler.sendPacket(infraredPacket); diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java index 945601109ed53..0cccb64928e9d 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxProduct.java @@ -371,12 +371,14 @@ public Features getFeatures(String version) { public ThingTypeUID getThingTypeUID() { if (hasFeature(COLOR)) { - if (hasFeature(TILE_EFFECT)) { - return LifxBindingConstants.THING_TYPE_TILELIGHT; + if (hasFeature(HEV)) { + return LifxBindingConstants.THING_TYPE_COLORHEVLIGHT; } else if (hasFeature(INFRARED)) { return LifxBindingConstants.THING_TYPE_COLORIRLIGHT; } else if (hasFeature(MULTIZONE)) { return LifxBindingConstants.THING_TYPE_COLORMZLIGHT; + } else if (hasFeature(TILE_EFFECT)) { + return LifxBindingConstants.THING_TYPE_TILELIGHT; } else { return LifxBindingConstants.THING_TYPE_COLORLIGHT; } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetHevCycleConfigurationRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetHevCycleConfigurationRequest.java new file mode 100644 index 0000000000000..69c78468b7b0c --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetHevCycleConfigurationRequest.java @@ -0,0 +1,54 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; + +/** + * @author Wouter Born - Initial contribution + */ +public class GetHevCycleConfigurationRequest extends Packet { + + public static final int TYPE = 0x91; + + public GetHevCycleConfigurationRequest() { + setTagged(false); + setAddressable(true); + setResponseRequired(true); + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 0; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + // do nothing + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(0); + } + + @Override + public int[] expectedResponses() { + return new int[] { StateHevCycleConfigurationResponse.TYPE }; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetHevCycleRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetHevCycleRequest.java new file mode 100644 index 0000000000000..eb24879180021 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetHevCycleRequest.java @@ -0,0 +1,54 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; + +/** + * @author Wouter Born - Initial contribution + */ +public class GetHevCycleRequest extends Packet { + + public static final int TYPE = 0x8E; + + public GetHevCycleRequest() { + setTagged(false); + setAddressable(true); + setResponseRequired(true); + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 0; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + // do nothing + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(0); + } + + @Override + public int[] expectedResponses() { + return new int[] { StateHevCycleResponse.TYPE }; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetLastHevCycleResultRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetLastHevCycleResultRequest.java new file mode 100644 index 0000000000000..476da0f2d2f97 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/GetLastHevCycleResultRequest.java @@ -0,0 +1,54 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; + +/** + * @author Wouter Born - Initial contribution + */ +public class GetLastHevCycleResultRequest extends Packet { + + public static final int TYPE = 0x94; + + public GetLastHevCycleResultRequest() { + setTagged(false); + setAddressable(true); + setResponseRequired(true); + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 0; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + // do nothing + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(0); + } + + @Override + public int[] expectedResponses() { + return new int[] { StateLastHevCycleResultResponse.TYPE }; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/HevCycleState.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/HevCycleState.java new file mode 100644 index 0000000000000..75b5e863c3d92 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/HevCycleState.java @@ -0,0 +1,86 @@ +/** + * 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.lifx.internal.dto; + +import java.time.Duration; + +/** + * The pending or current HEV cycle state. + * + * @author Wouter Born - Initial contribution + */ +public class HevCycleState { + + public static final HevCycleState OFF = new HevCycleState(false); + public static final HevCycleState ON = new HevCycleState(true); + + private boolean enable; + private Duration duration; + + public HevCycleState(boolean enable) { + this.enable = enable; + this.duration = Duration.ZERO; + } + + public HevCycleState(boolean enable, Duration duration) { + this.enable = enable; + this.duration = duration; + } + + public boolean isEnable() { + return enable; + } + + public Duration getDuration() { + return duration; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((duration == null) ? 0 : duration.hashCode()); + result = prime * result + (enable ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + HevCycleState other = (HevCycleState) obj; + if (duration == null) { + if (other.duration != null) { + return false; + } + } else if (!duration.equals(other.duration)) { + return false; + } + if (enable != other.enable) { + return false; + } + return true; + } + + @Override + public String toString() { + return "HevCycleState [enable=" + enable + ", duration=" + duration + "]"; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/LightLastHevCycleResult.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/LightLastHevCycleResult.java new file mode 100644 index 0000000000000..14cde69f9b064 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/LightLastHevCycleResult.java @@ -0,0 +1,50 @@ +/** + * 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.lifx.internal.dto; + +import java.util.Arrays; +import java.util.Optional; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Wouter Born - Initial contribution + */ +@NonNullByDefault +public enum LightLastHevCycleResult { + + SUCCESS(0), + BUSY(1), + INTERRUPTED_BY_RESET(2), + INTERRUPTED_BY_HOMEKIT(3), + INTERRUPTED_BY_LAN(4), + INTERRUPTED_BY_CLOUD(5), + NONE(255); + + private final int type; + + LightLastHevCycleResult(int type) { + this.type = type; + } + + public static LightLastHevCycleResult fromValue(int type) { + Optional result = Arrays.stream(values()).filter((value) -> value.type == type) + .findFirst(); + + if (!result.isPresent()) { + throw new IllegalArgumentException("Invalid LightLastHevCycleResult type: " + type); + } + + return result.get(); + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/PacketFactory.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/PacketFactory.java index ba9ea39f0f4c3..bd68da0fd7156 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/PacketFactory.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/PacketFactory.java @@ -52,10 +52,13 @@ private PacketFactory() { register(GetColorZonesRequest.class); register(GetEchoRequest.class); register(GetGroupRequest.class); + register(GetHevCycleConfigurationRequest.class); + register(GetHevCycleRequest.class); register(GetHostFirmwareRequest.class); register(GetHostInfoRequest.class); register(GetInfoRequest.class); register(GetLabelRequest.class); + register(GetLastHevCycleResultRequest.class); register(GetLightInfraredRequest.class); register(GetLightPowerRequest.class); register(GetLocationRequest.class); @@ -71,16 +74,21 @@ private PacketFactory() { register(SetColorRequest.class); register(SetColorZonesRequest.class); register(SetDimAbsoluteRequest.class); + register(SetHevCycleRequest.class); + register(SetHevCycleConfigurationRequest.class); register(SetLabelRequest.class); register(SetLightInfraredRequest.class); register(SetLightPowerRequest.class); register(SetPowerRequest.class); register(SetTagsRequest.class); register(StateGroupResponse.class); + register(StateHevCycleConfigurationResponse.class); + register(StateHevCycleResponse.class); register(StateHostFirmwareResponse.class); register(StateHostInfoResponse.class); register(StateInfoResponse.class); register(StateLabelResponse.class); + register(StateLastHevCycleResultResponse.class); register(StateLightInfraredResponse.class); register(StateLightPowerResponse.class); register(StateLocationResponse.class); diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/SetHevCycleConfigurationRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/SetHevCycleConfigurationRequest.java new file mode 100644 index 0000000000000..3dcab88dddf7f --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/SetHevCycleConfigurationRequest.java @@ -0,0 +1,81 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; +import java.time.Duration; + +import org.openhab.binding.lifx.internal.fields.BoolIntField; +import org.openhab.binding.lifx.internal.fields.Field; +import org.openhab.binding.lifx.internal.fields.UInt32Field; + +/** + * @author Wouter Born - Initial contribution + */ +public class SetHevCycleConfigurationRequest extends Packet { + + public static final int TYPE = 0x92; + + public static final Field FIELD_INDICATION = new BoolIntField(); + public static final Field FIELD_DURATION = new UInt32Field().little(); + + private boolean indication; + private long duration; + + public boolean isIndication() { + return indication; + } + + public Duration getDuration() { + return Duration.ofSeconds(duration); + } + + public SetHevCycleConfigurationRequest() { + setTagged(false); + setAddressable(true); + setResponseRequired(true); + } + + public SetHevCycleConfigurationRequest(boolean indication, Duration duration) { + this(); + this.indication = indication; + this.duration = duration.toSeconds(); + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 5; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + indication = FIELD_INDICATION.value(bytes); + duration = FIELD_DURATION.value(bytes); + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(packetLength()).put(FIELD_INDICATION.bytes(indication)) + .put(FIELD_DURATION.bytes(duration)); + } + + @Override + public int[] expectedResponses() { + return new int[] { StateHevCycleConfigurationResponse.TYPE }; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/SetHevCycleRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/SetHevCycleRequest.java new file mode 100644 index 0000000000000..5c062353b1301 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/SetHevCycleRequest.java @@ -0,0 +1,85 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; +import java.time.Duration; + +import org.openhab.binding.lifx.internal.fields.BoolIntField; +import org.openhab.binding.lifx.internal.fields.Field; +import org.openhab.binding.lifx.internal.fields.UInt32Field; + +/** + * @author Wouter Born - Initial contribution + */ +public class SetHevCycleRequest extends Packet { + + public static final int TYPE = 0x8F; + + public static final Field FIELD_ENABLE = new BoolIntField(); + public static final Field FIELD_DURATION = new UInt32Field().little(); + + private boolean enable; + private long duration; + + public boolean isEnable() { + return enable; + } + + public Duration getDuration() { + return Duration.ofSeconds(duration); + } + + public SetHevCycleRequest() { + setTagged(false); + setAddressable(true); + setResponseRequired(true); + } + + public SetHevCycleRequest(boolean enable) { + this(); + this.enable = enable; + } + + public SetHevCycleRequest(boolean enable, Duration duration) { + this(); + this.enable = enable; + this.duration = duration.toSeconds(); + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 5; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + enable = FIELD_ENABLE.value(bytes); + duration = FIELD_DURATION.value(bytes); + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(packetLength()).put(FIELD_ENABLE.bytes(enable)).put(FIELD_DURATION.bytes(duration)); + } + + @Override + public int[] expectedResponses() { + return new int[] { StateHevCycleResponse.TYPE }; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateHevCycleConfigurationResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateHevCycleConfigurationResponse.java new file mode 100644 index 0000000000000..1b2fd2c5165ad --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateHevCycleConfigurationResponse.java @@ -0,0 +1,69 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; +import java.time.Duration; + +import org.openhab.binding.lifx.internal.fields.BoolIntField; +import org.openhab.binding.lifx.internal.fields.Field; +import org.openhab.binding.lifx.internal.fields.UInt32Field; + +/** + * @author Wouter Born - Initial contribution + */ +public class StateHevCycleConfigurationResponse extends Packet { + + public static final int TYPE = 0x93; + + public static final Field FIELD_INDICATION = new BoolIntField(); + public static final Field FIELD_DURATION = new UInt32Field().little(); + + private boolean indication; + private long duration; + + public boolean isIndication() { + return indication; + } + + public Duration getDuration() { + return Duration.ofSeconds(duration); + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 5; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + indication = FIELD_INDICATION.value(bytes); + duration = FIELD_DURATION.value(bytes); + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(packetLength()).put(FIELD_INDICATION.bytes(indication)) + .put(FIELD_DURATION.bytes(duration)); + } + + @Override + public int[] expectedResponses() { + return new int[] {}; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateHevCycleResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateHevCycleResponse.java new file mode 100644 index 0000000000000..92e2b022be8cf --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateHevCycleResponse.java @@ -0,0 +1,76 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; +import java.time.Duration; + +import org.openhab.binding.lifx.internal.fields.BoolIntField; +import org.openhab.binding.lifx.internal.fields.Field; +import org.openhab.binding.lifx.internal.fields.UInt32Field; + +/** + * @author Wouter Born - Initial contribution + */ +public class StateHevCycleResponse extends Packet { + + public static final int TYPE = 0x90; + + public static final Field FIELD_DURATION = new UInt32Field().little(); + public static final Field FIELD_REMAINING = new UInt32Field().little(); + public static final Field FIELD_LAST_POWER = new BoolIntField(); + + private long duration; + private long remaining; + private boolean lastPower; + + public Duration getDuration() { + return Duration.ofSeconds(duration); + } + + public Duration getRemaining() { + return Duration.ofSeconds(remaining); + } + + public boolean isLastPower() { + return lastPower; + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 9; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + duration = FIELD_DURATION.value(bytes); + remaining = FIELD_REMAINING.value(bytes); + lastPower = FIELD_LAST_POWER.value(bytes); + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(packetLength()).put(FIELD_DURATION.bytes(duration)) + .put(FIELD_REMAINING.bytes(remaining)).put(FIELD_LAST_POWER.bytes(lastPower)); + } + + @Override + public int[] expectedResponses() { + return new int[] {}; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateLastHevCycleResultResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateLastHevCycleResultResponse.java new file mode 100644 index 0000000000000..6f80659ba83c7 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/dto/StateLastHevCycleResultResponse.java @@ -0,0 +1,59 @@ +/** + * 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.lifx.internal.dto; + +import java.nio.ByteBuffer; + +import org.openhab.binding.lifx.internal.fields.Field; +import org.openhab.binding.lifx.internal.fields.UInt8Field; + +/** + * @author Wouter Born - Initial contribution + */ +public class StateLastHevCycleResultResponse extends Packet { + + public static final int TYPE = 0x95; + + public static final Field FIELD_RESULT = new UInt8Field().little(); + + private int result; + + public LightLastHevCycleResult getResult() { + return LightLastHevCycleResult.fromValue(result); + } + + @Override + public int packetType() { + return TYPE; + } + + @Override + protected int packetLength() { + return 1; + } + + @Override + protected void parsePacket(ByteBuffer bytes) { + result = FIELD_RESULT.value(bytes); + } + + @Override + protected ByteBuffer packetBytes() { + return ByteBuffer.allocate(packetLength()).put(FIELD_RESULT.bytes(result)); + } + + @Override + public int[] expectedResponses() { + return new int[] {}; + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/BoolIntField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/BoolIntField.java new file mode 100644 index 0000000000000..037e5c30267b6 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/BoolIntField.java @@ -0,0 +1,43 @@ +/** + * 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.lifx.internal.fields; + +import java.nio.ByteBuffer; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Wouter Born - Initial contribution + */ +@NonNullByDefault +public class BoolIntField extends Field { + + public BoolIntField() { + super(1); + } + + @Override + public int defaultLength() { + return 1; + } + + @Override + public Boolean value(ByteBuffer bytes) { + return bytes.get() == 1; + } + + @Override + public ByteBuffer bytesInternal(Boolean value) { + return ByteBuffer.allocate(1).put((byte) (value ? 1 : 0)); + } +} diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java index fd0684298003c..9be4f24b4a84f 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -42,11 +43,13 @@ import org.openhab.binding.lifx.internal.LifxProduct; import org.openhab.binding.lifx.internal.LifxProduct.Features; import org.openhab.binding.lifx.internal.dto.Effect; +import org.openhab.binding.lifx.internal.dto.GetHevCycleRequest; import org.openhab.binding.lifx.internal.dto.GetLightInfraredRequest; import org.openhab.binding.lifx.internal.dto.GetLightPowerRequest; import org.openhab.binding.lifx.internal.dto.GetRequest; import org.openhab.binding.lifx.internal.dto.GetTileEffectRequest; import org.openhab.binding.lifx.internal.dto.GetWifiInfoRequest; +import org.openhab.binding.lifx.internal.dto.HevCycleState; import org.openhab.binding.lifx.internal.dto.Packet; import org.openhab.binding.lifx.internal.dto.PowerState; import org.openhab.binding.lifx.internal.dto.SignalStrength; @@ -94,6 +97,7 @@ public class LifxLightHandler extends BaseThingHandler { private final LifxChannelFactory channelFactory; private @NonNullByDefault({}) Features features; + private Duration hevCycleDuration = Duration.ZERO; private @Nullable PercentType powerOnBrightness; private @Nullable HSBType powerOnColor; private @Nullable PercentType powerOnTemperature; @@ -191,6 +195,14 @@ private HSBK nullSafeUpdateColor(@Nullable PowerState powerState, @Nullable HSBK return updateColor; } + @Override + public void setHevCycleState(HevCycleState hevCycleState) { + if (!isStateChangePending() || hevCycleState.equals(pendingLightState.getHevCycleState())) { + updateStateIfChanged(CHANNEL_HEV_CYCLE, OnOffType.from(hevCycleState.isEnable())); + } + super.setHevCycleState(hevCycleState); + } + @Override public void setInfrared(PercentType infrared) { if (!isStateChangePending() || infrared.equals(pendingLightState.getInfrared())) { @@ -263,6 +275,8 @@ public void initialize() { if (speed != null) { effectFlameSpeed = speed; } + hevCycleDuration = getHevCycleDuration(); + channelStates.clear(); currentLightState = new CurrentLightState(); pendingLightState = new LifxLightState(); @@ -410,6 +424,19 @@ public String getLogId(@Nullable MACAddress macAddress, @Nullable InetSocketAddr return speed == null ? null : Double.valueOf(speed.toString()); } + private Duration getHevCycleDuration() { + ChannelUID channelUID = new ChannelUID(getThing().getUID(), LifxBindingConstants.CHANNEL_HEV_CYCLE); + Channel channel = getThing().getChannel(channelUID.getId()); + + if (channel == null) { + return Duration.ZERO; + } + + Configuration configuration = channel.getConfiguration(); + Object duration = configuration.get(LifxBindingConstants.CONFIG_PROPERTY_HEV_CYCLE_DURATION); + return duration == null ? Duration.ZERO : Duration.ofSeconds(Integer.valueOf(duration.toString())); + } + private Features getFeatures() { LifxProduct product = getProduct(); @@ -486,121 +513,129 @@ private void sendPacket(Packet packet) { @Override public void handleCommand(ChannelUID channelUID, Command command) { if (command instanceof RefreshType) { - channelStates.remove(channelUID.getId()); - switch (channelUID.getId()) { - case CHANNEL_COLOR: - case CHANNEL_BRIGHTNESS: - sendPacket(new GetLightPowerRequest()); - sendPacket(new GetRequest()); - break; - case CHANNEL_TEMPERATURE: - sendPacket(new GetRequest()); - break; - case CHANNEL_INFRARED: - sendPacket(new GetLightInfraredRequest()); - break; - case CHANNEL_SIGNAL_STRENGTH: - sendPacket(new GetWifiInfoRequest()); - break; - case CHANNEL_EFFECT: - if (features.hasFeature(TILE_EFFECT)) { - sendPacket(new GetTileEffectRequest()); - } - break; - default: - break; - } + handleRefreshCommand(channelUID); } else { - boolean supportedCommand = true; - switch (channelUID.getId()) { - case CHANNEL_COLOR: - if (command instanceof HSBType) { - handleHSBCommand((HSBType) command); - } else if (command instanceof PercentType) { - handlePercentCommand((PercentType) command); - } else if (command instanceof OnOffType) { - handleOnOffCommand((OnOffType) command); - } else if (command instanceof IncreaseDecreaseType) { - handleIncreaseDecreaseCommand((IncreaseDecreaseType) command); - } else { - supportedCommand = false; - } - break; - case CHANNEL_BRIGHTNESS: - if (command instanceof PercentType) { - handlePercentCommand((PercentType) command); - } else if (command instanceof OnOffType) { - handleOnOffCommand((OnOffType) command); - } else if (command instanceof IncreaseDecreaseType) { - handleIncreaseDecreaseCommand((IncreaseDecreaseType) command); - } else { - supportedCommand = false; - } - break; - case CHANNEL_TEMPERATURE: - if (command instanceof PercentType) { - handleTemperatureCommand((PercentType) command); - } else if (command instanceof IncreaseDecreaseType) { - handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command); - } else { - supportedCommand = false; - } - break; - case CHANNEL_INFRARED: - if (command instanceof PercentType) { - handleInfraredCommand((PercentType) command); - } else if (command instanceof IncreaseDecreaseType) { - handleIncreaseDecreaseInfraredCommand((IncreaseDecreaseType) command); - } else { - supportedCommand = false; - } - break; - case CHANNEL_EFFECT: - if (command instanceof StringType && features.hasFeature(TILE_EFFECT)) { - handleTileEffectCommand((StringType) command); - } else { - supportedCommand = false; - } - break; - default: - try { - if (channelUID.getId().startsWith(CHANNEL_COLOR_ZONE)) { - int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_COLOR_ZONE, "")); - if (command instanceof HSBType) { - handleHSBCommand((HSBType) command, zoneIndex); - } else if (command instanceof PercentType) { - handlePercentCommand((PercentType) command, zoneIndex); - } else if (command instanceof IncreaseDecreaseType) { - handleIncreaseDecreaseCommand((IncreaseDecreaseType) command, zoneIndex); - } else { - supportedCommand = false; - } - } else if (channelUID.getId().startsWith(CHANNEL_TEMPERATURE_ZONE)) { - int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_TEMPERATURE_ZONE, "")); - if (command instanceof PercentType) { - handleTemperatureCommand((PercentType) command, zoneIndex); - } else if (command instanceof IncreaseDecreaseType) { - handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command, zoneIndex); - } else { - supportedCommand = false; - } - } else { - supportedCommand = false; - } - } catch (NumberFormatException e) { - logger.error("Failed to parse zone index for a command of a light ({}) : {}", logId, - e.getMessage()); - supportedCommand = false; - } - break; + Runnable channelCommandRunnable = getChannelCommandRunnable(channelUID, command); + if (channelCommandRunnable == null) { + return; + } + + String channelId = channelUID.getId(); + boolean isHevCycleChannelCommand = CHANNEL_HEV_CYCLE.equals(channelId); + boolean isInfraredChannelCommand = CHANNEL_INFRARED.equals(channelId); + boolean waitForHevCycleDisabled = false; + + if (getFeatures().hasFeature(HEV) && !isHevCycleChannelCommand) { + LifxLightState lightState = getLightStateForCommand(); + HevCycleState currentHevCycleState = lightState.getHevCycleState(); + if (currentHevCycleState == null || currentHevCycleState.isEnable()) { + lightState.setHevCycleState(HevCycleState.OFF); + lightState.setPowerState(PowerState.OFF); + waitForHevCycleDisabled = true; + } } - if (supportedCommand && !(command instanceof OnOffType) && !CHANNEL_INFRARED.equals(channelUID.getId())) { - getLightStateForCommand().setPowerState(PowerState.ON); + Runnable compositeCommandsRunnable = () -> { + channelCommandRunnable.run(); + if (!(command instanceof OnOffType) && !isHevCycleChannelCommand && !isInfraredChannelCommand) { + getLightStateForCommand().setPowerState(PowerState.ON); + } + }; + + if (waitForHevCycleDisabled) { + scheduler.schedule(compositeCommandsRunnable, 200, TimeUnit.MILLISECONDS); + } else { + compositeCommandsRunnable.run(); } } } + private @Nullable Runnable getChannelCommandRunnable(ChannelUID channelUID, Command command) { + switch (channelUID.getId()) { + case CHANNEL_BRIGHTNESS: + if (command instanceof PercentType) { + return () -> handlePercentCommand((PercentType) command); + } else if (command instanceof OnOffType) { + return () -> handleOnOffCommand((OnOffType) command); + } else if (command instanceof IncreaseDecreaseType) { + return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command); + } else { + return null; + } + case CHANNEL_COLOR: + if (command instanceof HSBType) { + return () -> handleHSBCommand((HSBType) command); + } else if (command instanceof PercentType) { + return () -> handlePercentCommand((PercentType) command); + } else if (command instanceof OnOffType) { + return () -> handleOnOffCommand((OnOffType) command); + } else if (command instanceof IncreaseDecreaseType) { + return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command); + } else { + return null; + } + case CHANNEL_EFFECT: + if (command instanceof StringType && features.hasFeature(TILE_EFFECT)) { + return () -> handleTileEffectCommand((StringType) command); + } else { + return null; + } + case CHANNEL_HEV_CYCLE: + if (command instanceof OnOffType) { + return () -> handleHevCycleCommand((OnOffType) command); + } else { + return null; + } + case CHANNEL_INFRARED: + if (command instanceof PercentType) { + return () -> handleInfraredCommand((PercentType) command); + } else if (command instanceof IncreaseDecreaseType) { + return () -> handleIncreaseDecreaseInfraredCommand((IncreaseDecreaseType) command); + } else { + return null; + } + case CHANNEL_TEMPERATURE: + if (command instanceof PercentType) { + return () -> handleTemperatureCommand((PercentType) command); + } else if (command instanceof IncreaseDecreaseType) { + return () -> handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command); + } else { + return null; + } + default: + try { + if (channelUID.getId().startsWith(CHANNEL_COLOR_ZONE)) { + int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_COLOR_ZONE, "")); + if (command instanceof HSBType) { + return () -> handleHSBCommand((HSBType) command, zoneIndex); + } else if (command instanceof PercentType) { + return () -> handlePercentCommand((PercentType) command, zoneIndex); + } else if (command instanceof IncreaseDecreaseType) { + return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command, zoneIndex); + } else { + return null; + } + } else if (channelUID.getId().startsWith(CHANNEL_TEMPERATURE_ZONE)) { + int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_TEMPERATURE_ZONE, "")); + if (command instanceof PercentType) { + return () -> handleTemperatureCommand((PercentType) command, zoneIndex); + } else if (command instanceof IncreaseDecreaseType) { + return () -> handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command, + zoneIndex); + } else { + return null; + } + } else { + return null; + } + } catch (NumberFormatException e) { + logger.error("Failed to parse zone index for a command of a light ({}) : {}", logId, + e.getMessage()); + return null; + } + } + } + private LifxLightState getLightStateForCommand() { if (!isStateChangePending()) { pendingLightState.copy(currentLightState); @@ -612,6 +647,36 @@ private boolean isStateChangePending() { return pendingLightState.getDurationSinceLastChange().minus(MAX_STATE_CHANGE_DURATION).isNegative(); } + private void handleRefreshCommand(ChannelUID channelUID) { + channelStates.remove(channelUID.getId()); + switch (channelUID.getId()) { + case CHANNEL_COLOR: + case CHANNEL_BRIGHTNESS: + sendPacket(new GetLightPowerRequest()); + sendPacket(new GetRequest()); + break; + case CHANNEL_EFFECT: + if (features.hasFeature(TILE_EFFECT)) { + sendPacket(new GetTileEffectRequest()); + } + break; + case CHANNEL_HEV_CYCLE: + sendPacket(new GetHevCycleRequest()); + break; + case CHANNEL_INFRARED: + sendPacket(new GetLightInfraredRequest()); + break; + case CHANNEL_SIGNAL_STRENGTH: + sendPacket(new GetWifiInfoRequest()); + break; + case CHANNEL_TEMPERATURE: + sendPacket(new GetRequest()); + break; + default: + break; + } + } + private void handleTemperatureCommand(PercentType temperature) { HSBK newColor = getLightStateForCommand().getColor(); newColor.setSaturation(PercentType.ZERO); @@ -688,6 +753,11 @@ private void handleIncreaseDecreaseTemperatureCommand(IncreaseDecreaseType incre handleTemperatureCommand(newTemperature, zoneIndex); } + private void handleHevCycleCommand(OnOffType onOff) { + HevCycleState hevCycleState = new HevCycleState(onOff == OnOffType.ON, hevCycleDuration); + getLightStateForCommand().setHevCycleState(hevCycleState); + } + private void handleInfraredCommand(PercentType infrared) { getLightStateForCommand().setInfrared(infrared); } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java index fab89fa7f1984..865c33fede908 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java @@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.lifx.internal.LifxLightState; import org.openhab.binding.lifx.internal.dto.Effect; +import org.openhab.binding.lifx.internal.dto.HevCycleState; import org.openhab.binding.lifx.internal.dto.PowerState; import org.openhab.binding.lifx.internal.dto.SignalStrength; import org.openhab.binding.lifx.internal.fields.HSBK; @@ -45,6 +46,14 @@ public interface LifxLightStateListener { */ void handlePowerStateChange(@Nullable PowerState oldPowerState, PowerState newPowerState); + /** + * Called when the HEV cycle state property changes. + * + * @param oldHevCycleState the old HEV cycle state value + * @param newHevCycleState the new HEV cycle state value + */ + void handleHevCycleStateChange(@Nullable HevCycleState oldHevCycleState, HevCycleState newHevCycleState); + /** * Called when the infrared property changes. * diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/config/config.xml index b2f662f94f3ab..13ed432e1ebe9 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/config/config.xml @@ -42,25 +42,32 @@ - - - - Color temperature level used when switching on the light. Use empty value to leave color temperature as - is. - - - - + Speed of the morph effect in seconds. 3 - + Speed of the flame effect in seconds. 4 + + + + HEV cycle duration in seconds. Use empty value for the cycle duration configured in the light. + + + + + + + Color temperature level used when switching on the light. Use empty value to leave color temperature as + is. + + + diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx.properties b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx.properties index 1cc88dac0005a..c4f511d6ac937 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx.properties +++ b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx.properties @@ -4,16 +4,18 @@ binding.lifx.description = This is the binding for LIFX lights. # thing types thing-type.lifx.colorlight.label = LIFX Color Light +thing-type.lifx.colorhevlight.label = LIFX Color HEV Light thing-type.lifx.colorirlight.label = LIFX Color IR Light thing-type.lifx.colormzlight.label = LIFX Color MultiZone Light +thing-type.lifx.tilelight.label = LIFX Tile Light thing-type.lifx.whitelight.label = LIFX White Light # thing type configuration -thing-type.config.lifx.light.deviceId.label = LIFX device ID +thing-type.config.lifx.light.deviceId.label = LIFX Device ID thing-type.config.lifx.light.deviceId.description = Identifies the light, e.g. "D073D5A1A1A1" thing-type.config.lifx.light.host.label = Host thing-type.config.lifx.light.host.description = Hostname or IP address of the light. Use empty value for automatic discovery. -thing-type.config.lifx.light.fadetime.label = Fade time +thing-type.config.lifx.light.fadetime.label = Fade Time thing-type.config.lifx.light.fadetime.description = The time to fade to the new color value (in ms). # channel types @@ -21,30 +23,34 @@ channel-type.lifx.brightness.label = Brightness channel-type.lifx.brightness.description = Sets the brightness of the light channel-type.lifx.color.label = Color channel-type.lifx.color.description = Selects the color of the light -channel-type.lifx.colorzone.label = Color zone {0} +channel-type.lifx.colorzone.label = Color Zone {0} channel-type.lifx.colorzone.description = Selects the zone {0} color of the light -channel-type.lifx.infrared.label = Infrared -channel-type.lifx.infrared.description = Sets the infrared of the light -channel-type.lifx.temperature.label = Temperature -channel-type.lifx.temperature.description = Sets the temperature of the light -channel-type.lifx.temperaturezone.label = Temperature zone {0} -channel-type.lifx.temperaturezone.description = Sets the zone {0} temperature of the light channel-type.lifx.effect.label = Effect channel-type.lifx.effect.description = Sets the effect of the light channel-type.lifx.effect.state.option.off = Off channel-type.lifx.effect.state.option.morph = Morph channel-type.lifx.effect.state.option.flame = Flame +channel-type.lifx.hevcycle.label = HEV Cycle +channel-type.lifx.hevcycle.description = Controls the HEV clean cycle of the light +channel-type.lifx.infrared.label = Infrared +channel-type.lifx.infrared.description = Sets the infrared of the light +channel-type.lifx.temperature.label = Temperature +channel-type.lifx.temperature.description = Sets the temperature of the light +channel-type.lifx.temperaturezone.label = Temperature Zone {0} +channel-type.lifx.temperaturezone.description = Sets the zone {0} temperature of the light # channel type configuration -channel-type.config.lifx.brightness.powerOnBrightness.label = Power on brightness +channel-type.config.lifx.brightness.powerOnBrightness.label = Power On Brightness channel-type.config.lifx.brightness.powerOnBrightness.description = Brightness level used when switching on the light. Use empty value to leave brightness as is. -channel-type.config.lifx.color.powerOnBrightness.label = Power on brightness +channel-type.config.lifx.color.powerOnBrightness.label = Power On Brightness channel-type.config.lifx.color.powerOnBrightness.description = Brightness level used when switching on the light. Use empty value to leave brightness as is. -channel-type.config.lifx.color.powerOnColor.label = Power on color +channel-type.config.lifx.color.powerOnColor.label = Power On Color channel-type.config.lifx.color.powerOnColor.description = Color used when switching on the light. Use empty value to leave color as is. -channel-type.config.lifx.temperature.powerOnTemperature.label = Power on color temperature -channel-type.config.lifx.temperature.powerOnTemperature.description = Color temperature used when switching on the light. Use empty value to leave color temperature as is. -channel-type.config.lifx.effect.effectMorphSpeed.label = Morph effect speed +channel-type.config.lifx.effect.effectMorphSpeed.label = Morph Effect Speed channel-type.config.lifx.effect.effectMorphSpeed.description = Speed of the morph effect in seconds. -channel-type.config.lifx.effect.effectFlameSpeed.label = Flame effect speed +channel-type.config.lifx.effect.effectFlameSpeed.label = Flame Effect Speed channel-type.config.lifx.effect.effectFlameSpeed.description = Speed of the flame effect in seconds. +channel-type.config.lifx.hevcycle.hevCycleDuration.label = HEV Cycle Duration +channel-type.config.lifx.hevcycle.hevCycleDuration.description = HEV cycle duration in seconds. Use empty value for the cycle duration configured in the light. +channel-type.config.lifx.temperature.powerOnTemperature.label = Power On Color Temperature +channel-type.config.lifx.temperature.powerOnTemperature.description = Color temperature used when switching on the light. Use empty value to leave color temperature as is. diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx_nl.properties b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx_nl.properties index 1a6afa243d36d..c21aab2872b98 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx_nl.properties +++ b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/i18n/lifx_nl.properties @@ -4,15 +4,17 @@ binding.lifx.description = Dit is de binding voor LIFX lampen. # thing types thing-type.lifx.colorlight.label = LIFX Kleuren Lamp +thing-type.lifx.colorhevlight.label = LIFX Kleuren HEV Lamp thing-type.lifx.colorirlight.label = LIFX Kleuren IR Lamp thing-type.lifx.colormzlight.label = LIFX Kleuren MultiZone Lamp +thing-type.lifx.tilelight.label = LIFX Tegel Lamp thing-type.lifx.whitelight.label = LIFX Wittinten Lamp # thing type configuration -thing-type.config.lifx.light.deviceId.label = LIFX apparaat ID +thing-type.config.lifx.light.deviceId.label = LIFX Apparaat ID thing-type.config.lifx.light.deviceId.description = Identificeert de lamp, bv. "D073D5A1A1A1" thing-type.config.lifx.light.host.label = Host -thing-type.config.lifx.light.host.description = Hostnaam of IP adres van de lamp. Gebruik lege waarde voor automatische detectie. +thing-type.config.lifx.light.host.description = Hostnaam of IP adres van de lamp. Gebruik een lege waarde voor automatische detectie. thing-type.config.lifx.light.fadetime.label = Vervagingsduur thing-type.config.lifx.light.fadetime.description = De tijdsduur van het vervagen naar een nieuwe kleur (in ms). @@ -21,24 +23,34 @@ channel-type.lifx.brightness.label = Helderheid channel-type.lifx.brightness.description = Bepaalt de helderheid van de lamp channel-type.lifx.color.label = Kleur channel-type.lifx.color.description = Bepaalt de kleur van de lamp -channel-type.lifx.colorzone.label = Kleur zone {0} +channel-type.lifx.colorzone.label = Kleur Zone {0} channel-type.lifx.colorzone.description = Bepaalt de kleur van lampzone {0} +channel-type.lifx.effect.label = Effect +channel-type.lifx.effect.description = Bepaalt het lichteffect +channel-type.lifx.effect.state.option.off = Uit +channel-type.lifx.effect.state.option.morph = Morph +channel-type.lifx.effect.state.option.flame = Vlam +channel-type.lifx.hevcycle.label = HEV Cyclus +channel-type.lifx.hevcycle.description = Bedient de HEV schoonmaakcylcus van de lamp channel-type.lifx.infrared.label = Infrarood channel-type.lifx.infrared.description = Bepaalt het infraroodniveau van de lamp channel-type.lifx.temperature.label = Temperatuur channel-type.lifx.temperature.description = Bepaalt de kleurtemperatuur van de lamp -channel-type.lifx.temperaturezone.label = Temperatuur zone {0} +channel-type.lifx.temperaturezone.label = Temperatuur Zone {0} channel-type.lifx.temperaturezone.description = Bepaalt de kleurtemperatuur van lampzone {0} -channel-type.lifx.effect.label = Effect -channel-type.lifx.effect.description = Bepaalt het lichteffect -channel-type.lifx.effect.state.option.off = Uit -channel-type.lifx.effect.state.option.morph = Morph -channel-type.lifx.effect.state.option.flame = Flamme # channel type configuration channel-type.config.lifx.brightness.powerOnBrightness.label = Inschakelhelderheid channel-type.config.lifx.brightness.powerOnBrightness.description = Het helderheidsniveau bij inschakeling van de lamp. Gebruik een lege waarde om de helderheid ongewijzigd te laten. -channel-type.config.lifx.effect.effectMorphSpeed.label = Morph-effect snelheid +channel-type.config.lifx.color.powerOnBrightness.label = Inschakelhelderheid +channel-type.config.lifx.color.powerOnBrightness.description = Het helderheidsniveau bij inschakeling van de lamp. Gebruik een lege waarde om de helderheid ongewijzigd te laten. +channel-type.config.lifx.color.powerOnColor.label = Inschakelkleur +channel-type.config.lifx.color.powerOnColor.description = De kleur die gebruikt wordt bij het inschakelen van de lamp. Gebruik een lege waarde om de kleur ongewijzigd te laten. +channel-type.config.lifx.effect.effectMorphSpeed.label = Morph-effect Snelheid channel-type.config.lifx.effect.effectMorphSpeed.description = De snelheid van het Morph-effect in seconden. -channel-type.config.lifx.effect.effectFlameSpeed.label = Vlam-effect snelheid +channel-type.config.lifx.effect.effectFlameSpeed.label = Vlam-effect Snelheid channel-type.config.lifx.effect.effectFlameSpeed.description = De snelheid van het Vlam-effect in seconden. +channel-type.config.lifx.hevcycle.hevCycleDuration.label = HEV Cycluslooptijd +channel-type.config.lifx.hevcycle.hevCycleDuration.description = HEV cycluslooptijd in seconden. Gebruik een lege waarde om de in de lamp geconfigureerde cycluslooptijd te gebruiken. +channel-type.config.lifx.temperature.powerOnTemperature.label = Inschakelkleurtemperatuur +channel-type.config.lifx.temperature.powerOnTemperature.description = De kleurtemperatuur die gebruikt wordt bij het inschakelen van de lamp. Gebruik een lege waarde om de kleurtemperatuur ongewijzigd te laten. diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/thing/channel.xml b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/thing/channel.xml index 5536a9ec2eee8..4e5260d4b4cea 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/thing/channel.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/thing/channel.xml @@ -36,6 +36,13 @@ + + Switch + + Controls the HEV clean cycle of the light + + + Dimmer diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/thing/colorhevlight.xml b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/thing/colorhevlight.xml new file mode 100644 index 0000000000000..9506454f30b05 --- /dev/null +++ b/bundles/org.openhab.binding.lifx/src/main/resources/OH-INF/thing/colorhevlight.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + macAddress + + + +