blob: 3449f0ca837e5cb99d32dd9fa4ece4efba577ffc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014-2018 Orange.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* BAREAU Cyrille <cyrille.bareau@orange.com>
* BONNARDEL Gregory <gbonnardel.ext@orange.com>
*******************************************************************************/
package org.eclipse.om2m.sdt.home.hue;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.om2m.hue.api.HueLightDevice;
import org.eclipse.om2m.hue.api.types.LightState;
import org.eclipse.om2m.sdt.Domain;
import org.eclipse.om2m.sdt.Module;
import org.eclipse.om2m.sdt.datapoints.BooleanDataPoint;
import org.eclipse.om2m.sdt.datapoints.IntegerDataPoint;
import org.eclipse.om2m.sdt.exceptions.AccessException;
import org.eclipse.om2m.sdt.exceptions.ActionException;
import org.eclipse.om2m.sdt.exceptions.DataPointException;
import org.eclipse.om2m.sdt.home.actions.Toggle;
import org.eclipse.om2m.sdt.home.devices.Light;
import org.eclipse.om2m.sdt.home.driver.Utils;
import org.eclipse.om2m.sdt.home.modules.BinarySwitch;
import org.eclipse.om2m.sdt.home.modules.Brightness;
import org.eclipse.om2m.sdt.home.modules.Colour;
import org.eclipse.om2m.sdt.home.modules.ColourSaturation;
import org.eclipse.om2m.sdt.home.modules.FaultDetection;
import org.eclipse.om2m.sdt.home.types.DatapointType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.device.Constants;
@SuppressWarnings("rawtypes")
public class HomeLight extends Light {
static private final int RED = 0;
static private final int GREEN = 1;
static private final int BLUE = 2;
static private final String SRED = DatapointType.red.getShortName();
static private final String SGREEN = DatapointType.green.getShortName();
static private final String SBLUE = DatapointType.blue.getShortName();
private HueLightDevice hueLight;
private Domain domain;
private List<ServiceRegistration> registrations;
public HomeLight(HueLightDevice device, Domain domain) {
super(device.getId(),
(String) device.getProperties().get(Constants.DEVICE_SERIAL),
domain);
this.domain = domain;
this.hueLight = device;
try {
addBinarySwitch();
} catch (Exception e) {
Activator.logger.warning("Error addBinarySwitch", e);
}
try {
addFaultDetection();
} catch (Exception e) {
Activator.logger.warning("Error addFaultDetection", e);
}
try {
addColour();
} catch (Exception e) {
Activator.logger.warning("Error addLight", e);
}
try {
addColourSaturation();
} catch (Exception e) {
Activator.logger.warning("Error addLight", e);
}
//JW 2018.04.16
try {
addBrightness();
} catch (Exception e) {
Activator.logger.warning("addBrightness", e);
}
}
public void register(BundleContext context) {
registrations = Utils.register(this, context);
}
void unregister() {
for (ServiceRegistration reg : registrations) {
reg.unregister();
}
domain.removeDevice(getName());
}
private void addBinarySwitch() {
BinarySwitch binarySwitch = new BinarySwitch("BinarySwitch_" + getId(), domain,
new BooleanDataPoint(DatapointType.powerState) {
@Override
public void doSetValue(Boolean v) throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
hueLight.setState(new LightState(v));
}
@Override
public Boolean doGetValue() throws DataPointException {
return hueLight.isReachable() && hueLight.isOn();
}
});
binarySwitch.setToggle(new Toggle("toggle") {
@Override
protected void doToggle() throws ActionException {
if (! hueLight.isReachable()) {
throw new ActionException("Not reachable");
}
boolean on = hueLight.isOn();
hueLight.setState(new LightState(!on));
}
});
addModule(binarySwitch);
}
private void addFaultDetection() {
FaultDetection faultDetection = new FaultDetection("FaultDetection_" + getId(), domain,
new BooleanDataPoint(DatapointType.status) {
@Override
public Boolean doGetValue() throws DataPointException {
return ! hueLight.isReachable();
}
});
addModule(faultDetection);
}
private void addColour() {
Colour colour = new Colour("colour_" + getId(), domain,
new IntegerDataPoint(DatapointType.red) {
@Override
public void doSetValue(Integer value) throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
setColor(RED, value);
}
@Override
public Integer doGetValue() throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
return getColor(RED);
}
},
new IntegerDataPoint(DatapointType.green) {
@Override
public void doSetValue(Integer value) throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
setColor(GREEN, value);
}
@Override
public Integer doGetValue() throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
return getColor(GREEN);
}
},
new IntegerDataPoint(DatapointType.blue) {
@Override
public void doSetValue(Integer value) throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
setColor(BLUE, value);
}
@Override
public Integer doGetValue() throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
return getColor(BLUE);
}
});
colour.setDatapointHandler(new Module.DatapointHandler() {
@Override
public void setValues(Map<String, Object> values)
throws DataPointException, AccessException {
setColors((Integer) values.get(SRED),
(Integer) values.get(SGREEN),
(Integer) values.get(SBLUE));
}
@Override
public Map<String, Object> getValues(List<String> names)
throws DataPointException, AccessException {
int[] colors = getColors();
Map<String, Object> ret = new HashMap<String, Object>();
for (String s : names) {
if (s.equals(SRED)) ret.put(SRED, colors[RED]);
else if (s.equals(SGREEN)) ret.put(SGREEN, colors[GREEN]);
else if (s.equals(SBLUE)) ret.put(SBLUE, colors[BLUE]);
}
return ret;
}
});
addModule(colour);
}
private void addColourSaturation() {
ColourSaturation colourSaturation = new ColourSaturation("colourSaturation_" + getId(), domain,
new IntegerDataPoint(DatapointType.colourSaturation) {
@Override
public void doSetValue(Integer value) throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
// get current state
LightState currentLightState = hueLight.getState();
// set saturation
currentLightState.setSat((int) ((double) value * 2.55d));
hueLight.setState(currentLightState);
}
@Override
public Integer doGetValue() throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
// get current state
LightState currentLightState = hueLight.getState();
return (int) ((double) currentLightState.getSat() / 2.55d);
}
});
addModule(colourSaturation);
}
// JW 2018.04.16
private void addBrightness() {
Brightness brightness = new Brightness("brightness_" + getId(), domain,
new IntegerDataPoint(DatapointType.brightness) {
@Override
public void doSetValue(Integer value) throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
LightState currentLightState = hueLight.getState();
currentLightState.setBri((int) ((double) value * 2.55d));
hueLight.setState(currentLightState);
}
@Override
protected Integer doGetValue() throws DataPointException {
if (! hueLight.isReachable()) {
throw new DataPointException("Not reachable");
}
LightState currentLightState = hueLight.getState();
return (int) ((double) currentLightState.getBri() / 2.55d);
}
});
addModule(brightness);
}
private void setColor(int colorIndex, int colorValue) {
// get current state
LightState currentLightState = hueLight.getState();
int h = Math.round(((float) currentLightState.getHue()) / 65565f * 360f);
int s = Math.round(((float) currentLightState.getBri()) / 255f * 100f );
int v = Math.round(((float) currentLightState.getSat()) / 255f * 100f);
// convert current color in rgb
int[] rgb = HSVtoRGB(h, s, v);
// update red value
rgb[colorIndex] = colorValue;
// compute HSV
int[] hsv = RGBtoHSB(rgb[RED], rgb[GREEN], rgb[BLUE]);
// set new state
LightState state = new LightState(hueLight.isOn());
state.setHue((int) ((float)hsv[0] /360 * 65535f));
state.setSat((int) ((float)hsv[2] * 2.55f));
state.setBri((int) ((float)hsv[1] * 2.55f));
hueLight.setState(state);
}
private void setColors(Integer red, Integer green, Integer blue) {
// get current state
LightState currentLightState = hueLight.getState();
//int h = Math.round(((float) currentLightState.getHue()) / 65565f * 360f);
int h = Math.round(((float) currentLightState.getHue()) / 65535f * 360f);
int s = Math.round(((float) currentLightState.getBri()) / 255f * 100f );
int v = Math.round(((float) currentLightState.getSat()) / 255f * 100f);
// convert current color in rgb
int[] rgb = HSVtoRGB(h, s, v);
// update values
if (red != null)
rgb[RED] = red;
if (green != null)
rgb[GREEN] = green;
if (blue != null)
rgb[BLUE] = blue;
// compute HSV
int[] hsv = RGBtoHSB(rgb[RED], rgb[GREEN], rgb[BLUE]);
// set new state
LightState state = new LightState(hueLight.isOn());
state.setHue((int) ((float)hsv[0] /360 * 65535f));
// JW 2016.04.18
// state.setSat((int) ((float)hsv[2] * 2.55f));
// state.setBri((int) ((float)hsv[1] * 2.55f));
state.setSat((int) ((float)hsv[1] * 2.55f));
state.setBri((int) ((float)hsv[2] * 2.55f));
hueLight.setState(state);
}
private Integer getColor(int colorIndex) {
// get current state
LightState currentLightState = hueLight.getState();
int h = Math.round(((float)currentLightState.getHue()) / 65535f * 360f);
// JW 2018.04.18
// int s = Math.round(((float) currentLightState.getBri()) / 255f * 100f);
// int v = Math.round(((float) currentLightState.getSat()) / 255f * 100f);
int v = Math.round(((float) currentLightState.getBri()) / 255f * 100f);
int s = Math.round(((float) currentLightState.getSat()) / 255f * 100f);
// convert current color in rgb
int[] rgb = HSVtoRGB(h, s, v);
return new Integer(rgb[colorIndex]);
}
private int[] getColors() {
// get current state
LightState currentLightState = hueLight.getState();
int h = Math.round(((float)currentLightState.getHue()) / 65535f * 360f);
// JW 2018.04.18
// int s = Math.round(((float) currentLightState.getBri()) / 255f * 100f);
// int v = Math.round(((float) currentLightState.getSat()) / 255f * 100f);
int v = Math.round(((float) currentLightState.getBri()) / 255f * 100f);
int s = Math.round(((float) currentLightState.getSat()) / 255f * 100f);
// convert current color in rgb
return HSVtoRGB(h, s, v);
}
/**
* Convert RGB color to HSV color
*
* @param r
* red. between 0 and 255
* @param g
* green. between 0 and 255
* @param b
* blue. between 0 and 255
* @return hsv color (index 0: h between 0 and 360; index 1: s between 0 and
* 100, index 2: v between 0 and 100)
*/
protected static int[] RGBtoHSB(int r, int g, int b) {
float hue = 0, saturation = 0;
int[] hsbvals = new int[3];
int cmax = (r > g) ? r : g;
if (b > cmax)
cmax = b;
int cmin = (r < g) ? r : g;
if (b < cmin)
cmin = b;
float brightness = ((float) cmax) / 255.0f;
if (cmax != 0)
saturation = ((float) (cmax - cmin)) / ((float) cmax);
if (saturation != 0) {
float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
if (r == cmax)
hue = bluec - greenc;
else if (g == cmax)
hue = 2.0f + redc - bluec;
else
hue = 4.0f + greenc - redc;
hue = hue / 6.0f;
if (hue < 0)
hue = hue + 1.0f;
}
hsbvals[0] = Math.round(hue * 360f);
hsbvals[1] = Math.round(saturation * 100f);
hsbvals[2] = Math.round(brightness * 100f);
return hsbvals;
}
/**
* Convert HSV color into RGB color
*
* @param h
* hue. between 0 and 360 (degres)
* @param s
* saturation. between 0 and 100 (%)
* @param v
* brighness. between 0 and 100 (%)
* @return rgb color (index 0: r between 0 and 255; index 1: g between 0 and
* 255; index 2 : b between 0 255).
*/
protected static int[] HSVtoRGB(int h, int s, int v) {
float hh, p, q, t, ff;
float i;
int[] out = new int[3];
float r, g, b, hFloat, sFloat, vFloat;
hFloat = ((float) h) / 360f;
sFloat = ((float) s) / 100f;
vFloat = ((float) v) / 100f;
if (s <= 0.0) { // < is bogus, just shuts up warnings
out[0] = (int) (vFloat * 255);
out[1] = (int) (vFloat * 255);
out[2] = (int) (vFloat * 255);
return out;
}
hh = hFloat * 6;
if (hh == 6)
hh = 0.0f;
i = (float) Math.floor(hh);
ff = hh - i;
p = v * (1.0f - sFloat);
q = v * (1.0f - (sFloat * ff));
t = v * (1.0f - (sFloat * (1.0f - ff)));
switch ((int) i) {
case 0:
r = v;
g = (float) t;
b = (float) p;
break;
case 1:
r = (float) q;
g = v;
b = (float) p;
break;
case 2:
r = (float) p;
g = v;
b = (float) t;
break;
case 3:
r = (float) p;
g = (float) q;
b = v;
break;
case 4:
r = (float) t;
g = (float) p;
b = v;
break;
case 5:
default:
r = v;
g = (float) p;
b = (float) q;
break;
}
out[0] = Math.round(r * 2.55f);
out[1] = Math.round(g * 2.55f);
out[2] = Math.round(b * 2.55f);
return out;
}
}