/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.binding.hue.handler;
import org.eclipse.smarthome.binding.hue.internal.State;
import org.eclipse.smarthome.binding.hue.internal.State.AlertMode;
import org.eclipse.smarthome.binding.hue.internal.State.Effect;
import org.eclipse.smarthome.binding.hue.internal.StateUpdate;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.HSBType;
import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.PercentType;
import org.eclipse.smarthome.core.library.types.StringType;
/**
* The {@link LightStateConverter} is responsible for mapping Eclipse SmartHome
* types to jue types and vice versa.
*
* @author Dennis Nobel - Initial contribution
* @author Oliver Libutzki - Adjustments
* @author Kai Kreuzer - made code static
* @author Andre Fuechsel - added method for brightness
* @author Yordan Zhelev - added method for alert
* @author Denis Dudnik - switched to internally integrated source of Jue library, minor code cleanup
*
*/
public class LightStateConverter {
private static final int HUE_FACTOR = 182;
private static final double SATURATION_FACTOR = 2.54;
private static final double BRIGHTNESS_FACTOR = 2.54;
private static final int MIN_COLOR_TEMPERATURE = 153;
private static final int MAX_COLOR_TEMPERATURE = 500;
private static final int COLOR_TEMPERATURE_RANGE = MAX_COLOR_TEMPERATURE - MIN_COLOR_TEMPERATURE;
/**
* {@value #ALERT_MODE_NONE}. The light is not performing an alert effect.
*/
static final String ALERT_MODE_NONE = "NONE";
/**
* {@value #ALERT_MODE_SELECT}. The light is performing one breathe cycle.
*/
static final String ALERT_MODE_SELECT = "SELECT";
/**
* {@value #ALERT_MODE_LONG_SELECT}. The light is performing breathe cycles
* for 15 seconds or until an "alert": "none" command is received.
*/
static final String ALERT_MODE_LONG_SELECT = "LSELECT";
private static final int DIM_STEPSIZE = 30;
/**
* Transforms the given {@link HSBType} into a light state.
*
* @param hsbType
* HSB type
* @return light state representing the {@link HSBType}.
*/
public static StateUpdate toColorLightState(HSBType hsbType) {
int hue = (int) Math.round(hsbType.getHue().doubleValue() * HUE_FACTOR);
int saturation = (int) Math.round(hsbType.getSaturation().doubleValue() * SATURATION_FACTOR);
int brightness = (int) Math.round(hsbType.getBrightness().doubleValue() * BRIGHTNESS_FACTOR);
StateUpdate stateUpdate = new StateUpdate().setHue(hue).setSat(saturation);
if (brightness > 0) {
stateUpdate.setBrightness(brightness);
}
return stateUpdate;
}
/**
* Transforms the given {@link OnOffType} into a light state containing the
* 'on' value.
*
* @param onOffType
* on or off state
* @return light state containing the 'on' value
*/
public static StateUpdate toOnOffLightState(OnOffType onOffType) {
return new StateUpdate().setOn(OnOffType.ON.equals(onOffType));
}
/**
* Transforms the given {@link PercentType} into a light state containing
* the brightness and the 'on' value represented by {@link PercentType}.
*
* @param percentType
* brightness represented as {@link PercentType}
* @return light state containing the brightness and the 'on' value
*/
public static StateUpdate toBrightnessLightState(PercentType percentType) {
boolean on = !percentType.equals(PercentType.ZERO);
final StateUpdate stateUpdate = new StateUpdate().setOn(on);
int brightness = (int) Math.round(percentType.floatValue() * BRIGHTNESS_FACTOR);
if (brightness > 0) {
stateUpdate.setBrightness(brightness);
}
return stateUpdate;
}
/**
* Adjusts the given brightness using the {@link IncreaseDecreaseType} and
* returns the updated value.
*
* @param command
* The {@link IncreaseDecreaseType} to be used
* @param currentBrightness
* The current brightness
* @return The adjusted brightness value
*/
public static int toAdjustedBrightness(IncreaseDecreaseType command, int currentBrightness) {
int newBrightness;
if (command == IncreaseDecreaseType.DECREASE) {
newBrightness = Math.max(currentBrightness - DIM_STEPSIZE, 0);
} else {
newBrightness = Math.min(currentBrightness + DIM_STEPSIZE, (int) (BRIGHTNESS_FACTOR * 100));
}
return newBrightness;
}
/**
* Transforms the given {@link PercentType} into a light state containing
* the color temperature represented by {@link PercentType}.
*
* @param percentType
* color temperature represented as {@link PercentType}
* @return light state containing the color temperature
*/
public static StateUpdate toColorTemperatureLightState(PercentType percentType) {
int colorTemperature = MIN_COLOR_TEMPERATURE
+ Math.round((COLOR_TEMPERATURE_RANGE * percentType.floatValue()) / 100);
return new StateUpdate().setColorTemperature(colorTemperature);
}
/**
* Adjusts the given color temperature using the {@link IncreaseDecreaseType} and returns the updated value.
*
* @param type
* The {@link IncreaseDecreaseType} to be used
* @param currentColorTemp
* The current color temperature
* @return The adjusted color temperature value
*/
public static int toAdjustedColorTemp(IncreaseDecreaseType type, int currentColorTemp) {
int newColorTemp;
if (type == IncreaseDecreaseType.DECREASE) {
newColorTemp = Math.max(currentColorTemp - DIM_STEPSIZE, MIN_COLOR_TEMPERATURE);
} else {
newColorTemp = Math.min(currentColorTemp + DIM_STEPSIZE, MAX_COLOR_TEMPERATURE);
}
return newColorTemp;
}
/**
* Transforms Hue Light {@link State} into {@link PercentType} representing
* the color temperature.
*
* @param lightState
* light state
* @return percent type representing the color temperature
*/
public static PercentType toColorTemperaturePercentType(State lightState) {
int percent = (int) Math
.round(((lightState.getColorTemperature() - MIN_COLOR_TEMPERATURE) * 100.0) / COLOR_TEMPERATURE_RANGE);
return new PercentType(restrictToBounds(percent));
}
/**
* Transforms Hue Light {@link State} into {@link PercentType} representing
* the brightness.
*
* @param lightState
* light state
* @return percent type representing the brightness
*/
public static PercentType toBrightnessPercentType(State lightState) {
int percent = (int) Math.round(lightState.getBrightness() / BRIGHTNESS_FACTOR);
return new PercentType(restrictToBounds(percent));
}
/**
* Transforms {@link State} into {@link StringType} representing the {@link AlertMode}.
*
* @param lightState
* light state.
* @return string type representing the alert mode.
*/
public static StringType toAlertStringType(State lightState) {
return new StringType(lightState.getAlertMode().toString());
}
/**
* Transforms Hue Light {@link State} into {@link HSBType} representing the
* color.
*
* @param lightState
* light state
* @return HSB type representing the color
*/
public static HSBType toHSBType(State lightState) {
int hue = lightState.getHue();
int saturationInPercent = (int) (lightState.getSaturation() / SATURATION_FACTOR);
int brightnessInPercent = (int) (lightState.getBrightness() / BRIGHTNESS_FACTOR);
saturationInPercent = restrictToBounds(saturationInPercent);
brightnessInPercent = restrictToBounds(brightnessInPercent);
return new HSBType(new DecimalType(hue / HUE_FACTOR), new PercentType(saturationInPercent),
new PercentType(brightnessInPercent));
}
/**
* Transforms the given {@link StringType} into a light state containing the {@link AlertMode} to be triggered.
*
* @param alertType
* {@link StringType} representing the required {@link AlertMode} . <br>
* Supported values are:
* <ul>
* <li>{@value #ALERT_MODE_NONE}.
* <li>{@value #ALERT_MODE_SELECT}.
* <li>{@value #ALERT_MODE_LONG_SELECT}.
* <ul>
* @return light state containing the {@link AlertMode} or <b><code>null </code></b> if the provided
* {@link StringType} represents unsupported mode.
*/
public static StateUpdate toAlertState(StringType alertType) {
AlertMode alertMode;
switch (alertType.toString()) {
case ALERT_MODE_NONE:
alertMode = State.AlertMode.NONE;
break;
case ALERT_MODE_SELECT:
alertMode = State.AlertMode.SELECT;
break;
case ALERT_MODE_LONG_SELECT:
alertMode = State.AlertMode.LSELECT;
break;
default:
return null;
}
return new StateUpdate().setAlert(alertMode);
}
/**
* Transforms the given {@link OnOffType} into a light state containing the {@link Effect} value.
* {@link OnOffType#ON} will result in {@link Effect#COLORLOOP}. {@link OnOffType#OFF} will result in
* {@link Effect#NONE}.
*
* @param onOffType
* on or off state
* @return light state containing the {@link Effect} value
*/
public static StateUpdate toOnOffEffectState(OnOffType onOffType) {
StateUpdate stateUpdate;
if (OnOffType.ON.equals(onOffType)) {
stateUpdate = new StateUpdate().setEffect(Effect.COLORLOOP);
} else {
stateUpdate = new StateUpdate().setEffect(Effect.NONE);
}
return stateUpdate;
}
private static int restrictToBounds(int percentValue) {
if (percentValue < 0) {
return 0;
} else if (percentValue > 100) {
return 100;
}
return percentValue;
}
}