blob: c0c9a97211acd1b80059aae9e17f10a1f80e81ae [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2016 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/
*******************************************************************************/
package org.eclipse.om2m.sdt.home.lifx.sdt;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.DataPointException;
import org.eclipse.om2m.sdt.home.devices.Light;
import org.eclipse.om2m.sdt.home.lifx.LIFXDevice;
import org.eclipse.om2m.sdt.home.modules.BinarySwitch;
import org.eclipse.om2m.sdt.home.modules.Colour;
import org.eclipse.om2m.sdt.home.types.DatapointType;
public class LIFXSDTDevice 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 final LIFXDevice lifxDevice;
public LIFXSDTDevice(Domain domain, LIFXDevice pLIFXDevice) {
super(computeLifxDeviceId(pLIFXDevice), computeLifxDeviceSerial(pLIFXDevice), domain);
this.lifxDevice = pLIFXDevice;
setDeviceAliasName("LIFX Color Bubble");
setDeviceManufacturer("LIFX");
setDeviceModelName("Color 1000");
try {
setDeviceName(pLIFXDevice.getLabel());
} catch (Exception e1) {
e1.printStackTrace();
}
setProtocol("LIFX");
// binary switch module
BinarySwitch binarySwitch = new BinarySwitch(getSerialNumber() + "_BinarySwitch", domain,
new BooleanDataPoint(DatapointType.powerState) {
@Override
protected Boolean doGetValue() throws DataPointException {
try {
return lifxDevice.getPower(false) != 0;
} catch (Exception e) {
throw new DataPointException("Error when retrieving power state:" + e.getMessage());
}
}
@Override
protected void doSetValue(Boolean value) throws DataPointException {
try {
lifxDevice.setPower((value ? 65535 : 0), 0);
} catch (Exception e) {
throw new DataPointException("Error when setting power state:" + e.getMessage());
}
}
});
addModule(binarySwitch);
Colour colourModule = new Colour(getSerialNumber() + "_Colour", domain,
new IntegerDataPoint(DatapointType.red) {
@Override
protected Integer doGetValue() throws DataPointException {
try {
return getColor(RED);
} catch (Exception e) {
throw new DataPointException(e.getMessage());
}
}
@Override
protected void doSetValue(Integer value) throws DataPointException {
try {
setColor(RED, value);
} catch (Exception e) {
throw new DataPointException(e.getMessage());
}
}
},
new IntegerDataPoint(DatapointType.green) {
@Override
protected Integer doGetValue() throws DataPointException {
try {
return getColor(GREEN);
} catch (Exception e) {
throw new DataPointException(e.getMessage());
}
}
@Override
protected void doSetValue(Integer value) throws DataPointException {
try {
setColor(GREEN, value);
} catch (Exception e) {
throw new DataPointException(e.getMessage());
}
}
},
new IntegerDataPoint(DatapointType.blue) {
@Override
protected Integer doGetValue() throws DataPointException {
try {
return getColor(BLUE);
} catch (Exception e) {
throw new DataPointException(e.getMessage());
}
}
@Override
protected void doSetValue(Integer value) throws DataPointException {
try {
setColor(BLUE, value);
} catch (Exception e) {
throw new DataPointException(e.getMessage());
}
}
});
colourModule.setDatapointHandler(new Module.DatapointHandler() {
@Override
public void setValues(Map<String, Object> values)
throws DataPointException, AccessException {
try {
setColors((Integer) values.get(SRED),
(Integer) values.get(SGREEN),
(Integer) values.get(SBLUE));
} catch (Exception e) {
throw new DataPointException(e);
}
}
@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(colourModule);
}
private static String computeLifxDeviceId(LIFXDevice pLIFXDevice) {
return pLIFXDevice.getId().replaceAll(":", "_");
}
private static String computeLifxDeviceSerial(LIFXDevice pLIFXDevice) {
return pLIFXDevice.getId().replaceAll(":", "_");
}
private void setColor(int colorIndex, int colorValue) throws Exception {
// get current state
int h = Math.round((float) (lifxDevice.getHue() / 65565d * 360d));
int s = Math.round((float) (lifxDevice.getSaturation() / 65535d * 100d));
int v = Math.round((float) (lifxDevice.getBrightness() / 65535d * 100d));
// 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
double newHue = ((double)hsv[0]) / 360d * 65535d;
double newSaturation = ((double) hsv[1]) / 100d * 65535d;
double newBrightness = ((double) hsv[2]) / 100d * 65535d;
lifxDevice.setLightState(65535, newHue, newSaturation, lifxDevice.getKelvin(), newBrightness, 0);
}
private void setColors(Integer red, Integer green, Integer blue) throws Exception {
lifxDevice.setLightState(65535, red, green, blue, 0);
}
private Integer getColor(int colorIndex) throws Exception {
// get current state
int h = Math.round((float) (lifxDevice.getHue() / 65565d * 360d));
int s = Math.round((float) (lifxDevice.getSaturation() / 65535d * 100d));
int v = Math.round((float) (lifxDevice.getBrightness() / 65535d * 100d));
// convert current color in rgb
int[] rgb = HSVtoRGB(h, s, v);
return new Integer(rgb[colorIndex]);
}
private int[] getColors() {
// get current state
int h = Math.round((float) (lifxDevice.getHue() / 65565d * 360d));
int s = Math.round((float) (lifxDevice.getSaturation() / 65535d * 100d));
int v = Math.round((float) (lifxDevice.getBrightness() / 65535d * 100d));
// 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, saturation, brightness;
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;
brightness = ((float) cmax) / 255.0f;
if (cmax != 0)
saturation = ((float) (cmax - cmin)) / ((float) cmax);
else
saturation = 0;
if (saturation == 0)
hue = 0;
else {
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;
}
}