Updating color handling

This commit is contained in:
BWS Systems
2019-05-21 16:44:38 -05:00
parent b6b9089ec4
commit 45e2b63f98
5 changed files with 370 additions and 263 deletions

View File

@@ -49,8 +49,6 @@ This bridge was built to help put the Internet of Things together.
## Build ## Build
To customize and build it yourself, build a new jar with maven: To customize and build it yourself, build a new jar with maven:
ATTENTION: This requires JDK 1.8 to build
``` ```
mvn install mvn install
``` ```
@@ -58,30 +56,23 @@ Otherwise, downloads are available at https://github.com/bwssytems/ha-bridge/rel
## Run ## Run
Then locate the jar and start the server with: Then locate the jar and start the server with:
ATTENTION: This requires JDK 1.8 to run
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.2.2.jar java -jar ha-bridge-5.3.0.jar
```
ATTENTION: If running Java9, you will need to add the xml bind module
```
java -jar --add-modules java.xml.bind ha-bridge-5.2.2.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.2.2.jar is in your /home/pi/ha-bridge directory. Create the directory and make sure that ha-bridge-5.3.0.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.2.2/ha-bridge-5.2.2.jar pi@raspberrypi:~/ha-bridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.3.0/ha-bridge-5.3.0.jar
``` ```
Create the ha-bridge.service unit file: Create the ha-bridge.service unit file:
@@ -100,7 +91,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.2.2.jar ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/ha-bridge/data/habridge.config /home/pi/ha-bridge/ha-bridge-5.3.0.jar
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

43
pom.xml
View File

@@ -1,20 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.bwssystems.HABridge</groupId> <groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId> <artifactId>ha-bridge</artifactId>
<version>5.2.2</version> <version>5.2.next_a</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>HA Bridge</name> <name>HA Bridge</name>
<description>Emulates a Philips Hue bridge to allow the Amazon Echo to hook up to other HA systems, i.e. Vera or Harmony Hub or Nest, using lightweight frameworks</description> <description>Emulates a Philips Hue bridge to allow the Amazon Echo to hook up to other HA systems, i.e. Vera or Harmony Hub or Nest, using lightweight frameworks</description>
<properties> <properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
@@ -157,10 +154,37 @@
</resource> </resource>
</resources> </resources>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M2</version>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.6</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version> <version>3.0.0-M3</version>
<configuration> <configuration>
<skipTests>true</skipTests> <skipTests>true</skipTests>
</configuration> </configuration>
@@ -168,7 +192,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version> <version>3.2.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -230,8 +254,7 @@
</filter> </filter>
</filters> </filters>
<transformers> <transformers>
<transformer <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.bwssystems.HABridge.HABridge</mainClass> <mainClass>com.bwssystems.HABridge.HABridge</mainClass>
</transformer> </transformer>
</transformers> </transformers>

View File

@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.DeviceMapTypes; import com.bwssystems.HABridge.DeviceMapTypes;
import com.bwssystems.HABridge.api.CallItem; import com.bwssystems.HABridge.api.CallItem;
import com.bwssystems.HABridge.api.hue.DeviceResponse; import com.bwssystems.HABridge.api.hue.DeviceResponse;
import com.bwssystems.HABridge.api.hue.DeviceState;
import com.bwssystems.HABridge.dao.DeviceDescriptor; import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.HABridge.plugins.hue.HueHome; import com.bwssystems.HABridge.plugins.hue.HueHome;
import com.bwssystems.HABridge.util.BackupHandler; import com.bwssystems.HABridge.util.BackupHandler;
@@ -67,7 +68,10 @@ public class DeviceRepository extends BackupHandler {
{ {
DeviceDescriptor list[] = gson.fromJson(jsonContent, DeviceDescriptor[].class); DeviceDescriptor list[] = gson.fromJson(jsonContent, DeviceDescriptor[].class);
for(int i = 0; i < list.length; i++) { 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]); put(list[i].getId(), list[i]);
if(Integer.decode(list[i].getId()) > nextId) { if(Integer.decode(list[i].getId()) > nextId) {
nextId = Integer.decode(list[i].getId()); nextId = Integer.decode(list[i].getId());

View File

@@ -6,7 +6,6 @@ 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;
@@ -24,6 +23,92 @@ public class ColorDecode {
private static final String COLOR_HSL = "${color.hsl}"; private static final String COLOR_HSL = "${color.hsl}";
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> 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) { public static List<Integer> convertCIEtoRGB(List<Double> xy, int brightness) {
List<Integer> rgb; List<Integer> rgb;
double x = xy.get(0); // the given x value double x = xy.get(0); // the given x value
@@ -42,21 +127,18 @@ public class ColorDecode {
g = g / r; g = g / r;
b = b / r; b = b / r;
r = 1.0; r = 1.0;
} } else if (g > b && g > r && g > 1.0) {
else if (g > b && g > r && g > 1.0) {
r = r / g; r = r / g;
b = b / g; b = b / g;
g = 1.0; g = 1.0;
} } else if (b > r && b > g && b > 1.0) {
else if (b > r && b > g && b > 1.0) {
r = r / b; r = r / b;
g = g / b; g = g / b;
b = 1.0; b = 1.0;
} }
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055; 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; 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; b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
@@ -68,16 +150,14 @@ public class ColorDecode {
b = b / r; b = b / r;
r = 1.0; r = 1.0;
} }
} } else if (g > b && g > r) {
else if (g > b && g > r) {
// green is biggest // green is biggest
if (g > 1.0) { if (g > 1.0) {
r = r / g; r = r / g;
b = b / g; b = b / g;
g = 1.0; g = 1.0;
} }
} } else if (b > r && b > g) {
else if (b > r && b > g) {
// blue is biggest // blue is biggest
if (b > 1.0) { if (b > 1.0) {
r = r / b; r = r / b;
@@ -96,11 +176,13 @@ 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 XY: " + x + " " + y + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2)); log.debug("Color change with XY: " + x + " " + y + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1)
+ " " + rgb.get(2));
return rgb; 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) { public static List<Integer> convertCTtoRGB(Integer ct) {
double temperature = 1000000.0 / (double) ct; double temperature = 1000000.0 / (double) ct;
temperature /= 100; temperature /= 100;
@@ -133,7 +215,8 @@ public class ColorDecode {
rgb.add((int) Math.round(r)); rgb.add((int) Math.round(r));
rgb.add((int) Math.round(g)); rgb.add((int) Math.round(g));
rgb.add((int) Math.round(b)); 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)); log.debug("Color change with CT: " + ct + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " "
+ rgb.get(2));
return rgb; return rgb;
} }
@@ -167,17 +250,20 @@ public class ColorDecode {
while (notDone) { while (notDone) {
notDone = false; notDone = false;
if (request.contains(COLOR_R)) { 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; notDone = true;
} }
if (request.contains(COLOR_G)) { 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; notDone = true;
} }
if (request.contains(COLOR_B)) { 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; notDone = true;
} }
@@ -197,7 +283,8 @@ public class ColorDecode {
} }
if (request.contains(COLOR_RGBX)) { 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; notDone = true;
} }
@@ -240,7 +327,8 @@ public class ColorDecode {
} else if (group == 4) { } else if (group == 4) {
retVal += "CB"; retVal += "CB";
} }
log.debug("Convert RGB to Milight. Result: WHITE. RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2)); log.debug("Convert RGB to Milight. Result: WHITE. RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " "
+ rgb.get(2));
return retVal + "0055"; return retVal + "0055";
} else { // normal color } else { // normal color
r /= (double) 0xFF; r /= (double) 0xFF;
@@ -263,7 +351,8 @@ public class ColorDecode {
h = Math.round(h * 60); h = Math.round(h * 60);
} }
int milight = (int) ((256 + 176 - Math.floor(h / 360.0 * 255.0)) % 256); 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)); 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"; return "40" + String.format("%02X", milight) + "55";
} }
} }

View File

@@ -600,8 +600,8 @@ public class HueMulator {
if((deviceState != null) && deviceState.isOn() && deviceState.getBri() <= 0) if((deviceState != null) && deviceState.isOn() && deviceState.getBri() <= 0)
deviceState.setBri(254); deviceState.setBri(254);
if((deviceState != null) && !deviceState.isOn() && (targetBri != null || targetBriInc != null)) // if((deviceState != null) && !deviceState.isOn() && (targetBri != null || targetBriInc != null))
deviceState.setOn(true); // deviceState.setOn(true);
responseString = responseString + "]"; responseString = responseString + "]";
@@ -1186,11 +1186,11 @@ public class HueMulator {
isOnRequest = true; isOnRequest = true;
} }
if(!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest) { 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 if(!device.isOnFirstDim() && !device.isOnWhenDimPresent() && isDimRequest) {
isOnRequest = false; // isOnRequest = false;
} }
if(device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) { if(device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) {