import static org.openhab.binding.lifx.internal.LifxProduct.TemperatureRange.*;
import static org.openhab.binding.lifx.internal.LifxProduct.Vendor.LIFX;
-import java.util.Arrays;
-import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
@NonNullByDefault
public enum LifxProduct {
- PRODUCT_1(1, "LIFX Original 1000", TR_2500_9000, COLOR),
- PRODUCT_3(3, "LIFX Color 650", TR_2500_9000, COLOR),
- PRODUCT_10(10, "LIFX White 800 (Low Voltage)", TR_2700_6500),
- PRODUCT_11(11, "LIFX White 800 (High Voltage)", TR_2700_6500),
- PRODUCT_15(15, "LIFX Color 1000", TR_2500_9000, COLOR),
- PRODUCT_18(18, "LIFX White 900 BR30 (Low Voltage)", TR_2700_6500),
- PRODUCT_19(19, "LIFX White 900 BR30 (High Voltage)", TR_2700_6500),
- PRODUCT_20(20, "LIFX Color 1000 BR30", TR_2500_9000, COLOR),
- PRODUCT_22(22, "LIFX Color 1000", TR_2500_9000, COLOR),
- PRODUCT_27(27, "LIFX A19", TR_2500_9000, COLOR),
- PRODUCT_28(28, "LIFX BR30", TR_2500_9000, COLOR),
- PRODUCT_29(29, "LIFX A19 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_30(30, "LIFX BR30 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_31(31, "LIFX Z", TR_2500_9000, COLOR, MULTIZONE),
- PRODUCT_32(32, "LIFX Z", TR_2500_9000, COLOR, MULTIZONE),
- PRODUCT_36(36, "LIFX Downlight", TR_2500_9000, COLOR),
- PRODUCT_37(37, "LIFX Downlight", TR_2500_9000, COLOR),
- PRODUCT_38(38, "LIFX Beam", TR_2500_9000, COLOR, MULTIZONE),
- PRODUCT_39(39, "LIFX Downlight White to Warm", TR_1500_9000),
- PRODUCT_40(40, "LIFX Downlight", TR_2500_9000, COLOR),
- PRODUCT_43(43, "LIFX A19", TR_2500_9000, COLOR),
- PRODUCT_44(44, "LIFX BR30", TR_2500_9000, COLOR),
- PRODUCT_45(45, "LIFX A19 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_46(46, "LIFX BR30 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_49(49, "LIFX Mini Color", TR_2500_9000, COLOR),
- PRODUCT_50(50, "LIFX Mini White to Warm", TR_1500_4000),
- PRODUCT_51(51, "LIFX Mini White", TR_2700_2700),
- PRODUCT_52(52, "LIFX GU10", TR_2500_9000, COLOR),
- PRODUCT_53(53, "LIFX GU10", TR_2500_9000, COLOR),
- PRODUCT_55(55, "LIFX Tile", TR_2500_9000, CHAIN, COLOR, MATRIX, TILE_EFFECT),
- PRODUCT_57(57, "LIFX Candle", TR_1500_9000, COLOR, MATRIX),
- PRODUCT_59(59, "LIFX Mini Color", TR_2500_9000, COLOR),
- PRODUCT_60(60, "LIFX Mini White to Warm", TR_1500_4000),
- PRODUCT_61(61, "LIFX Mini White", TR_2700_2700),
- PRODUCT_62(62, "LIFX A19", TR_2500_9000, COLOR),
- PRODUCT_63(63, "LIFX BR30", TR_2500_9000, COLOR),
- PRODUCT_64(64, "LIFX A19 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_65(65, "LIFX BR30 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_66(66, "LIFX Mini White", TR_2700_2700),
- PRODUCT_68(68, "LIFX Candle", TR_1500_9000, MATRIX),
- PRODUCT_81(81, "LIFX Candle White to Warm", TR_2200_6500),
- PRODUCT_82(82, "LIFX Filament Clear", TR_2100_2100),
- PRODUCT_85(85, "LIFX Filament Amber", TR_2000_2000),
- PRODUCT_87(87, "LIFX Mini White", TR_2700_2700),
- PRODUCT_88(88, "LIFX Mini White", TR_2700_2700),
- PRODUCT_90(90, "LIFX Clean", TR_2500_9000, HEV),
- PRODUCT_91(91, "LIFX Color", TR_2500_9000, COLOR),
- PRODUCT_92(92, "LIFX Color", TR_2500_9000, COLOR),
- PRODUCT_94(94, "LIFX BR30", TR_2500_9000, COLOR),
- PRODUCT_96(96, "LIFX Candle White to Warm", TR_2200_6500),
- PRODUCT_97(97, "LIFX A19", TR_2500_9000, COLOR),
- PRODUCT_98(98, "LIFX BR30", TR_2500_9000, COLOR),
- PRODUCT_99(99, "LIFX Clean", TR_2500_9000, HEV),
- PRODUCT_100(100, "LIFX Filament Clear", TR_2100_2100),
- PRODUCT_101(101, "LIFX Filament Amber", TR_2000_2000),
- PRODUCT_109(109, "LIFX A19 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_110(110, "LIFX BR30 Night Vision", TR_2500_9000, COLOR, INFRARED),
- PRODUCT_111(111, "LIFX A19 Night Vision", TR_2500_9000, COLOR, INFRARED);
+ PRODUCT_1(1, "LIFX Original 1000", new Features(TR_2500_9000, COLOR)),
+ PRODUCT_3(3, "LIFX Color 650", new Features(TR_2500_9000, COLOR)),
+ PRODUCT_10(10, "LIFX White 800 (Low Voltage)", new Features(TR_2700_6500)),
+ PRODUCT_11(11, "LIFX White 800 (High Voltage)", new Features(TR_2700_6500)),
+ PRODUCT_15(15, "LIFX Color 1000", new Features(TR_2500_9000, COLOR)),
+ PRODUCT_18(18, "LIFX White 900 BR30 (Low Voltage)", new Features(TR_2700_6500)),
+ PRODUCT_19(19, "LIFX White 900 BR30 (High Voltage)", new Features(TR_2700_6500)),
+ PRODUCT_20(20, "LIFX Color 1000 BR30", new Features(TR_2500_9000, COLOR)),
+ PRODUCT_22(22, "LIFX Color 1000", new Features(TR_2500_9000, COLOR)),
+ PRODUCT_27(27, "LIFX A19", new Features(TR_2500_9000, COLOR), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_28(28, "LIFX BR30", new Features(TR_2500_9000, COLOR), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_29(29, "LIFX A19 Night Vision", new Features(TR_2500_9000, COLOR, INFRARED), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_30(30, "LIFX BR30 Night Vision", new Features(TR_2500_9000, COLOR, INFRARED), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_31(31, "LIFX Z", new Features(TR_2500_9000, COLOR, MULTIZONE)),
+ PRODUCT_32(32, "LIFX Z", new Features(TR_2500_9000, COLOR, MULTIZONE), //
+ new Upgrade(2, 77, new Features(EXTENDED_MULTIZONE)), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_36(36, "LIFX Downlight", new Features(TR_2500_9000, COLOR), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_37(37, "LIFX Downlight", new Features(TR_2500_9000, COLOR), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_38(38, "LIFX Beam", new Features(TR_2500_9000, COLOR, MULTIZONE), //
+ new Upgrade(2, 77, new Features(EXTENDED_MULTIZONE)), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_39(39, "LIFX Downlight White to Warm", new Features(TR_2500_9000), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_40(40, "LIFX Downlight", new Features(TR_2500_9000, COLOR), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_43(43, "LIFX A19", new Features(TR_2500_9000, COLOR), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_44(44, "LIFX BR30", new Features(TR_2500_9000, COLOR), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_45(45, "LIFX A19 Night Vision", new Features(TR_2500_9000, COLOR, INFRARED), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_46(46, "LIFX BR30 Night Vision", new Features(TR_2500_9000, COLOR, INFRARED), //
+ new Upgrade(2, 80, new Features(TR_1500_9000))),
+ PRODUCT_49(49, "LIFX Mini Color", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_50(50, "LIFX Mini White to Warm", new Features(TR_1500_6500), //
+ new Upgrade(3, 70, new Features(TR_1500_9000))),
+ PRODUCT_51(51, "LIFX Mini White", new Features(TR_2700_2700)),
+ PRODUCT_52(52, "LIFX GU10", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_53(53, "LIFX GU10", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_55(55, "LIFX Tile", new Features(TR_2500_9000, CHAIN, COLOR, MATRIX, TILE_EFFECT)),
+ PRODUCT_57(57, "LIFX Candle", new Features(TR_1500_9000, COLOR, MATRIX)),
+ PRODUCT_59(59, "LIFX Mini Color", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_60(60, "LIFX Mini White to Warm", new Features(TR_1500_6500), //
+ new Upgrade(3, 70, new Features(TR_1500_9000))),
+ PRODUCT_61(61, "LIFX Mini White", new Features(TR_2700_2700)),
+ PRODUCT_62(62, "LIFX A19", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_63(63, "LIFX BR30", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_64(64, "LIFX A19 Night Vision", new Features(TR_1500_9000, COLOR, INFRARED)),
+ PRODUCT_65(65, "LIFX BR30 Night Vision", new Features(TR_1500_9000, COLOR, INFRARED)),
+ PRODUCT_66(66, "LIFX Mini White", new Features(TR_2700_2700)),
+ PRODUCT_68(68, "LIFX Candle", new Features(TR_1500_9000, MATRIX)),
+ PRODUCT_70(70, "LIFX Switch", new Features(BUTTONS, RELAYS)),
+ PRODUCT_71(71, "LIFX Switch", new Features(BUTTONS, RELAYS)),
+ PRODUCT_81(81, "LIFX Candle White to Warm", new Features(TR_2200_6500)),
+ PRODUCT_82(82, "LIFX Filament Clear", new Features(TR_2100_2100)),
+ PRODUCT_85(85, "LIFX Filament Amber", new Features(TR_2000_2000)),
+ PRODUCT_87(87, "LIFX Mini White", new Features(TR_2700_2700)),
+ PRODUCT_88(88, "LIFX Mini White", new Features(TR_2700_2700)),
+ PRODUCT_89(89, "LIFX Switch", new Features(BUTTONS, RELAYS)),
+ PRODUCT_90(90, "LIFX Clean", new Features(TR_1500_9000, HEV)),
+ PRODUCT_91(91, "LIFX Color", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_92(92, "LIFX Color", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_94(94, "LIFX BR30", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_96(96, "LIFX Candle White to Warm", new Features(TR_2200_6500)),
+ PRODUCT_97(97, "LIFX A19", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_98(98, "LIFX BR30", new Features(TR_1500_9000, COLOR)),
+ PRODUCT_99(99, "LIFX Clean", new Features(TR_1500_9000, HEV)),
+ PRODUCT_100(100, "LIFX Filament Clear", new Features(TR_2100_2100)),
+ PRODUCT_101(101, "LIFX Filament Amber", new Features(TR_2000_2000)),
+ PRODUCT_109(109, "LIFX A19 Night Vision", new Features(TR_1500_9000, COLOR, INFRARED)),
+ PRODUCT_110(110, "LIFX BR30 Night Vision", new Features(TR_1500_9000, COLOR, INFRARED)),
+ PRODUCT_111(111, "LIFX A19 Night Vision", new Features(TR_1500_9000, COLOR, INFRARED));
/**
* Enumerates the product features.
*/
public enum Feature {
+ BUTTONS,
CHAIN,
COLOR,
+ EXTENDED_MULTIZONE,
HEV,
INFRARED,
MATRIX,
MULTIZONE,
+ RELAYS,
TILE_EFFECT
}
* Enumerates the color temperature ranges of lights.
*/
public enum TemperatureRange {
+ /**
+ * When the temperature range is not defined for {@link Upgrade}s it is inherited from the most
+ * recent firmware version.
+ */
+ NONE(0, 0),
+
/**
* 1500-4000K
*/
TR_1500_4000(1500, 4000),
+ /**
+ * 1500-6500K
+ */
+ TR_1500_6500(1500, 6500),
+
/**
* 1500-9000K
*/
}
}
- private final Vendor vendor;
- private final long id;
- private final String name;
- private final TemperatureRange temperatureRange;
- private final EnumSet<Feature> features = EnumSet.noneOf(Feature.class);
+ public static class Features {
+ private TemperatureRange temperatureRange;
+ private Set<Feature> features;
+
+ private Features(Feature... features) {
+ this(NONE, features);
+ }
+
+ private Features(Features other) {
+ this(other.temperatureRange, other.features);
+ }
+
+ private Features(TemperatureRange temperatureRange, Feature... features) {
+ this.temperatureRange = temperatureRange;
+ this.features = Set.of(features);
+ }
+
+ private Features(TemperatureRange temperatureRange, Set<Feature> features) {
+ this.temperatureRange = temperatureRange;
+ this.features = Set.copyOf(features);
+ }
+
+ public TemperatureRange getTemperatureRange() {
+ return temperatureRange;
+ }
+
+ public boolean hasFeature(Feature feature) {
+ return features.contains(feature);
+ }
- private LifxProduct(long id, String name, TemperatureRange temperatureRange) {
- this(LIFX, id, name, temperatureRange);
+ public void update(Features other) {
+ temperatureRange = other.temperatureRange;
+ features = other.features;
+ }
}
- private LifxProduct(long id, String name, TemperatureRange temperatureRange, Feature... features) {
- this(LIFX, id, name, temperatureRange, features);
+ static class Upgrade {
+ final long major;
+ final long minor;
+ final Features features;
+
+ private Upgrade(long major, long minor, Features features) {
+ this.major = major;
+ this.minor = minor;
+ this.features = features;
+ }
}
- private LifxProduct(Vendor vendor, long id, String name, TemperatureRange temperatureRange) {
- this(vendor, id, name, temperatureRange, new Feature[0]);
+ private final Vendor vendor;
+ private final long id;
+ private final String name;
+ private final Features features;
+ private final List<Upgrade> upgrades;
+
+ private LifxProduct(long id, String name, Features features, Upgrade... upgrades) {
+ this(LIFX, id, name, features, upgrades);
}
- private LifxProduct(Vendor vendor, long id, String name, TemperatureRange temperatureRange, Feature... features) {
+ private LifxProduct(Vendor vendor, long id, String name, Features features, Upgrade... upgrades) {
this.vendor = vendor;
this.id = id;
this.name = name;
- this.temperatureRange = temperatureRange;
- this.features.addAll(Arrays.asList(features));
+ this.features = features;
+ this.upgrades = List.of(upgrades);
}
@Override
return name;
}
- public TemperatureRange getTemperatureRange() {
- return temperatureRange;
+ /**
+ * Returns the features of the initial product firmware version.
+ *
+ * @return the initial features
+ */
+ public Features getFeatures() {
+ return new Features(features);
+ }
+
+ /**
+ * Returns the features for a specific product firmware version.
+ *
+ * @param version the firmware version
+ * @return the composite features of all firmware upgrades for the given major and minor firmware version
+ */
+ public Features getFeatures(String version) {
+ if (upgrades.isEmpty() || !version.contains(".")) {
+ return new Features(features);
+ }
+
+ String[] majorMinorVersion = version.split("\\.");
+ long major = Long.valueOf(majorMinorVersion[0]);
+ long minor = Long.valueOf(majorMinorVersion[1]);
+
+ TemperatureRange temperatureRange = features.temperatureRange;
+ Set<Feature> features = new HashSet<>(this.features.features);
+
+ for (Upgrade upgrade : upgrades) {
+ if (upgrade.major < major || (upgrade.major == major && upgrade.minor <= minor)) {
+ Features upgradeFeatures = upgrade.features;
+ if (upgradeFeatures.temperatureRange != NONE) {
+ temperatureRange = upgradeFeatures.temperatureRange;
+ }
+ features.addAll(upgradeFeatures.features);
+ } else {
+ break;
+ }
+ }
+
+ return new Features(temperatureRange, features);
}
public ThingTypeUID getThingTypeUID() {
}
}
- public boolean hasFeature(Feature feature) {
- return features.contains(feature);
+ private boolean hasFeature(Feature feature) {
+ return features.hasFeature(feature);
}
/**
throw new IllegalArgumentException(id + " is not a valid product ID");
}
+
+ List<Upgrade> getUpgrades() {
+ return upgrades;
+ }
+
+ public boolean isLight() {
+ return !features.hasFeature(Feature.BUTTONS) && !features.hasFeature(Feature.RELAYS);
+ }
}
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.lifx.internal.LifxLightState;
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.GetLightInfraredRequest;
import org.openhab.binding.lifx.internal.dto.GetLightPowerRequest;
private static final Duration MAX_STATE_CHANGE_DURATION = Duration.ofSeconds(4);
private final LifxChannelFactory channelFactory;
- private @NonNullByDefault({}) LifxProduct product;
+ private @NonNullByDefault({}) Features features;
private @Nullable PercentType powerOnBrightness;
private @Nullable HSBType powerOnColor;
updateStateIfChanged(CHANNEL_COLOR, hsb);
updateStateIfChanged(CHANNEL_BRIGHTNESS, hsb.getBrightness());
updateStateIfChanged(CHANNEL_TEMPERATURE,
- kelvinToPercentType(updateColor.getKelvin(), product.getTemperatureRange()));
+ kelvinToPercentType(updateColor.getKelvin(), features.getTemperatureRange()));
updateZoneChannels(powerState, colors);
}
}
private void updateZoneChannels(@Nullable PowerState powerState, HSBK[] colors) {
- if (!product.hasFeature(MULTIZONE) || colors.length == 0) {
+ if (!features.hasFeature(MULTIZONE) || colors.length == 0) {
return;
}
HSBK updateColor = nullSafeUpdateColor(powerState, color);
updateStateIfChanged(CHANNEL_COLOR_ZONE + i, updateColor.getHSB());
updateStateIfChanged(CHANNEL_TEMPERATURE_ZONE + i,
- kelvinToPercentType(updateColor.getKelvin(), product.getTemperatureRange()));
+ kelvinToPercentType(updateColor.getKelvin(), features.getTemperatureRange()));
}
}
}
LifxLightConfig configuration = getConfigAs(LifxLightConfig.class);
logId = getLogId(configuration.getMACAddress(), configuration.getHost());
- product = getProduct();
- logger.debug("{} : Initializing handler for product {}", logId, product.getName());
+ if (logger.isDebugEnabled()) {
+ logger.debug("{} : Initializing handler for product {}", logId, getProduct().getName());
+ }
+
+ features = getFeatures();
powerOnBrightness = getPowerOnBrightness();
powerOnColor = getPowerOnColor();
currentLightState = new CurrentLightState();
pendingLightState = new LifxLightState();
- LifxLightContext context = new LifxLightContext(logId, product, configuration, currentLightState,
+ LifxLightContext context = new LifxLightContext(logId, features, configuration, currentLightState,
pendingLightState, scheduler);
communicationHandler = new LifxLightCommunicationHandler(context);
private @Nullable PercentType getPowerOnBrightness() {
Channel channel = null;
- if (product.hasFeature(COLOR)) {
+ if (features.hasFeature(COLOR)) {
ChannelUID channelUID = new ChannelUID(getThing().getUID(), LifxBindingConstants.CHANNEL_COLOR);
channel = getThing().getChannel(channelUID.getId());
} else {
private @Nullable HSBType getPowerOnColor() {
Channel channel = null;
- if (product.hasFeature(COLOR)) {
+ if (features.hasFeature(COLOR)) {
ChannelUID channelUID = new ChannelUID(getThing().getUID(), LifxBindingConstants.CHANNEL_COLOR);
channel = getThing().getChannel(channelUID.getId());
}
private @Nullable Double getEffectSpeed(String parameter) {
Channel channel = null;
- if (product.hasFeature(TILE_EFFECT)) {
+ if (features.hasFeature(TILE_EFFECT)) {
ChannelUID channelUID = new ChannelUID(getThing().getUID(), LifxBindingConstants.CHANNEL_EFFECT);
channel = getThing().getChannel(channelUID.getId());
}
return speed == null ? null : Double.valueOf(speed.toString());
}
+ private Features getFeatures() {
+ LifxProduct product = getProduct();
+
+ String propertyValue = getThing().getProperties().get(LifxBindingConstants.PROPERTY_HOST_VERSION);
+ if (propertyValue == null) {
+ logger.debug("{} : Using features of initial firmware version", logId);
+ return product.getFeatures();
+ }
+
+ logger.debug("{} : Using features of firmware version {}", logId, propertyValue);
+ return product.getFeatures(propertyValue);
+ }
+
private LifxProduct getProduct() {
- Object propertyValue = getThing().getProperties().get(LifxBindingConstants.PROPERTY_PRODUCT_ID);
+ String propertyValue = getThing().getProperties().get(LifxBindingConstants.PROPERTY_PRODUCT_ID);
if (propertyValue == null) {
return LifxProduct.getLikelyProduct(getThing().getThingTypeUID());
}
// Without first conversion to double, on a very first thing creation from discovery inbox,
// the product type is incorrectly parsed, as framework passed it as a floating point number
// (e.g. 50.0 instead of 50)
- Double d = Double.valueOf((String) propertyValue);
+ Double d = Double.valueOf(propertyValue);
long productID = d.longValue();
return LifxProduct.getProductFromProductID(productID);
} catch (IllegalArgumentException e) {
sendPacket(new GetWifiInfoRequest());
break;
case CHANNEL_EFFECT:
- if (product.hasFeature(TILE_EFFECT)) {
+ if (features.hasFeature(TILE_EFFECT)) {
sendPacket(new GetTileEffectRequest());
}
break;
}
break;
case CHANNEL_EFFECT:
- if (command instanceof StringType && product.hasFeature(TILE_EFFECT)) {
+ if (command instanceof StringType && features.hasFeature(TILE_EFFECT)) {
handleTileEffectCommand((StringType) command);
} else {
supportedCommand = false;
private void handleTemperatureCommand(PercentType temperature) {
HSBK newColor = getLightStateForCommand().getColor();
newColor.setSaturation(PercentType.ZERO);
- newColor.setKelvin(percentTypeToKelvin(temperature, product.getTemperatureRange()));
+ newColor.setKelvin(percentTypeToKelvin(temperature, features.getTemperatureRange()));
getLightStateForCommand().setColor(newColor);
}
private void handleTemperatureCommand(PercentType temperature, int zoneIndex) {
HSBK newColor = getLightStateForCommand().getColor(zoneIndex);
newColor.setSaturation(PercentType.ZERO);
- newColor.setKelvin(percentTypeToKelvin(temperature, product.getTemperatureRange()));
+ newColor.setKelvin(percentTypeToKelvin(temperature, features.getTemperatureRange()));
getLightStateForCommand().setColor(newColor, zoneIndex);
}
PercentType localPowerOnTemperature = powerOnTemperature;
if (localPowerOnTemperature != null && onOff == OnOffType.ON) {
getLightStateForCommand()
- .setTemperature(percentTypeToKelvin(localPowerOnTemperature, product.getTemperatureRange()));
+ .setTemperature(percentTypeToKelvin(localPowerOnTemperature, features.getTemperatureRange()));
}
PercentType powerOnBrightness = this.powerOnBrightness;
private void handleIncreaseDecreaseTemperatureCommand(IncreaseDecreaseType increaseDecrease) {
PercentType baseTemperature = kelvinToPercentType(getLightStateForCommand().getColor().getKelvin(),
- product.getTemperatureRange());
+ features.getTemperatureRange());
PercentType newTemperature = increaseDecreasePercentType(increaseDecrease, baseTemperature);
handleTemperatureCommand(newTemperature);
}
private void handleIncreaseDecreaseTemperatureCommand(IncreaseDecreaseType increaseDecrease, int zoneIndex) {
PercentType baseTemperature = kelvinToPercentType(getLightStateForCommand().getColor(zoneIndex).getKelvin(),
- product.getTemperatureRange());
+ features.getTemperatureRange());
PercentType newTemperature = increaseDecreasePercentType(increaseDecrease, baseTemperature);
handleTemperatureCommand(newTemperature, zoneIndex);
}
flameSpeedInMSecs.longValue());
getLightStateForCommand().setTileEffect(effect);
} catch (IllegalArgumentException e) {
- logger.debug("Wrong effect type received as command: {}", type);
+ logger.debug("{} : Wrong effect type received as command: {}", logId, type);
+ }
+ }
+
+ @Override
+ protected void updateProperties(Map<String, String> properties) {
+ String oldHostVersion = getThing().getProperties().get(LifxBindingConstants.PROPERTY_HOST_VERSION);
+ super.updateProperties(properties);
+ String newHostVersion = getThing().getProperties().get(LifxBindingConstants.PROPERTY_HOST_VERSION);
+
+ if (!Objects.equals(oldHostVersion, newHostVersion)) {
+ features.update(getFeatures());
}
}
--- /dev/null
+/**
+ * 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;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.openhab.binding.lifx.internal.LifxProduct.Feature.*;
+import static org.openhab.binding.lifx.internal.LifxProduct.TemperatureRange.*;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.lifx.internal.LifxProduct.Features;
+import org.openhab.binding.lifx.internal.LifxProduct.Upgrade;
+
+/**
+ * Tests {@link LifxProduct}.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+@NonNullByDefault
+public class LifxProductTest {
+
+ @Test
+ public void productIDsAreUnique() {
+ Set<Long> productIDs = new HashSet<>();
+ for (LifxProduct product : LifxProduct.values()) {
+ assertThat(productIDs, not(hasItem(product.getID())));
+ productIDs.add(product.getID());
+ }
+ }
+
+ @Test
+ public void productNamesMatchProductIDs() {
+ for (LifxProduct product : LifxProduct.values()) {
+ assertThat(product.name(), is("PRODUCT_" + product.getID()));
+ }
+ }
+
+ @Test
+ public void lightsHaveDefinedTemperatureRange() {
+ for (LifxProduct product : LifxProduct.values()) {
+ if (product.isLight()) {
+ String reason = String.format("The %s light does not define a temperature range", product.name());
+ assertThat(reason, product.getFeatures().getTemperatureRange(), is(not(NONE)));
+ }
+ }
+ }
+
+ @Test
+ public void upgradesSortedByMajorMinor() {
+ for (LifxProduct product : LifxProduct.values()) {
+ long major = 0;
+ long minor = 0;
+ for (Upgrade upgrade : product.getUpgrades()) {
+ String reason = String.format("Upgrades for %s are not sorted by major minor (%s.%s >= %s.%s)",
+ product.name(), major, minor, upgrade.major, upgrade.minor);
+ assertThat(reason, major < upgrade.major || (major == upgrade.major && minor < upgrade.minor),
+ is(true));
+ major = upgrade.major;
+ minor = upgrade.minor;
+ }
+ }
+ }
+
+ @Test
+ public void getFeaturesForProductWithoutUpgrades() {
+ LifxProduct product = LifxProduct.PRODUCT_1;
+ assertThat(product.getUpgrades(), hasSize(0));
+
+ Features features = product.getFeatures();
+ assertThat(features.getTemperatureRange(), is(TR_2500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+
+ features = product.getFeatures("1.23");
+ assertThat(features.getTemperatureRange(), is(TR_2500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+ }
+
+ @Test
+ public void getFeaturesForProductWithUpgrades() {
+ LifxProduct product = LifxProduct.PRODUCT_32;
+ assertThat(product.getUpgrades(), hasSize(2));
+
+ Features features = product.getFeatures();
+ assertThat(features.getTemperatureRange(), is(TR_2500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+ assertThat(features.hasFeature(EXTENDED_MULTIZONE), is(false));
+ assertThat(features.hasFeature(INFRARED), is(false));
+ assertThat(features.hasFeature(MULTIZONE), is(true));
+
+ features = product.getFeatures("2.70");
+ assertThat(features.getTemperatureRange(), is(TR_2500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+ assertThat(features.hasFeature(EXTENDED_MULTIZONE), is(false));
+ assertThat(features.hasFeature(INFRARED), is(false));
+ assertThat(features.hasFeature(MULTIZONE), is(true));
+
+ features = product.getFeatures("2.77");
+ assertThat(features.getTemperatureRange(), is(TR_2500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+ assertThat(features.hasFeature(EXTENDED_MULTIZONE), is(true));
+ assertThat(features.hasFeature(INFRARED), is(false));
+ assertThat(features.hasFeature(MULTIZONE), is(true));
+
+ features = product.getFeatures("2.79");
+ assertThat(features.getTemperatureRange(), is(TR_2500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+ assertThat(features.hasFeature(EXTENDED_MULTIZONE), is(true));
+ assertThat(features.hasFeature(INFRARED), is(false));
+ assertThat(features.hasFeature(MULTIZONE), is(true));
+
+ features = product.getFeatures("2.80");
+ assertThat(features.getTemperatureRange(), is(TR_1500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+ assertThat(features.hasFeature(EXTENDED_MULTIZONE), is(true));
+ assertThat(features.hasFeature(INFRARED), is(false));
+ assertThat(features.hasFeature(MULTIZONE), is(true));
+
+ features = product.getFeatures("2.81");
+ assertThat(features.getTemperatureRange(), is(TR_1500_9000));
+ assertThat(features.hasFeature(COLOR), is(true));
+ assertThat(features.hasFeature(EXTENDED_MULTIZONE), is(true));
+ assertThat(features.hasFeature(INFRARED), is(false));
+ assertThat(features.hasFeature(MULTIZONE), is(true));
+ }
+}