Compare commits

...

2 Commits

Author SHA1 Message Date
bwssystems
675e74df7b Add switch for dim when color request is present and other items 2020-12-08 17:03:24 -06:00
bwssystems
fb7aabb780 Fix all color handling and dim with no on request 2020-12-07 18:07:42 -06:00
16 changed files with 475 additions and 187 deletions

View File

@@ -57,20 +57,20 @@ Then locate the jar and start the server with:
ATTENTION: Due to port 80 being the default, Linux restricts this to super user. Use the instructions below. ATTENTION: Due to port 80 being the default, Linux restricts this to super user. Use the instructions below.
``` ```
java -jar ha-bridge-5.3.1RC3.jar java -jar ha-bridge-5.3.1RC5.jar
``` ```
## Manual installation of ha-bridge and setup of systemd service ## Manual installation of ha-bridge and setup of systemd service
Next gen Linux systems (this includes the Raspberry Pi), use systemd to run and manage services. Next gen Linux systems (this includes the Raspberry Pi), use systemd to run and manage services.
Here is a link on how to use systemd: https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units Here is a link on how to use systemd: https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
Create the directory and make sure that ha-bridge-5.3.1RC3.jar is in your /home/pi/ha-bridge directory. Create the directory and make sure that ha-bridge-5.3.1RC5.jar is in your /home/pi/ha-bridge directory.
``` ```
pi@raspberrypi:~ $ mkdir ha-bridge pi@raspberrypi:~ $ mkdir ha-bridge
pi@raspberrypi:~ $ cd ha-bridge pi@raspberrypi:~ $ cd ha-bridge
pi@raspberrypi:~/ha-bridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.3.1RC3/ha-bridge-5.3.1RC3.jar pi@raspberrypi:~/ha-bridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.3.1RC5/ha-bridge-5.3.1RC5.jar
``` ```
Create the ha-bridge.service unit file: Create the ha-bridge.service unit file:
@@ -89,7 +89,7 @@ After=network.target
Type=simple Type=simple
WorkingDirectory=/home/pi/ha-bridge WorkingDirectory=/home/pi/ha-bridge
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/ha-bridge/data/habridge.config /home/pi/ha-bridge/ha-bridge-5.3.1RC3.jar ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/ha-bridge/data/habridge.config /home/pi/ha-bridge/ha-bridge-5.3.1RC5.jar
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId> <groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId> <artifactId>ha-bridge</artifactId>
<version>5.3.1RC3</version> <version>5.3.1RC5-java11</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>HA Bridge</name> <name>HA Bridge</name>

View File

@@ -200,7 +200,10 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setNumberoflogmessages(Integer.valueOf(Configuration.NUMBER_OF_LOG_MESSAGES)); theBridgeSettings.setNumberoflogmessages(Integer.valueOf(Configuration.NUMBER_OF_LOG_MESSAGES));
if(theBridgeSettings.getButtonsleep() == null || theBridgeSettings.getButtonsleep() < 0) if(theBridgeSettings.getButtonsleep() == null || theBridgeSettings.getButtonsleep() < 0)
theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP)); theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP));
if(theBridgeSettings.getLinkbuttontimeout() < 30)
theBridgeSettings.setLinkbuttontimeout(Configuration.LINK_BUTTON_TIMEOUT);
theBridgeSettings.setVeraconfigured(theBridgeSettings.isValidVera()); theBridgeSettings.setVeraconfigured(theBridgeSettings.isValidVera());
theBridgeSettings.setFibaroconfigured(theBridgeSettings.isValidFibaro()); theBridgeSettings.setFibaroconfigured(theBridgeSettings.isValidFibaro());

View File

@@ -135,6 +135,10 @@ public class BridgeSettingsDescriptor {
@SerializedName("upnpadvanced") @SerializedName("upnpadvanced")
@Expose @Expose
private boolean upnpadvanced; private boolean upnpadvanced;
@SerializedName("linkbuttontimeout")
@Expose
private Integer linkbuttontimeout;
// @SerializedName("activeloggers") // @SerializedName("activeloggers")
// @Expose // @Expose
// private List<NameValue> activeloggers; // private List<NameValue> activeloggers;
@@ -197,6 +201,7 @@ public class BridgeSettingsDescriptor {
this.haaddressessecured = false; this.haaddressessecured = false;
this.configfile = Configuration.CONFIG_FILE; this.configfile = Configuration.CONFIG_FILE;
this.upnpadvanced = false; this.upnpadvanced = false;
this.linkbuttontimeout = Configuration.LINK_BUTTON_TIMEOUT;
} }
public String getUpnpConfigAddress() { public String getUpnpConfigAddress() {
@@ -860,4 +865,12 @@ public class BridgeSettingsDescriptor {
public void setUpnpadvanced(boolean upnpadvanced) { public void setUpnpadvanced(boolean upnpadvanced) {
this.upnpadvanced = upnpadvanced; this.upnpadvanced = upnpadvanced;
} }
public Integer getLinkbuttontimeout() {
return linkbuttontimeout;
}
public void setLinkbuttontimeout(Integer linkbuttontimeout) {
this.linkbuttontimeout = linkbuttontimeout;
}
} }

View File

@@ -17,4 +17,5 @@ public class Configuration {
public static final int UPNP_SEND_DELAY = 650; public static final int UPNP_SEND_DELAY = 650;
public static final int BROADLINK_DISCOVER_PORT = 40000; public static final int BROADLINK_DISCOVER_PORT = 40000;
public static final int BROADLINK_DISCONVER_TIMEOUT = 5000; public static final int BROADLINK_DISCONVER_TIMEOUT = 5000;
public static final int LINK_BUTTON_TIMEOUT = 45;
} }

View File

@@ -276,12 +276,12 @@ public class SystemControl {
if(!request.body().isEmpty()) { if(!request.body().isEmpty()) {
linkParams = new Gson().fromJson(request.body(), LinkParams.class); linkParams = new Gson().fromJson(request.body(), LinkParams.class);
if(linkParams.getSeconds() <= 0) if(linkParams.getSeconds() <= 0)
linkParams.setSeconds(1); linkParams.setSeconds(3);
} }
else { else {
linkParams = new LinkParams(); linkParams = new LinkParams();
linkParams.setSilent(false); linkParams.setSilent(false);
linkParams.setSeconds(30); linkParams.setSeconds(bridgeSettings.getBridgeSettingsDescriptor().getLinkbuttontimeout());
} }
if(!linkParams.isSilent()) if(!linkParams.isSilent())
log.info("Link button pressed...."); log.info("Link button pressed....");

View File

@@ -92,6 +92,12 @@ public class DeviceDescriptor{
@SerializedName("startupActions") @SerializedName("startupActions")
@Expose @Expose
private String startupActions; private String startupActions;
@SerializedName("dimNoOn")
@Expose
private boolean dimNoOn;
@SerializedName("dimOnColor")
@Expose
private boolean dimOnColor;
public String getName() { public String getName() {
return name; return name;
@@ -355,4 +361,20 @@ public class DeviceDescriptor{
public void setStartupActions(String startupActions) { public void setStartupActions(String startupActions) {
this.startupActions = startupActions; this.startupActions = startupActions;
} }
public boolean isDimNoOn() {
return dimNoOn;
}
public void setDimNoOn(boolean dimNoOn) {
this.dimNoOn = dimNoOn;
}
public boolean isDimOnColor() {
return dimOnColor;
}
public void setDimOnColor(boolean dimOnColor) {
this.dimOnColor = dimOnColor;
}
} }

View File

@@ -21,6 +21,9 @@ public class BrightnessDecode {
private static final String INTENSITY_MATH_CLOSE_HEX = ").hex}"; private static final String INTENSITY_MATH_CLOSE_HEX = ").hex}";
private static final String INTENSITY_PERCENT_HEX = "${intensity.percent.hex}"; private static final String INTENSITY_PERCENT_HEX = "${intensity.percent.hex}";
private static final String INTENSITY_BYTE_HEX = "${intensity.byte.hex}"; private static final String INTENSITY_BYTE_HEX = "${intensity.byte.hex}";
private static final String INTENSITY_PREVIOUS_PERCENT = "${intensity.previous_percent}";
private static final String INTENSITY_PREVIOUS_DECIMAL_PERCENT = "${intensity.previous_decimal_percent}";
private static final String INTENSITY_PREVIOUS_BYTE = "${intensity.previous_byte}";
public static int calculateIntensity(int setIntensity, Integer targetBri, Integer targetBriInc) { public static int calculateIntensity(int setIntensity, Integer targetBri, Integer targetBriInc) {
if (targetBri != null) { if (targetBri != null) {
@@ -45,7 +48,7 @@ public class BrightnessDecode {
* intensity.math(X*1) : where X is the value from the interface call and * intensity.math(X*1) : where X is the value from the interface call and
* can use net.java.dev.eval math * can use net.java.dev.eval math
*/ */
public static String replaceIntensityValue(String request, int intensity, boolean isHex) { private static String replaceIntensityValue(String request, int previous_intensity, int intensity, boolean isHex) {
if (request == null) { if (request == null) {
return null; return null;
} }
@@ -54,6 +57,8 @@ public class BrightnessDecode {
String replaceTarget = null; String replaceTarget = null;
int percentBrightness = 0; int percentBrightness = 0;
float decimalBrightness = (float) 1.0; float decimalBrightness = (float) 1.0;
int previousPercentBrightness = 0;
float previousDecimalBrightness = (float) 1.0;
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>(); Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
String mathDescriptor = null; String mathDescriptor = null;
@@ -68,6 +73,17 @@ public class BrightnessDecode {
percentBrightness = 1; percentBrightness = 1;
} }
if(previous_intensity > 0) {
previousDecimalBrightness = (float) (previous_intensity / 255.0);
if(previous_intensity > 0 && previous_intensity < 5)
previousPercentBrightness = 1;
else
previousPercentBrightness = (int) Math.round(previous_intensity / 255.0 * 100);
} else {
previousDecimalBrightness = (float) 1.0;
previousPercentBrightness = 1;
}
while(notDone) { while(notDone) {
notDone = false; notDone = false;
if (request.contains(INTENSITY_BYTE)) { if (request.contains(INTENSITY_BYTE)) {
@@ -78,6 +94,14 @@ public class BrightnessDecode {
} }
replaceTarget = INTENSITY_BYTE; replaceTarget = INTENSITY_BYTE;
notDone = true; notDone = true;
} else if (request.contains(INTENSITY_PREVIOUS_BYTE)) {
if (isHex) {
replaceValue = convertToHex(previous_intensity);
} else {
replaceValue = String.valueOf(previous_intensity);
}
replaceTarget = INTENSITY_PREVIOUS_BYTE;
notDone = true;
} else if (request.contains(INTENSITY_BYTE_HEX)) { } else if (request.contains(INTENSITY_BYTE_HEX)) {
replaceValue = convertToHex(intensity); replaceValue = convertToHex(intensity);
replaceTarget = INTENSITY_BYTE_HEX; replaceTarget = INTENSITY_BYTE_HEX;
@@ -90,6 +114,14 @@ public class BrightnessDecode {
} }
replaceTarget = INTENSITY_PERCENT; replaceTarget = INTENSITY_PERCENT;
notDone = true; notDone = true;
} else if (request.contains(INTENSITY_PREVIOUS_PERCENT)) {
if (isHex) {
replaceValue = convertToHex(previousPercentBrightness);
} else {
replaceValue = String.valueOf(previousPercentBrightness);
}
replaceTarget = INTENSITY_PREVIOUS_PERCENT;
notDone = true;
} else if (request.contains(INTENSITY_PERCENT_HEX)) { } else if (request.contains(INTENSITY_PERCENT_HEX)) {
replaceValue = convertToHex(percentBrightness); replaceValue = convertToHex(percentBrightness);
replaceTarget = INTENSITY_PERCENT_HEX; replaceTarget = INTENSITY_PERCENT_HEX;
@@ -98,6 +130,10 @@ public class BrightnessDecode {
replaceValue = String.format(Locale.ROOT, "%1.2f", decimalBrightness); replaceValue = String.format(Locale.ROOT, "%1.2f", decimalBrightness);
replaceTarget = INTENSITY_DECIMAL_PERCENT; replaceTarget = INTENSITY_DECIMAL_PERCENT;
notDone = true; notDone = true;
} else if (request.contains(INTENSITY_PREVIOUS_DECIMAL_PERCENT)) {
replaceValue = String.format(Locale.ROOT, "%1.2f", previousDecimalBrightness);
replaceTarget = INTENSITY_PREVIOUS_DECIMAL_PERCENT;
notDone = true;
} else if (request.contains(INTENSITY_MATH_CLOSE)) { } else if (request.contains(INTENSITY_MATH_CLOSE)) {
mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(), mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(),
request.indexOf(INTENSITY_MATH_CLOSE)); request.indexOf(INTENSITY_MATH_CLOSE));
@@ -135,7 +171,7 @@ public class BrightnessDecode {
// Helper Method // Helper Method
public static String calculateReplaceIntensityValue(String request, int theIntensity, Integer targetBri, Integer targetBriInc, boolean isHex) { public static String calculateReplaceIntensityValue(String request, int theIntensity, Integer targetBri, Integer targetBriInc, boolean isHex) {
return replaceIntensityValue(request, calculateIntensity(theIntensity, targetBri, targetBriInc), isHex); return replaceIntensityValue(request, theIntensity, calculateIntensity(theIntensity, targetBri, targetBriInc), isHex);
} }
// Apache Commons Conversion utils likes little endian too much // Apache Commons Conversion utils likes little endian too much

View File

@@ -18,6 +18,8 @@ package com.bwssystems.HABridge.hue;
* XYZ -> CIE-LAB -> XYZ * XYZ -> CIE-LAB -> XYZ
* @author Diego Catalano * @author Diego Catalano
*/ */
public class ColorConverter { public class ColorConverter {
/** /**
@@ -26,6 +28,7 @@ public class ColorConverter {
private ColorConverter() {} private ColorConverter() {}
public static enum YCbCrColorSpace {ITU_BT_601,ITU_BT_709_HDTV}; public static enum YCbCrColorSpace {ITU_BT_601,ITU_BT_709_HDTV};
private final static double EPSILON = 0.00001;
// XYZ (Tristimulus) Reference values of a perfect reflecting diffuser // XYZ (Tristimulus) Reference values of a perfect reflecting diffuser
@@ -259,7 +262,7 @@ public class ColorConverter {
* @param blue Blue coefficient. * @param blue Blue coefficient.
* @return Normalized RGChromaticity. Range[0..1]. * @return Normalized RGChromaticity. Range[0..1].
*/ */
public static double[] RGChromaticity(int red, int green, int blue){ public static float[] RGChromaticity(int red, int green, int blue){
double[] color = new double[5]; double[] color = new double[5];
double sum = red + green + blue; double sum = red + green + blue;
@@ -276,24 +279,7 @@ public class ColorConverter {
double rS = color[0] - 0.333; double rS = color[0] - 0.333;
double gS = color[1] - 0.333; double gS = color[1] - 0.333;
//saturation //saturationBRGBtoHSV(int red, int green, int blue){
color[3] = Math.sqrt(rS * rS + gS * gS);
//hue
color[4] = Math.atan(rS / gS);
return color;
}
/**
* RGB -> HSV.
* Adds (hue + 360) % 360 for represent hue in the range [0..359].
* @param red Red coefficient. Values in the range [0..255].
* @param green Green coefficient. Values in the range [0..255].
* @param blue Blue coefficient. Values in the range [0..255].
* @return HSV color space.
*/
public static float[] RGBtoHSV(int red, int green, int blue){
float[] hsv = new float[3]; float[] hsv = new float[3];
float r = red / 255f; float r = red / 255f;
float g = green / 255f; float g = green / 255f;
@@ -633,66 +619,66 @@ public class ColorConverter {
} }
/** /**
* RGB -> HLS. * RGB -> HSL.
* @param red Red coefficient. Values in the range [0..255]. * @param red Red coefficient. Values in the range [0..255].
* @param green Green coefficient. Values in the range [0..255]. * @param green Green coefficient. Values in the range [0..255].
* @param blue Blue coefficient. Values in the range [0..255]. * @param blue Blue coefficient. Values in the range [0..255].
* @return HLS color space. * @return HSL color space.
*/ */
public static float[] RGBtoHLS(int red, int green, int blue){ public static float[] RGBtoHSL(int red, int green, int blue){
float[] hsl = new float[3]; float[] hsl = new float[3];
float r = red / 255f; double r = red;
float g = green / 255f; double g = green;
float b = blue / 255f; double b = blue;
float max = Math.max(r,Math.max(r,b)); double max = Math.max(r,Math.max(g,b));
float min = Math.min(r,Math.min(r,b)); double min = Math.min(r,Math.min(g,b));
float delta = max - min; // double delta = max - min;
//HSK //HSK
float h = 0; Double h = 0d;
float s = 0; Double s = 0d;
float l = (max + min) / 2; Double l = 0d;
if ( delta == 0 ){ //saturation
// gray color double cnt = (max + min) / 2d;
h = 0; if (cnt <= 127d) {
s = 0.0f; s = ((max - min) / (max + min));
}
else
{
// get saturation value
s = ( l <= 0.5 ) ? ( delta / ( max + min ) ) : ( delta / ( 2 - max - min ) );
// get hue value
float hue;
if ( r == max )
{
hue = ( ( g - b ) / 6 ) / delta;
} }
else if ( g == max ) else {
{ s = ((max - min) / (510d - max - min));
hue = ( 1.0f / 3 ) + ( ( b - r ) / 6 ) / delta;
}
else
{
hue = ( 2.0f / 3 ) + ( ( r - g ) / 6 ) / delta;
} }
// correct hue if needed //lightness
if ( hue < 0 ) l = ((max + min) / 2d) / 255d;
hue += 1;
if ( hue > 1 )
hue -= 1;
h = (int) ( hue * 360 ); //hue
} if (Math.abs(max - min) <= EPSILON) {
h = 0d;
s = 0d;
}
else {
double diff = max - min;
hsl[0] = h; if (Math.abs(max - r) <= EPSILON) {
hsl[1] = s; h = 60d * (g - b) / diff;
hsl[2] = l; }
else if (Math.abs(max - g) <= EPSILON) {
h = 60d * (b - r) / diff + 120d;
}
else {
h = 60d * (r - g) / diff + 240d;
}
if (h < 0d) {
h += 360d;
}
}
hsl[0] = h.floatValue();
hsl[1] = s.floatValue();
hsl[2] = l.floatValue();
return hsl; return hsl;
} }
@@ -931,10 +917,15 @@ public class ColorConverter {
*/ */
public static float[] XYtoXYZ(XYColorSpace xy){ public static float[] XYtoXYZ(XYColorSpace xy){
float[] xyz = new float[3]; float[] xyz = new float[3];
/* Old Way
xyz[0] = (xy.getBrightnessAdjusted() / xy.getXy()[1]) * xy.getXy()[0]; xyz[0] = (xy.getBrightnessAdjusted() / xy.getXy()[1]) * xy.getXy()[0];
xyz[1] = xy.getBrightnessAdjusted(); xyz[1] = xy.getBrightnessAdjusted();
xyz[2] = (xy.getBrightnessAdjusted() / xy.getXy()[1]) * (1.0f - xy.getXy()[0] - xy.getXy()[1]); xyz[2] = (xy.getBrightnessAdjusted() / xy.getXy()[1]) * (1.0f - xy.getXy()[0] - xy.getXy()[1]);
*/
// New Way
xyz[0] = xy.getXy()[0] * (xy.getBrightnessAdjusted() / xy.getXy()[1]) ;
xyz[1] = xy.getBrightnessAdjusted();
xyz[2] = (float) ((1.0 - xy.getXy()[0] - xy.getXy()[1]) * (xy.getBrightnessAdjusted() / xy.getXy()[1]));
return xyz; return xyz;
} }

View File

@@ -4,12 +4,12 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.awt.Color; // import java.awt.Color;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.hue.ColorData; // import com.bwssystems.HABridge.hue.ColorData;
public class ColorDecode { public class ColorDecode {
private static final Logger log = LoggerFactory.getLogger(ColorDecode.class); private static final Logger log = LoggerFactory.getLogger(ColorDecode.class);
@@ -27,73 +27,81 @@ public class ColorDecode {
private static final String COLOR_BRI = "${colorbri}"; private static final String COLOR_BRI = "${colorbri}";
private static final Pattern COLOR_MILIGHT = Pattern.compile("\\$\\{color.milight\\:([01234])\\}"); private static final Pattern COLOR_MILIGHT = Pattern.compile("\\$\\{color.milight\\:([01234])\\}");
public static List<Integer> convertHSBtoRGB(HueSatBri hsb) {
/* This is supersceded by the next iteration function below this original one
public static List<Integer> convertHSBtoRGBOrig(HueSatBri hsb) {
List<Integer> rgb; List<Integer> rgb;
Float hue = (Float)(hsb.getHue()*1.0f); Float hue = (Float)(hsb.getHue()*1.0f);
Float saturation = (Float)(hsb.getSat()*1.0f); Float saturation = (Float)(hsb.getSat()*1.0f);
Float brightness = (Float)(hsb.getBri()*1.0f); Float brightness = (Float)(hsb.getBri()*1.0f);
log.info("Hue = " + hue + ", Sat = " + saturation + ", Bri = " + brightness); log.info("Hue = " + hue + ", Sat = " + saturation + ", Bri = " + brightness);
//Convert Hue into degrees for HSB //Convert Hue into degrees for HSB
hue = hue / 182.04f; // hue = hue / 182.04f;
hue = (hue / 65535.0f) * 360.0f;
//Bri and Sat must be values from 0-1 (~percentage) //Bri and Sat must be values from 0-1 (~percentage)
brightness = brightness / 255.0f; // ightness = brightness / 255.0f;
saturation = saturation / 255.0f; // saturation = saturation / 255.0f;
brightness = brightness / 254.0f;
saturation = saturation / 254.0f;
Float r = 0f; Float r = 0f;
Float g = 0f; Float g = 0f;
Float b = 0f; Float b = 0f;
if (saturation == 0) if(brightness > 0.0f) {
{ if (saturation == 0)
r = g = b = brightness; {
} r = g = b = brightness;
else }
{ else
// the color wheel consists of 6 sectors. {
Float sectorPos = hue / 60.0f; // the color wheel consists of 6 sectors.
int sectorNumber = (int)(Math.floor(sectorPos)); Float sectorPos = hue / 60.0f;
// get the fractional part of the sector int sectorNumber = (int)(Math.floor(sectorPos));
Float fractionalSector = sectorPos - sectorNumber; // get the fractional part of the sector
Float fractionalSector = sectorPos - sectorNumber;
// calculate values for the three axes of the color. // calculate values for the three axes of the color.
Float p = brightness * (1.0f - saturation); Float p = brightness * (1.0f - saturation);
Float q = brightness * (1.0f - (saturation * fractionalSector)); Float q = brightness * (1.0f - (saturation * fractionalSector));
Float t = brightness * (1.0f - (saturation * (1f - fractionalSector))); Float t = brightness * (1.0f - (saturation * (1f - fractionalSector)));
// assign the fractional colors to r, g, and b based on the sector the angle is in. // assign the fractional colors to r, g, and b based on the sector the angle is in.
switch (sectorNumber) switch (sectorNumber)
{ {
case 0: case 0:
r = brightness; r = brightness;
g = t; g = t;
b = p; b = p;
break; break;
case 1: case 1:
r = q; r = q;
g = brightness; g = brightness;
b = p; b = p;
break; break;
case 2: case 2:
r = p; r = p;
g = brightness; g = brightness;
b = t; b = t;
break; break;
case 3: case 3:
r = p; r = p;
g = q; g = q;
b = brightness; b = brightness;
break; break;
case 4: case 4:
r = t; r = t;
g = p; g = p;
b = brightness; b = brightness;
break; break;
case 5: case 5:
r = brightness; r = brightness;
g = p; g = p;
b = q; b = q;
break; break;
} }
}
} }
//Check if any value is out of byte range //Check if any value is out of byte range
@@ -114,10 +122,106 @@ public class ColorDecode {
rgb.add((int)Math.round(r*255)); rgb.add((int)Math.round(r*255));
rgb.add((int)Math.round(g*255)); rgb.add((int)Math.round(g*255));
rgb.add((int)Math.round(b*255)); rgb.add((int)Math.round(b*255));
log.debug("Color change with HSB: " + hsb + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " log.info("Color change with HSB: " + hsb + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " "
+ rgb.get(2)); + rgb.get(2));
int theRGB = Color.HSBtoRGB(hue, saturation, brightness);
Color decodedRGB = new Color(theRGB);
log.info("Color change with HSB using java Color: " + hsb + ". Resulting RGB Values: " + decodedRGB.getRed() + " " + decodedRGB.getGreen() + " "
+ decodedRGB.getBlue());
return rgb; return rgb;
} }
*/
public static List<Integer> convertHSBtoRGB(HueSatBri hsb) {
List<Integer> rgb;
Float hue = (Float)(hsb.getHue()*1.0f);
Float saturation = (Float)(hsb.getSat()*1.0f);
Float brightness = (Float)(hsb.getBri()*1.0f);
log.info("Hue = " + hue + ", Sat = " + saturation + ", Bri = " + brightness);
//Convert Hue into degrees for HSB
// hue = hue / 182.04f;
hue = (hue / 65535.0f);
//Bri and Sat must be values from 0-1 (~percentage)
// ightness = brightness / 255.0f;
// saturation = saturation / 255.0f;
brightness = brightness / 254.0f;
saturation = saturation / 254.0f;
Float r = 0f;
Float g = 0f;
Float b = 0f;
Float temp2 = 0f;
Float temp1 = 0f;
if(brightness > 0.0f) {
if (saturation == 0)
{
r = g = b = brightness;
}
else
{
temp2 = (brightness < 0.5f) ? brightness * (1.0f + saturation) : brightness + saturation - (brightness * saturation);
temp1 = 2.0f * brightness - temp2;
r = GetColorComponent(temp1, temp2, hue + 1.0f/3.0f);
g = GetColorComponent(temp1, temp2, hue);
b = GetColorComponent(temp1, temp2, hue - 1.0f/3.0f);
}
}
//Check if any value is out of byte range
if (r < 0f)
{
r = 0f;
}
if (g < 0f)
{
g = 0f;
}
if (b < 0f)
{
b = 0f;
}
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 HSB New: " + hsb + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " "
+ rgb.get(2));
return rgb;
}
private static Float GetColorComponent(Float temp1, Float temp2, Float temp3)
{
temp3 = MoveIntoRange(temp3);
if (temp3 < 1.0f/6.0f)
{
return temp1 + (temp2 - temp1) * 6.0f * temp3;
}
if (temp3 < 0.5f)
{
return temp2;
}
if (temp3 < 2.0f/3.0f)
{
return temp1 + ((temp2 - temp1) * ((2.0f/3.0f) - temp3) * 6.0f);
}
return temp1;
}
private static Float MoveIntoRange(Float temp3)
{
if (temp3 < 0.0f) return temp3 + 1f;
if (temp3 > 1.0f) return temp3 - 1f;
return temp3;
}
public static List<Integer> convertCIEtoRGB(List<Double> xy, int brightness) { public static List<Integer> convertCIEtoRGB(List<Double> xy, int brightness) {
List<Integer> rgb; List<Integer> rgb;
@@ -133,7 +237,7 @@ public class ColorDecode {
rgb.add(rgbInt[0]); rgb.add(rgbInt[0]);
rgb.add(rgbInt[1]); rgb.add(rgbInt[1]);
rgb.add(rgbInt[2]); rgb.add(rgbInt[2]);
log.debug("Color change with XY: " + xy.get(0) + " " + xy.get(1) + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) log.debug("Color change with XY: " + xy.get(0) + " " + xy.get(1) + " " + brightness + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1)
+ " " + rgb.get(2)); + " " + rgb.get(2));
return rgb; return rgb;
} }
@@ -179,10 +283,10 @@ public class ColorDecode {
private static double assureBounds(double value) { private static double assureBounds(double value) {
if (value < 0.0) { if (value < 0.0) {
value = 0; value = 0.0;
} }
if (value > 255.0) { if (value > 255.0) {
value = 255; value = 255.0;
} }
return value; return value;
} }
@@ -252,8 +356,9 @@ public class ColorDecode {
List<Double> xyData = (List<Double>) colorData.getData(); List<Double> xyData = (List<Double>) colorData.getData();
request = request.replace(COLOR_XY, String.format("%f,%f", xyData.get(0), xyData.get(1))); request = request.replace(COLOR_XY, String.format("%f,%f", xyData.get(0), xyData.get(1)));
} else { } else {
List<Double> xyData = (List<Double>) colorData.getData(); float[] xyz = ColorConverter.RGBtoXYZ(rgb.get(0), rgb.get(1), rgb.get(2));
request = request.replace(COLOR_XY, String.format("%f,%f", xyData.get(0), xyData.get(1))); XYColorSpace theXYcolor = ColorConverter.XYZtoXY(xyz[0], xyz[1], xyz[2]);
request = request.replace(COLOR_XY, String.format("%f,%f",theXYcolor.getXy()[0], theXYcolor.getXy()[1]));
} }
notDone = true; notDone = true;
} }
@@ -263,9 +368,9 @@ public class ColorDecode {
HueSatBri hslData = (HueSatBri) colorData.getData(); HueSatBri hslData = (HueSatBri) colorData.getData();
request = request.replace(COLOR_H, String.format("%d", hslData.getHue())); request = request.replace(COLOR_H, String.format("%d", hslData.getHue()));
} else { } else {
float[] hsb = new float[3]; float[] hsb;
Color.RGBtoHSB(rgb.get(0), rgb.get(1), rgb.get(2), hsb); hsb = ColorConverter.RGBtoHSL(rgb.get(0), rgb.get(1), rgb.get(2));
float hue = hsb[0] * (float) 360.0; float hue = hsb[0];
request = request.replace(COLOR_H, String.format("%f", hue)); request = request.replace(COLOR_H, String.format("%f", hue));
} }
notDone = true; notDone = true;
@@ -276,8 +381,8 @@ public class ColorDecode {
HueSatBri hslData = (HueSatBri) colorData.getData(); HueSatBri hslData = (HueSatBri) colorData.getData();
request = request.replace(COLOR_S, String.format("%d", hslData.getSat())); request = request.replace(COLOR_S, String.format("%d", hslData.getSat()));
} else { } else {
float[] hsb = new float[3]; float[] hsb;
Color.RGBtoHSB(rgb.get(0), rgb.get(1), rgb.get(2), hsb); hsb = ColorConverter.RGBtoHSL(rgb.get(0), rgb.get(1), rgb.get(2));
float sat = hsb[1] * (float) 100.0; float sat = hsb[1] * (float) 100.0;
request = request.replace(COLOR_S, String.format("%f", sat)); request = request.replace(COLOR_S, String.format("%f", sat));
} }
@@ -289,7 +394,7 @@ public class ColorDecode {
HueSatBri hslData = (HueSatBri) colorData.getData(); HueSatBri hslData = (HueSatBri) colorData.getData();
request = request.replace(COLOR_BRI, String.format("%d", hslData.getBri())); request = request.replace(COLOR_BRI, String.format("%d", hslData.getBri()));
} else { } else {
request = request.replace(COLOR_BRI, String.format("%f", setIntensity)); request = request.replace(COLOR_BRI, String.format("%d", setIntensity));
} }
notDone = true; notDone = true;
} }
@@ -301,8 +406,8 @@ public class ColorDecode {
String.format("%d,%d,%d", hslData.getHue(), hslData.getSat(), hslData.getBri())); String.format("%d,%d,%d", hslData.getHue(), hslData.getSat(), hslData.getBri()));
} else { } else {
float[] hsb = new float[3]; float[] hsb = new float[3];
Color.RGBtoHSB(rgb.get(0), rgb.get(1), rgb.get(2), hsb); hsb = ColorConverter.RGBtoHSL(rgb.get(0), rgb.get(1), rgb.get(2));
float hue = hsb[0] * (float) 360.0; float hue = hsb[0];
float sat = hsb[1] * (float) 100.0; float sat = hsb[1] * (float) 100.0;
float bright = hsb[2] * (float) 100.0; float bright = hsb[2] * (float) 100.0;
request = request.replace(COLOR_HSB, String.format("%f,%f,%f", hue, sat, bright)); request = request.replace(COLOR_HSB, String.format("%f,%f,%f", hue, sat, bright));

View File

@@ -1221,12 +1221,44 @@ public class HueMulator {
isOnRequest = true; isOnRequest = true;
} }
if(device.isOnFirstDim()) {
if(isDimRequest && !device.getDeviceState().isOn()) {
isOnRequest = true;
theStateChanges.setOn(true);
// isDimRequest = false;
// isColorRequest = false;
} else if (isDimRequest && device.getDeviceState().isOn()) {
if (device.getDeviceState().getBri() == theStateChanges.getBri()) {
isOnRequest = true;
theStateChanges.setOn(true);
// isDimRequest = false;
// isColorRequest = false;
} else {
isOnRequest = false;
// isDimRequest = true;
// isColorRequest = false;
}
}
} else if (device.isOnWhenDimPresent()) {
if (isDimRequest) {
isOnRequest = true;
theStateChanges.setOn(true);
}
} else if (device.isDimNoOn()) {
if (isDimRequest && isOnRequest) {
isOnRequest = false;
}
}
if(isColorRequest && isDimRequest && !device.isDimOnColor()) {
isDimRequest = false;
}
/* Old code supperceded by the above block
if (!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest && !isOnRequest) { if (!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest && !isOnRequest) {
isOnRequest = true; isOnRequest = true;
theStateChanges.setOn(true); theStateChanges.setOn(true);
} else if (!device.isOnFirstDim() && !device.isOnWhenDimPresent() && isDimRequest) { } else
// isOnRequest = false;
}
if (device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) { if (device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) {
isOnRequest = true; isOnRequest = true;
@@ -1245,6 +1277,7 @@ public class HueMulator {
isColorRequest = false; isColorRequest = false;
} }
} }
*/
if (isOnRequest) { if (isOnRequest) {
if (bridgeSettings.isTracestate()) if (bridgeSettings.isTracestate())

View File

@@ -139,8 +139,7 @@ public class HassHome implements Home {
hassCommand = aGsonHandler.fromJson(anItem.getItem(), HassCommand.class); hassCommand = aGsonHandler.fromJson(anItem.getItem(), HassCommand.class);
else else
hassCommand = aGsonHandler.fromJson(anItem.getItem().getAsString().replaceAll("^\"|\"$", ""), HassCommand.class); hassCommand = aGsonHandler.fromJson(anItem.getItem().getAsString().replaceAll("^\"|\"$", ""), HassCommand.class);
hassCommand.setBri(BrightnessDecode.replaceIntensityValue(hassCommand.getBri(), hassCommand.setBri(BrightnessDecode.calculateReplaceIntensityValue(hassCommand.getBri(), intensity, targetBri, targetBriInc, false));
BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false));
HomeAssistant homeAssistant = getHomeAssistant(hassCommand.getHassName()); HomeAssistant homeAssistant = getHomeAssistant(hassCommand.getHassName());
if (homeAssistant == null) { if (homeAssistant == null) {
log.warn("Should not get here, no HomeAssistants available"); log.warn("Should not get here, no HomeAssistants available");

View File

@@ -479,7 +479,7 @@ app.service('bridgeService', function ($rootScope, $http, $base64, $location, ng
this.pushLinkButton = function () { this.pushLinkButton = function () {
return $http.put(this.state.systemsbase + "/presslinkbutton").then( return $http.put(this.state.systemsbase + "/presslinkbutton").then(
function (response) { function (response) {
self.displayTimer("Link your device", 30000); self.displayTimer("Link your device", self.state.settings.linkbuttontimeout * 1000);
}, },
function (error) { function (error) {
if (error.status === 401) if (error.status === 401)
@@ -1547,26 +1547,42 @@ app.service('bridgeService', function ($rootScope, $http, $base64, $location, ng
}; };
this.toXY = function (red, green, blue) { this.toXY = function (red, green, blue) {
//Gamma corrective var r = red / 255;
red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92); var g = green / 255;
green = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92); var b = blue / 255;
blue = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92);
//Apply wide gamut conversion D65 //R
var X = red * 0.664511 + green * 0.154324 + blue * 0.162028; if ( r > 0.04045)
var Y = red * 0.283881 + green * 0.668433 + blue * 0.047685; r = Math.pow(( ( r + 0.055 ) / 1.055 ), 2.4);
var Z = red * 0.000088 + green * 0.072310 + blue * 0.986039; else
r /= 12.92;
var fx = X / (X + Y + Z); //G
var fy = Y / (X + Y + Z); if ( g > 0.04045)
if (isNaN(fx)) { g = Math.pow(( ( g + 0.055 ) / 1.055 ), 2.4);
fx = 0.0; else
} g /= 12.92;
if (isNaN(fy)) {
fy = 0.0;
}
return [fx.toPrecision(4), fy.toPrecision(4)]; //B
if ( b > 0.04045)
b = Math.pow(( ( b + 0.055 ) / 1.055 ), 2.4);
else
b /= 12.92;
r *= 100;
g *= 100;
b *= 100;
var x = 0.412453 * r + 0.35758 * g + 0.180423 * b;
var y = 0.212671 * r + 0.71516 * g + 0.072169 * b;
var z = 0.019334 * r + 0.119193 * g + 0.950227 * b;
var newX = x / (x + y + z);
var newY = y / (x + y + z);
var interBright = (y / 100) * 254;
var newBright = Math.round(interBright);
return [newX.toPrecision(6), newY.toPrecision(6), newBright];
}; };
this.testUrl = function (device, type, value, valueType) { this.testUrl = function (device, type, value, valueType) {
@@ -1592,7 +1608,7 @@ app.service('bridgeService', function ($rootScope, $http, $base64, $location, ng
if (valueType === "color" && value) { if (valueType === "color" && value) {
if (addComma) if (addComma)
testBody = testBody + ","; testBody = testBody + ",";
testBody = testBody + "\"xy\": [" + value[0] + "," + value[1] + "]"; testBody = testBody + "\"xy\": [" + value[0] + "," + value[1] + "],\"bri\":" + value[2];
} }
testBody = testBody + "}"; testBody = testBody + "}";
if (testBody === "{}") { if (testBody === "{}") {

View File

@@ -114,6 +114,18 @@
ng-model="device.onFirstDim" ng-true-value=true ng-model="device.onFirstDim" ng-true-value=true
ng-false-value=false> {{device.onFirstDim}}</td> ng-false-value=false> {{device.onFirstDim}}</td>
</tr> </tr>
<tr>
<td><label>Dim only when On present (If dim is present and the on request is present, the on request will not be sent. This is overriden by the above settings.)</label></td>
<td><input type="checkbox"
ng-model="device.dimNoOn" ng-true-value=true
ng-false-value=false> {{device.dimNoOn}}</td>
</tr>
<tr>
<td><label>Send dim when color request present and dim present</label></td>
<td><input type="checkbox"
ng-model="device.dimOnColor" ng-true-value=true
ng-false-value=false> {{device.dimOnColor}}</td>
</tr>
<tr> <tr>
<td><label>Filter Address (comma separated list)</label></td> <td><label>Filter Address (comma separated list)</label></td>
<td><input type="text" class="form-control" id="device-requester-addr" <td><input type="text" class="form-control" id="device-requester-addr"

View File

@@ -844,6 +844,11 @@
<td><input id="bridge-settings-upnpsenddelay" class="form-control" type="number" <td><input id="bridge-settings-upnpsenddelay" class="form-control" type="number"
ng-model="bridge.settings.upnpsenddelay" min="100" max="15000"></td> ng-model="bridge.settings.upnpsenddelay" min="100" max="15000"></td>
</tr> </tr>
<tr>
<td>Link Button Timeout (seconds)</td>
<td><input id="bridge-settings-linkbuttontimeout" class="form-control" type="number"
ng-model="bridge.settings.linkbuttontimeout" min="30"></td>
</tr>
<tr> <tr>
<td>ID Seed (start numbering from this value)</td> <td>ID Seed (start numbering from this value)</td>
<td><input id="bridge-settings-seedid" class="form-control" type="number" <td><input id="bridge-settings-seedid" class="form-control" type="number"

View File

@@ -1,5 +1,6 @@
package com.bwssystems.color.test; package com.bwssystems.color.test;
import java.awt.Color;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -17,10 +18,10 @@ public class ConvertCIEColorTestCase {
@Test @Test
public void testColorConverterXYtoRGB() { public void testColorConverterXYtoRGB() {
ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(Double.parseDouble("0.671254"), Double.parseDouble("0.303273"))); ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(Double.parseDouble("0.20821628789344535"), Double.parseDouble("0.22503526273269103")));
XYColorSpace xyColor = new XYColorSpace(); XYColorSpace xyColor = new XYColorSpace();
xyColor.setBrightness(50); xyColor.setBrightness(56);
float[] xyFloat = new float[2]; float[] xyFloat = new float[2];
xyFloat[0] = xy.get(0).floatValue(); xyFloat[0] = xy.get(0).floatValue();
xyFloat[1] = xy.get(1).floatValue(); xyFloat[1] = xy.get(1).floatValue();
@@ -32,12 +33,29 @@ public class ConvertCIEColorTestCase {
rgbDecode.add(1, rgb[1]); rgbDecode.add(1, rgb[1]);
rgbDecode.add(2, rgb[2]); rgbDecode.add(2, rgb[2]);
List<Integer> assertDecode = new ArrayList<Integer>(); List<Integer> assertDecode = new ArrayList<Integer>();
assertDecode.add(0, 255); assertDecode.add(0, 60);
assertDecode.add(1, 0); assertDecode.add(1, 134);
assertDecode.add(2, 5); assertDecode.add(2, 196);
Assert.assertEquals(rgbDecode, assertDecode); Assert.assertEquals(rgbDecode, assertDecode);
} }
@Test
public void testColorConverterRGBtoXY() {
int red = 60;
int green = 134;
int blue = 196;
float[] xyz = ColorConverter.RGBtoXYZ(red, green, blue);
XYColorSpace theColorSpace = ColorConverter.XYZtoXY(xyz[0], xyz[1], xyz[2]);
List<Float> xyDecode = new ArrayList<Float>();
xyDecode.add(0, theColorSpace.getXy()[0]);
xyDecode.add(1, theColorSpace.getXy()[1]);
List<Float> assertDecode = new ArrayList<Float>();
assertDecode.add(0, 0.20821705f);
assertDecode.add(1, 0.22506176f);
Assert.assertEquals(xyDecode, assertDecode);
}
@Test @Test
public void testColorConversionXYtoRGB1() { public void testColorConversionXYtoRGB1() {
ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(Double.parseDouble("0.671254"), Double.parseDouble("0.303273"))); ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(Double.parseDouble("0.671254"), Double.parseDouble("0.303273")));
@@ -70,6 +88,22 @@ public class ConvertCIEColorTestCase {
Assert.assertEquals(rgbIntVal, 15270119); Assert.assertEquals(rgbIntVal, 15270119);
} }
@Test
public void testColorConversionXYtoRGB3() {
ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(Double.parseDouble("0.20821628789344535"), Double.parseDouble("0.22503526273269103")));
List<Integer> colorDecode = ColorDecode.convertCIEtoRGB(xy, 56);
List<Integer> assertDecode = new ArrayList<Integer>();
assertDecode.add(0, 60);
assertDecode.add(1, 134);
assertDecode.add(2, 196);
Assert.assertEquals(colorDecode, assertDecode);
// ColorData colorData = new ColorData(ColorData.ColorMode.XY, xy);
// int rgbIntVal = ColorDecode.getIntRGB(colorData, 56);
// Assert.assertEquals(rgbIntVal, 15270119);
}
@Test @Test
public void testColorConversionHSBtoRGB1() { public void testColorConversionHSBtoRGB1() {
HueSatBri hsb = new HueSatBri(); HueSatBri hsb = new HueSatBri();
@@ -79,12 +113,30 @@ public class ConvertCIEColorTestCase {
List<Integer> colorDecode = ColorDecode.convertHSBtoRGB(hsb); List<Integer> colorDecode = ColorDecode.convertHSBtoRGB(hsb);
List<Integer> assertDecode = new ArrayList<Integer>(); List<Integer> assertDecode = new ArrayList<Integer>();
assertDecode.add(0, 60); assertDecode.add(0, 61);
assertDecode.add(1, 97); assertDecode.add(1, 134);
assertDecode.add(2, 128); assertDecode.add(2, 196);
Assert.assertEquals(colorDecode, assertDecode); Assert.assertEquals(colorDecode, assertDecode);
} }
@Test
public void testColorConverterRGBtoHSB() {
int red = 61;
int green = 134;
int blue = 196;
float[] hsl = ColorConverter.RGBtoHSL(red, green, blue);
List<Integer> hsbDecode = new ArrayList<Integer>();
hsbDecode.add(0, (int) (hsl[0] / 360f * 65535f));
hsbDecode.add(1, (int) (hsl[1] * 254f));
hsbDecode.add(2, (int) (hsl[2] * 254f));
List<Integer> assertDecode = new ArrayList<Integer>();
assertDecode.add(0, 37783);
assertDecode.add(1, 135);
assertDecode.add(2, 127);
Assert.assertEquals(hsbDecode, assertDecode);
}
@Test @Test
public void testColorConversionCTtoRGB() { public void testColorConversionCTtoRGB() {
Integer ct = 500; Integer ct = 500;