mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-22 09:22:23 +00:00
Updating color handling
This commit is contained in:
@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.plugins.hue.HueHome;
|
||||
import com.bwssystems.HABridge.util.BackupHandler;
|
||||
@@ -67,7 +68,10 @@ public class DeviceRepository extends BackupHandler {
|
||||
{
|
||||
DeviceDescriptor list[] = gson.fromJson(jsonContent, DeviceDescriptor[].class);
|
||||
for(int i = 0; i < list.length; i++) {
|
||||
list[i].setDeviceState(null);
|
||||
if(list[i].getColorUrl() == null || list[i].getColorUrl().isEmpty())
|
||||
list[i].setDeviceState(DeviceState.createDeviceState(false));
|
||||
else
|
||||
list[i].setDeviceState(DeviceState.createDeviceState(true));
|
||||
put(list[i].getId(), list[i]);
|
||||
if(Integer.decode(list[i].getId()) > nextId) {
|
||||
nextId = Integer.decode(list[i].getId());
|
||||
|
||||
@@ -4,8 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.awt.Color;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -24,91 +23,174 @@ public class ColorDecode {
|
||||
private static final String COLOR_HSL = "${color.hsl}";
|
||||
private static final Pattern COLOR_MILIGHT = Pattern.compile("\\$\\{color.milight\\:([01234])\\}");
|
||||
|
||||
public static List<Integer> convertHSLtoRGB(int hue, int sat, int brightness) {
|
||||
List<Integer> rgb;
|
||||
float decimalBrightness = (float) 0.0;
|
||||
float var_1 = (float) 0.0;
|
||||
float var_2 = (float) 0.0;
|
||||
float h = (float) 0.0;
|
||||
float h2 = (float) 0.0;
|
||||
float s = (float) 0.0;
|
||||
double r = 0.0;
|
||||
double g = 0.0;
|
||||
double b = 0.0;
|
||||
|
||||
if(brightness > 0)
|
||||
decimalBrightness = (float) (brightness / 255.0);
|
||||
|
||||
if(hue > 0) {
|
||||
h = (float)(hue / 65535.0);
|
||||
h2 = h + (float)0.5;
|
||||
if(h2 > 1) {
|
||||
h2 = h2 * (float) -1.0;
|
||||
}
|
||||
}
|
||||
if(sat > 0) {
|
||||
s = (float)(sat / 254.0);
|
||||
}
|
||||
|
||||
if (s == 0)
|
||||
{
|
||||
r = decimalBrightness * 255;
|
||||
g = decimalBrightness * 255;
|
||||
b = decimalBrightness * 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (decimalBrightness < 0.5)
|
||||
{
|
||||
var_2 = decimalBrightness * (1 + s);
|
||||
}
|
||||
else
|
||||
{
|
||||
var_2 = (decimalBrightness + s) - (s * decimalBrightness);
|
||||
};
|
||||
|
||||
var_1 = 2 * decimalBrightness - var_2;
|
||||
r = 255 * hue_2_rgb(var_1,var_2,h2 + (1 / 3));
|
||||
g = 255 * hue_2_rgb(var_1,var_2,h2);
|
||||
b = 255 * hue_2_rgb(var_1,var_2,h2 - (1 / 3));
|
||||
};
|
||||
|
||||
rgb = new ArrayList<Integer>();
|
||||
rgb.add((int) Math.round(r * 255));
|
||||
rgb.add((int) Math.round(g * 255));
|
||||
rgb.add((int) Math.round(b * 255));
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
public static float hue_2_rgb(float v1, float v2, float vh) {
|
||||
if (vh < 0)
|
||||
{
|
||||
vh += 1;
|
||||
};
|
||||
|
||||
if (vh > 1)
|
||||
{
|
||||
vh -= 1;
|
||||
};
|
||||
|
||||
if ((6 * vh) < 1)
|
||||
{
|
||||
return (v1 + (v2 - v1) * 6 * vh);
|
||||
};
|
||||
|
||||
if ((2 * vh) < 1)
|
||||
{
|
||||
return (v2);
|
||||
};
|
||||
|
||||
if ((3 * vh) < 2)
|
||||
{
|
||||
return (v1 + (v2 - v1) * ((2 / 3 - vh) * 6));
|
||||
};
|
||||
|
||||
return (v1);
|
||||
}
|
||||
|
||||
public static List<Integer> convertCIEtoRGB(List<Double> xy, int brightness) {
|
||||
List<Integer> rgb;
|
||||
double x = xy.get(0); // the given x value
|
||||
double y = xy.get(1); // the given y value
|
||||
double z = 1.0 - x - y;
|
||||
double Y = (double)brightness/(double)254.00; // The given brightness value
|
||||
double Y = (double) brightness / (double) 254.00; // The given brightness value
|
||||
double X = (Y / y) * x;
|
||||
double Z = (Y / y) * z;
|
||||
|
||||
double r = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
|
||||
double r = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
|
||||
double g = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
|
||||
double b = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
|
||||
double b = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
|
||||
|
||||
if (r > b && r > g && r > 1.0) {
|
||||
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0;
|
||||
}
|
||||
else if (g > b && g > r && g > 1.0) {
|
||||
} else if (g > b && g > r && g > 1.0) {
|
||||
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0;
|
||||
}
|
||||
else if (b > r && b > g && b > 1.0) {
|
||||
} else if (b > r && b > g && b > 1.0) {
|
||||
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0;
|
||||
}
|
||||
|
||||
|
||||
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
|
||||
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
|
||||
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
|
||||
|
||||
if (r > b && r > g) {
|
||||
// red is biggest
|
||||
if (r > 1.0) {
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0;
|
||||
}
|
||||
}
|
||||
else if (g > b && g > r) {
|
||||
// green is biggest
|
||||
if (g > 1.0) {
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0;
|
||||
}
|
||||
}
|
||||
else if (b > r && b > g) {
|
||||
// blue is biggest
|
||||
if (b > 1.0) {
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0;
|
||||
}
|
||||
}
|
||||
if(r < 0.0)
|
||||
r = 0;
|
||||
if(g < 0.0)
|
||||
g = 0;
|
||||
if(b < 0.0)
|
||||
b = 0;
|
||||
|
||||
rgb = new ArrayList<Integer>();
|
||||
rgb.add((int)Math.round(r * 255));
|
||||
rgb.add((int)Math.round(g * 255));
|
||||
rgb.add((int)Math.round(b * 255));
|
||||
log.debug("Color change with XY: " + x + " " + y + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
if (r > b && r > g) {
|
||||
// red is biggest
|
||||
if (r > 1.0) {
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0;
|
||||
}
|
||||
} else if (g > b && g > r) {
|
||||
// green is biggest
|
||||
if (g > 1.0) {
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0;
|
||||
}
|
||||
} else if (b > r && b > g) {
|
||||
// blue is biggest
|
||||
if (b > 1.0) {
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0;
|
||||
}
|
||||
}
|
||||
if (r < 0.0)
|
||||
r = 0;
|
||||
if (g < 0.0)
|
||||
g = 0;
|
||||
if (b < 0.0)
|
||||
b = 0;
|
||||
|
||||
rgb = new ArrayList<Integer>();
|
||||
rgb.add((int) Math.round(r * 255));
|
||||
rgb.add((int) Math.round(g * 255));
|
||||
rgb.add((int) Math.round(b * 255));
|
||||
log.debug("Color change with XY: " + x + " " + y + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1)
|
||||
+ " " + rgb.get(2));
|
||||
return rgb;
|
||||
}
|
||||
|
||||
// took that approximation from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
|
||||
// took that approximation from
|
||||
// http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
|
||||
public static List<Integer> convertCTtoRGB(Integer ct) {
|
||||
double temperature = 1000000.0 / (double)ct;
|
||||
double temperature = 1000000.0 / (double) ct;
|
||||
temperature /= 100;
|
||||
double r,g,b;
|
||||
double r, g, b;
|
||||
if (temperature <= 66) {
|
||||
r = 255;
|
||||
g = temperature;
|
||||
g = 99.4708025861 * Math.log(g) - 161.1195681661;
|
||||
g = 99.4708025861 * Math.log(g) - 161.1195681661;
|
||||
} else {
|
||||
r = temperature - 60;
|
||||
r = 329.698727446 * (Math.pow(r, -0.1332047592));
|
||||
@@ -126,25 +208,26 @@ public class ColorDecode {
|
||||
b = 138.5177312231 * Math.log(b) - 305.0447927307;
|
||||
}
|
||||
}
|
||||
r = assureBounds(r);
|
||||
g = assureBounds(g);
|
||||
b = assureBounds(b);
|
||||
List<Integer> rgb = new ArrayList<Integer>();
|
||||
rgb.add((int)Math.round(r));
|
||||
rgb.add((int)Math.round(g));
|
||||
rgb.add((int)Math.round(b));
|
||||
log.debug("Color change with CT: " + ct + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return rgb;
|
||||
r = assureBounds(r);
|
||||
g = assureBounds(g);
|
||||
b = assureBounds(b);
|
||||
List<Integer> rgb = new ArrayList<Integer>();
|
||||
rgb.add((int) Math.round(r));
|
||||
rgb.add((int) Math.round(g));
|
||||
rgb.add((int) Math.round(b));
|
||||
log.debug("Color change with CT: " + ct + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " "
|
||||
+ rgb.get(2));
|
||||
return rgb;
|
||||
}
|
||||
|
||||
private static double assureBounds(double value) {
|
||||
if (value < 0.0) {
|
||||
value = 0;
|
||||
}
|
||||
if (value > 255.0) {
|
||||
value = 255;
|
||||
}
|
||||
return value;
|
||||
value = 0;
|
||||
}
|
||||
if (value > 255.0) {
|
||||
value = 255;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -159,25 +242,28 @@ public class ColorDecode {
|
||||
ColorData.ColorMode colorMode = colorData.getColorMode();
|
||||
List<Integer> rgb = null;
|
||||
if (colorMode == ColorData.ColorMode.XY) {
|
||||
rgb = convertCIEtoRGB((List<Double>)colorData.getData(), setIntensity);
|
||||
rgb = convertCIEtoRGB((List<Double>) colorData.getData(), setIntensity);
|
||||
} else if (colorMode == ColorData.ColorMode.CT) {
|
||||
rgb = convertCTtoRGB((Integer)colorData.getData());
|
||||
rgb = convertCTtoRGB((Integer) colorData.getData());
|
||||
}
|
||||
|
||||
while(notDone) {
|
||||
|
||||
while (notDone) {
|
||||
notDone = false;
|
||||
if (request.contains(COLOR_R)) {
|
||||
request = request.replace(COLOR_R, isHex ? String.format("%02X", rgb.get(0)) : String.valueOf(rgb.get(0)));
|
||||
request = request.replace(COLOR_R,
|
||||
isHex ? String.format("%02X", rgb.get(0)) : String.valueOf(rgb.get(0)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_G)) {
|
||||
request = request.replace(COLOR_G, isHex ? String.format("%02X", rgb.get(1)) : String.valueOf(rgb.get(1)));
|
||||
request = request.replace(COLOR_G,
|
||||
isHex ? String.format("%02X", rgb.get(1)) : String.valueOf(rgb.get(1)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_B)) {
|
||||
request = request.replace(COLOR_B, isHex ? String.format("%02X", rgb.get(2)) : String.valueOf(rgb.get(2)));
|
||||
request = request.replace(COLOR_B,
|
||||
isHex ? String.format("%02X", rgb.get(2)) : String.valueOf(rgb.get(2)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
@@ -197,75 +283,78 @@ public class ColorDecode {
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_RGBX)) {
|
||||
request = request.replace(COLOR_RGBX, String.format("%02X%02X%02X", rgb.get(0), rgb.get(1), rgb.get(2)));
|
||||
request = request.replace(COLOR_RGBX,
|
||||
String.format("%02X%02X%02X", rgb.get(0), rgb.get(1), rgb.get(2)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_HSL)) {
|
||||
float[] hsb = new float[3];
|
||||
Color.RGBtoHSB(rgb.get(0),rgb.get(1),rgb.get(2),hsb);
|
||||
float hue = hsb[0] * (float) 360.0;
|
||||
float sat = hsb[1] * (float) 100.0;
|
||||
float bright = hsb[2] * (float) 100.0;
|
||||
request = request.replace(COLOR_HSL, String.format("%f,%f,%f", hue, sat, bright));
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_HSL)) {
|
||||
float[] hsb = new float[3];
|
||||
Color.RGBtoHSB(rgb.get(0), rgb.get(1), rgb.get(2), hsb);
|
||||
float hue = hsb[0] * (float) 360.0;
|
||||
float sat = hsb[1] * (float) 100.0;
|
||||
float bright = hsb[2] * (float) 100.0;
|
||||
request = request.replace(COLOR_HSL, String.format("%f,%f,%f", hue, sat, bright));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Matcher m = COLOR_MILIGHT.matcher(request);
|
||||
while (m.find()) {
|
||||
int group = Integer.parseInt(m.group(1));
|
||||
request = m.replaceFirst(getMilightV5FromRgb(rgb, group));
|
||||
m.reset(request);
|
||||
int group = Integer.parseInt(m.group(1));
|
||||
request = m.replaceFirst(getMilightV5FromRgb(rgb, group));
|
||||
m.reset(request);
|
||||
}
|
||||
|
||||
|
||||
log.debug("Request <<" + request + ">>, not done: " + notDone);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private static String getMilightV5FromRgb(List<Integer> rgb, int group) {
|
||||
double r = (double)rgb.get(0);
|
||||
double g = (double)rgb.get(1);
|
||||
double b = (double)rgb.get(2);
|
||||
if (r > 245 && g > 245 && b > 245) { // it's white
|
||||
String retVal = "";
|
||||
if (group == 0) {
|
||||
retVal += "C2";
|
||||
} else if (group == 1) {
|
||||
retVal += "C5";
|
||||
} else if (group == 2) {
|
||||
retVal += "C7";
|
||||
} else if (group == 3) {
|
||||
retVal += "C9";
|
||||
} else if (group == 4) {
|
||||
retVal += "CB";
|
||||
}
|
||||
log.debug("Convert RGB to Milight. Result: WHITE. RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return retVal + "0055";
|
||||
} else { // normal color
|
||||
r /= (double)0xFF;
|
||||
g /= (double)0xFF;
|
||||
b /= (double)0xFF;
|
||||
double max = Math.max(Math.max(r, g), b), min = Math.min(Math.min(r, g), b);
|
||||
double h = 0;
|
||||
double d = max - min;
|
||||
double r = (double) rgb.get(0);
|
||||
double g = (double) rgb.get(1);
|
||||
double b = (double) rgb.get(2);
|
||||
if (r > 245 && g > 245 && b > 245) { // it's white
|
||||
String retVal = "";
|
||||
if (group == 0) {
|
||||
retVal += "C2";
|
||||
} else if (group == 1) {
|
||||
retVal += "C5";
|
||||
} else if (group == 2) {
|
||||
retVal += "C7";
|
||||
} else if (group == 3) {
|
||||
retVal += "C9";
|
||||
} else if (group == 4) {
|
||||
retVal += "CB";
|
||||
}
|
||||
log.debug("Convert RGB to Milight. Result: WHITE. RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " "
|
||||
+ rgb.get(2));
|
||||
return retVal + "0055";
|
||||
} else { // normal color
|
||||
r /= (double) 0xFF;
|
||||
g /= (double) 0xFF;
|
||||
b /= (double) 0xFF;
|
||||
double max = Math.max(Math.max(r, g), b), min = Math.min(Math.min(r, g), b);
|
||||
double h = 0;
|
||||
double d = max - min;
|
||||
|
||||
if (max == min) {
|
||||
h = 0;
|
||||
} else {
|
||||
if (max == r) {
|
||||
h = ((g - b) / d + (g < b ? 6 : 0));
|
||||
} else if (max == g) {
|
||||
h = ((b - r) / d + 2);
|
||||
} else if (max == b){
|
||||
h = ((r - g) / d + 4);
|
||||
}
|
||||
h = Math.round(h * 60);
|
||||
}
|
||||
int milight = (int)((256 + 176 - Math.floor(h / 360.0 * 255.0)) % 256);
|
||||
log.debug("Convert RGB to Milight. Result: " + milight + " RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return "40" + String.format("%02X", milight) + "55";
|
||||
}
|
||||
if (max == min) {
|
||||
h = 0;
|
||||
} else {
|
||||
if (max == r) {
|
||||
h = ((g - b) / d + (g < b ? 6 : 0));
|
||||
} else if (max == g) {
|
||||
h = ((b - r) / d + 2);
|
||||
} else if (max == b) {
|
||||
h = ((r - g) / d + 4);
|
||||
}
|
||||
h = Math.round(h * 60);
|
||||
}
|
||||
int milight = (int) ((256 + 176 - Math.floor(h / 360.0 * 255.0)) % 256);
|
||||
log.debug("Convert RGB to Milight. Result: " + milight + " RGB Values: " + rgb.get(0) + " " + rgb.get(1)
|
||||
+ " " + rgb.get(2));
|
||||
return "40" + String.format("%02X", milight) + "55";
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -600,8 +600,8 @@ public class HueMulator {
|
||||
if((deviceState != null) && deviceState.isOn() && deviceState.getBri() <= 0)
|
||||
deviceState.setBri(254);
|
||||
|
||||
if((deviceState != null) && !deviceState.isOn() && (targetBri != null || targetBriInc != null))
|
||||
deviceState.setOn(true);
|
||||
// if((deviceState != null) && !deviceState.isOn() && (targetBri != null || targetBriInc != null))
|
||||
// deviceState.setOn(true);
|
||||
|
||||
responseString = responseString + "]";
|
||||
|
||||
@@ -1186,11 +1186,11 @@ public class HueMulator {
|
||||
isOnRequest = true;
|
||||
}
|
||||
|
||||
if(!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest) {
|
||||
if(!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest && !isOnRequest) {
|
||||
isOnRequest = true;
|
||||
theStateChanges.setOn(true);
|
||||
} else if(!device.isOnFirstDim() && !device.isOnWhenDimPresent() && isDimRequest) {
|
||||
isOnRequest = false;
|
||||
// isOnRequest = false;
|
||||
}
|
||||
|
||||
if(device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) {
|
||||
|
||||
Reference in New Issue
Block a user