[lifx] Support HEV clean cycle (#11262)
* Implement HEV packets * Add colorhevlight thing type with a hevcycle channel * Update documentation Signed-off-by: Wouter Born <github@maindrain.net>
This commit is contained in:
parent
0a7a9ae281
commit
344011c2ad
@ -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 |
|
||||
| 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.
|
||||
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
|
||||
|
||||
@ -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<ThingTypeUID> 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<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_COLORLIGHT,
|
||||
THING_TYPE_COLORHEVLIGHT, THING_TYPE_COLORIRLIGHT, THING_TYPE_COLORMZLIGHT, THING_TYPE_TILELIGHT,
|
||||
THING_TYPE_WHITELIGHT);
|
||||
}
|
||||
|
||||
@ -25,11 +25,14 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
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 class LifxLightCurrentStateUpdater {
|
||||
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 class LifxLightCurrentStateUpdater {
|
||||
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 @@ public class LifxLightCurrentStateUpdater {
|
||||
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 @@ public class LifxLightCurrentStateUpdater {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
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 @@ import org.openhab.core.library.types.PercentType;
|
||||
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 class LifxLightState {
|
||||
return colorsCopy;
|
||||
}
|
||||
|
||||
public @Nullable HevCycleState getHevCycleState() {
|
||||
return hevCycleState;
|
||||
}
|
||||
|
||||
public @Nullable PercentType getInfrared() {
|
||||
return infrared;
|
||||
}
|
||||
@ -158,6 +165,13 @@ public class LifxLightState {
|
||||
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;
|
||||
|
||||
@ -34,13 +34,16 @@ import org.openhab.binding.lifx.internal.dto.AcknowledgementResponse;
|
||||
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 class LifxLightStateChanger implements LifxLightStateListener {
|
||||
}
|
||||
}
|
||||
|
||||
@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 class LifxLightStateChanger implements LifxLightStateListener {
|
||||
|
||||
@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 class LifxLightStateChanger implements LifxLightStateListener {
|
||||
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);
|
||||
|
||||
@ -371,12 +371,14 @@ public enum LifxProduct {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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 };
|
||||
}
|
||||
}
|
||||
@ -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 };
|
||||
}
|
||||
}
|
||||
@ -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 };
|
||||
}
|
||||
}
|
||||
@ -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 + "]";
|
||||
}
|
||||
}
|
||||
@ -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<LightLastHevCycleResult> result = Arrays.stream(values()).filter((value) -> value.type == type)
|
||||
.findFirst();
|
||||
|
||||
if (!result.isPresent()) {
|
||||
throw new IllegalArgumentException("Invalid LightLastHevCycleResult type: " + type);
|
||||
}
|
||||
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
@ -52,10 +52,13 @@ public class 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 @@ public class 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);
|
||||
|
||||
@ -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<Boolean> FIELD_INDICATION = new BoolIntField();
|
||||
public static final Field<Long> 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 };
|
||||
}
|
||||
}
|
||||
@ -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<Boolean> FIELD_ENABLE = new BoolIntField();
|
||||
public static final Field<Long> 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 };
|
||||
}
|
||||
}
|
||||
@ -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<Boolean> FIELD_INDICATION = new BoolIntField();
|
||||
public static final Field<Long> 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[] {};
|
||||
}
|
||||
}
|
||||
@ -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<Long> FIELD_DURATION = new UInt32Field().little();
|
||||
public static final Field<Long> FIELD_REMAINING = new UInt32Field().little();
|
||||
public static final Field<Boolean> 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[] {};
|
||||
}
|
||||
}
|
||||
@ -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<Integer> 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[] {};
|
||||
}
|
||||
}
|
||||
@ -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<Boolean> {
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,7 @@ import java.util.HashMap;
|
||||
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.LifxLightStateChanger;
|
||||
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 @@ public class LifxLightHandler extends BaseThingHandler {
|
||||
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 class LifxLightHandler extends BaseThingHandler {
|
||||
if (speed != null) {
|
||||
effectFlameSpeed = speed;
|
||||
}
|
||||
hevCycleDuration = getHevCycleDuration();
|
||||
|
||||
channelStates.clear();
|
||||
currentLightState = new CurrentLightState();
|
||||
pendingLightState = new LifxLightState();
|
||||
@ -410,6 +424,19 @@ public class LifxLightHandler extends BaseThingHandler {
|
||||
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,118 +513,126 @@ public class LifxLightHandler extends BaseThingHandler {
|
||||
@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;
|
||||
}
|
||||
|
||||
if (supportedCommand && !(command instanceof OnOffType) && !CHANNEL_INFRARED.equals(channelUID.getId())) {
|
||||
getLightStateForCommand().setPowerState(PowerState.ON);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -612,6 +647,36 @@ public class LifxLightHandler extends BaseThingHandler {
|
||||
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 @@ public class LifxLightHandler extends BaseThingHandler {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
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.
|
||||
*
|
||||
|
||||
@ -42,6 +42,26 @@
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="channel-type:lifx:effect">
|
||||
<parameter name="effectMorphSpeed" type="decimal" min="0" max="120" step="0.1" required="false" unit="s">
|
||||
<label>Morph Effect Speed</label>
|
||||
<description>Speed of the morph effect in seconds.</description>
|
||||
<default>3</default>
|
||||
</parameter>
|
||||
<parameter name="effectFlameSpeed" type="decimal" min="0" max="120" step="0.1" required="false" unit="s">
|
||||
<label>Flame Effect Speed</label>
|
||||
<description>Speed of the flame effect in seconds.</description>
|
||||
<default>4</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="channel-type:lifx:hevcycle">
|
||||
<parameter name="hevCycleDuration" type="integer" min="0" max="86400" step="1" required="false" unit="m">
|
||||
<label>HEV Cycle Duration</label>
|
||||
<description>HEV cycle duration in seconds. Use empty value for the cycle duration configured in the light.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="channel-type:lifx:temperature">
|
||||
<parameter name="powerOnTemperature" type="integer" min="0" max="100" required="false" unit="%">
|
||||
<label>Power On Temperature</label>
|
||||
@ -50,17 +70,4 @@
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="channel-type:lifx:effect">
|
||||
<parameter name="effectMorphSpeed" type="decimal" min="0" max="120" step="0.1" required="false" unit="s">
|
||||
<label>Morph effect speed</label>
|
||||
<description>Speed of the morph effect in seconds.</description>
|
||||
<default>3</default>
|
||||
</parameter>
|
||||
<parameter name="effectFlameSpeed" type="decimal" min="0" max="120" step="0.1" required="false" unit="s">
|
||||
<label>Flame effect speed</label>
|
||||
<description>Speed of the flame effect in seconds.</description>
|
||||
<default>4</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.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.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.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.description = Bepaalt de kleurtemperatuur van lampzone {0}
|
||||
|
||||
# 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.
|
||||
|
||||
@ -36,6 +36,13 @@
|
||||
</tags>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="hevcycle">
|
||||
<item-type>Switch</item-type>
|
||||
<label>HEV Cycle</label>
|
||||
<description>Controls the HEV clean cycle of the light</description>
|
||||
<config-description-ref uri="channel-type:lifx:hevcycle"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="infrared">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>Infrared</label>
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="lifx"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="colorhevlight">
|
||||
<label>LIFX Color HEV Light</label>
|
||||
<channels>
|
||||
<channel id="color" typeId="color"/>
|
||||
<channel id="temperature" typeId="temperature"/>
|
||||
<channel id="hevcycle" typeId="hevcycle"/>
|
||||
<channel id="signalstrength" typeId="system.signal-strength"/>
|
||||
</channels>
|
||||
<representation-property>macAddress</representation-property>
|
||||
<config-description-ref uri="thing-type:lifx:light"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Loading…
x
Reference in New Issue
Block a user