mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-19 00:20:26 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb7aabb780 | ||
|
|
969ed352f7 | ||
|
|
c98513c365 | ||
|
|
add9617a07 | ||
|
|
f9e9f16756 | ||
|
|
f15cc0d53a | ||
|
|
0f791c1e71 | ||
|
|
9887042f4d | ||
|
|
c840f2bc4d | ||
|
|
9a355b7906 | ||
|
|
9399af7ec7 | ||
|
|
be72f7e62c |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -12,6 +12,7 @@ data
|
|||||||
/.settings/
|
/.settings/
|
||||||
/start.bat
|
/start.bat
|
||||||
/.classpath
|
/.classpath
|
||||||
|
/.project
|
||||||
|
|
||||||
sftp-config\.json
|
sftp-config\.json
|
||||||
/bin/
|
/bin/
|
||||||
@@ -22,4 +23,5 @@ sftp-config\.json
|
|||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
.project
|
||||||
|
|||||||
23
.project
23
.project
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>ha-bridge</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
10
README.md
10
README.md
@@ -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.1RC1.jar
|
java -jar ha-bridge-5.3.1RC3.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.1RC1.jar is in your /home/pi/ha-bridge directory.
|
Create the directory and make sure that ha-bridge-5.3.1RC3.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.1RC1/ha-bridge-5.3.1RC1.jar
|
pi@raspberrypi:~/ha-bridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.3.1RC3/ha-bridge-5.3.1RC3.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.1RC1.jar
|
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/ha-bridge/data/habridge.config /home/pi/ha-bridge/ha-bridge-5.3.1RC3.jar
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
@@ -222,7 +222,7 @@ proxy.server = (
|
|||||||
```
|
```
|
||||||
### nginx Example
|
### nginx Example
|
||||||
```
|
```
|
||||||
location /api/ {
|
location /api {
|
||||||
proxy_pass http://127.0.0.1:8080/api;
|
proxy_pass http://127.0.0.1:8080/api;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
8
pom.xml
8
pom.xml
@@ -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.1RC1</version>
|
<version>5.3.1RC4-java11</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>HA Bridge</name>
|
<name>HA Bridge</name>
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.12</version>
|
<version>4.13.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<rules>
|
<rules>
|
||||||
<requireMavenVersion>
|
<requireMavenVersion>
|
||||||
<!-- Change this to Version 3.3 for Java 1.8 and Raspberry PI compilation -->
|
<!-- Change this to Version 3.3 for Java 1.8 and Raspberry PI compilation, Java 11 is 3.6 -->
|
||||||
<version>3.6</version>
|
<version>3.6</version>
|
||||||
</requireMavenVersion>
|
</requireMavenVersion>
|
||||||
</rules>
|
</rules>
|
||||||
@@ -184,7 +184,7 @@
|
|||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.8.1</version>
|
<version>3.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<!-- Comment this release line out for Java 1.8 and Raspberry PI compilation -->
|
<!-- Comment this release line out for Java 1.8 and Raspberry PI compilation -->
|
||||||
<release>11</release>
|
<release>11</release>
|
||||||
<!-- Uncomment the next two lines for Java 1.8 and Raspberry PI compilation -->
|
<!-- Uncomment the next two lines for Java 1.8 and Raspberry PI compilation -->
|
||||||
<!-- <source>1.8</source> -->
|
<!-- <source>1.8</source> -->
|
||||||
|
|||||||
@@ -250,10 +250,10 @@ public class BridgeSettings extends BackupHandler {
|
|||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
theBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettingsDescriptor.class);
|
theBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettingsDescriptor.class);
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Issue loading values from file: " + aPath.toUri().toString() + ", Gson convert failed.");
|
|
||||||
theBridgeSettings = new BridgeSettingsDescriptor();
|
|
||||||
theBridgeSettings.setConfigfile(aPath.toString());
|
theBridgeSettings.setConfigfile(aPath.toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Issue loading values from file: " + aPath.toUri().toString() + ", Gson convert failed. Using default settings.");
|
||||||
|
theBridgeSettings = new BridgeSettingsDescriptor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,9 @@ public class BridgeSettingsDescriptor {
|
|||||||
@SerializedName("haaddressessecured")
|
@SerializedName("haaddressessecured")
|
||||||
@Expose
|
@Expose
|
||||||
private boolean haaddressessecured;
|
private boolean haaddressessecured;
|
||||||
|
@SerializedName("upnpadvanced")
|
||||||
|
@Expose
|
||||||
|
private boolean upnpadvanced;
|
||||||
// @SerializedName("activeloggers")
|
// @SerializedName("activeloggers")
|
||||||
// @Expose
|
// @Expose
|
||||||
// private List<NameValue> activeloggers;
|
// private List<NameValue> activeloggers;
|
||||||
@@ -192,6 +195,8 @@ public class BridgeSettingsDescriptor {
|
|||||||
this.upnporiginal = false;
|
this.upnporiginal = false;
|
||||||
this.seedid = 100;
|
this.seedid = 100;
|
||||||
this.haaddressessecured = false;
|
this.haaddressessecured = false;
|
||||||
|
this.configfile = Configuration.CONFIG_FILE;
|
||||||
|
this.upnpadvanced = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUpnpConfigAddress() {
|
public String getUpnpConfigAddress() {
|
||||||
@@ -847,4 +852,12 @@ public class BridgeSettingsDescriptor {
|
|||||||
public void setHaaddressessecured(boolean haaddressessecured) {
|
public void setHaaddressessecured(boolean haaddressessecured) {
|
||||||
this.haaddressessecured = haaddressessecured;
|
this.haaddressessecured = haaddressessecured;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUpnpadvanced() {
|
||||||
|
return upnpadvanced;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpnpadvanced(boolean upnpadvanced) {
|
||||||
|
this.upnpadvanced = upnpadvanced;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class DeviceResponse {
|
|||||||
private String swversion;
|
private String swversion;
|
||||||
private String swconfigid;
|
private String swconfigid;
|
||||||
private String productid;
|
private String productid;
|
||||||
|
private String productname;
|
||||||
|
|
||||||
public DeviceState getState() {
|
public DeviceState getState() {
|
||||||
return state;
|
return state;
|
||||||
@@ -90,6 +91,14 @@ public class DeviceResponse {
|
|||||||
this.productid = productid;
|
this.productid = productid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getProductName() {
|
||||||
|
return productname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProductName(String productname) {
|
||||||
|
this.productname = productname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getLuminaireuniqueid() {
|
public String getLuminaireuniqueid() {
|
||||||
return luminaireuniqueid;
|
return luminaireuniqueid;
|
||||||
@@ -109,10 +118,11 @@ public class DeviceResponse {
|
|||||||
|
|
||||||
if (device.isColorDevice()) {
|
if (device.isColorDevice()) {
|
||||||
response.setType("Extended color light");
|
response.setType("Extended color light");
|
||||||
response.setModelid("LCT010");
|
response.setModelid("LCT015");
|
||||||
response.setSwversion("1.15.2_r19181");
|
response.setSwversion("1.46.13_r26312");
|
||||||
response.setSwconfigid("F921C859");
|
response.setSwconfigid("52E3234B");
|
||||||
response.setProductid("Philips-LCT010-1-A19ECLv4");
|
response.setProductid("Philips-LCT015-1-A19ECLv5");
|
||||||
|
response.setProductName("Hue color lamp");
|
||||||
} else {
|
} else {
|
||||||
response.setType("Dimmable light");
|
response.setType("Dimmable light");
|
||||||
response.setModelid("LWB007");
|
response.setModelid("LWB007");
|
||||||
@@ -129,13 +139,14 @@ public class DeviceResponse {
|
|||||||
response.setState(group.getAction());
|
response.setState(group.getAction());
|
||||||
|
|
||||||
response.setName(group.getName());
|
response.setName(group.getName());
|
||||||
response.setUniqueid("00:17:88:5E:D3:FF-" + String.format("%02X", Integer.parseInt(group.getId())));
|
response.setUniqueid("00:11:22:33:44:55:66:77-" + String.format("%02X", Integer.parseInt(group.getId())));
|
||||||
response.setManufacturername("Philips");
|
response.setManufacturername("Philips");
|
||||||
response.setType("Extended color light");
|
response.setType("Extended color light");
|
||||||
response.setModelid("LCT010");
|
response.setModelid("LCT015");
|
||||||
response.setSwversion("1.15.2_r19181");
|
response.setSwversion("1.46.13_r26312");
|
||||||
response.setSwconfigid("F921C859");
|
response.setSwconfigid("52E3234B");
|
||||||
response.setProductid("Philips-LCT010-1-A19ECLv4");
|
response.setProductid("Philips-LCT015-1-A19ECLv5");
|
||||||
|
response.setProductName("Hue color lamp");
|
||||||
|
|
||||||
response.setLuminaireuniqueid(null);
|
response.setLuminaireuniqueid(null);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.bwssystems.HABridge.api.hue;
|
|||||||
|
|
||||||
public class HueConstants {
|
public class HueConstants {
|
||||||
public final static String HUB_VERSION = "9999999999";
|
public final static String HUB_VERSION = "9999999999";
|
||||||
public final static String API_VERSION = "1.19.0";
|
public final static String API_VERSION = "1.17.0";
|
||||||
public final static String MODEL_ID = "BSB002";
|
public final static String MODEL_ID = "BSB002";
|
||||||
public final static String UUID_PREFIX = "2f402f80-da50-11e1-9b23-";
|
public final static String UUID_PREFIX = "2f402f80-da50-11e1-9b23-";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,10 @@ public class DeviceDescriptor{
|
|||||||
@SerializedName("startupActions")
|
@SerializedName("startupActions")
|
||||||
@Expose
|
@Expose
|
||||||
private String startupActions;
|
private String startupActions;
|
||||||
|
@SerializedName("dimNoOn")
|
||||||
|
@Expose
|
||||||
|
private boolean dimNoOn;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -355,4 +358,12 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -30,6 +30,8 @@ import com.google.gson.JsonSyntaxException;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is an in memory list to manage the configured devices and saves the list as a JSON string to a file for later
|
* This is an in memory list to manage the configured devices and saves the list as a JSON string to a file for later
|
||||||
@@ -188,7 +190,7 @@ public class DeviceRepository extends BackupHandler {
|
|||||||
nextId++;
|
nextId++;
|
||||||
}
|
}
|
||||||
if (descriptors[i].getUniqueid() == null || descriptors[i].getUniqueid().length() == 0) {
|
if (descriptors[i].getUniqueid() == null || descriptors[i].getUniqueid().length() == 0) {
|
||||||
descriptors[i].setUniqueid("00:17:88:5E:D3:" + hueUniqueId(Integer.valueOf(descriptors[i].getId())));
|
descriptors[i].setUniqueid(hueUniqueId(Integer.valueOf(descriptors[i].getId())));
|
||||||
}
|
}
|
||||||
put(descriptors[i].getId(), descriptors[i]);
|
put(descriptors[i].getId(), descriptors[i]);
|
||||||
theNames = theNames + " " + descriptors[i].getName() + ", ";
|
theNames = theNames + " " + descriptors[i].getName() + ", ";
|
||||||
@@ -206,11 +208,10 @@ public class DeviceRepository extends BackupHandler {
|
|||||||
DeviceDescriptor theDevice;
|
DeviceDescriptor theDevice;
|
||||||
boolean findNext = true;
|
boolean findNext = true;
|
||||||
|
|
||||||
|
|
||||||
nextId = seedId;
|
nextId = seedId;
|
||||||
while(deviceIterator.hasNext()) {
|
while (deviceIterator.hasNext()) {
|
||||||
theDevice = deviceIterator.next();
|
theDevice = deviceIterator.next();
|
||||||
if(theDevice.isLockDeviceId()) {
|
if (theDevice.isLockDeviceId()) {
|
||||||
lockedIds.add(theDevice.getId());
|
lockedIds.add(theDevice.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,15 +221,15 @@ public class DeviceRepository extends BackupHandler {
|
|||||||
theDevice = deviceIterator.next();
|
theDevice = deviceIterator.next();
|
||||||
if (!theDevice.isLockDeviceId()) {
|
if (!theDevice.isLockDeviceId()) {
|
||||||
findNext = true;
|
findNext = true;
|
||||||
while(findNext) {
|
while (findNext) {
|
||||||
if(lockedIds.contains(String.valueOf(nextId))) {
|
if (lockedIds.contains(String.valueOf(nextId))) {
|
||||||
nextId++;
|
nextId++;
|
||||||
} else {
|
} else {
|
||||||
findNext = false;
|
findNext = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
theDevice.setId(String.valueOf(nextId));
|
theDevice.setId(String.valueOf(nextId));
|
||||||
theDevice.setUniqueid("00:17:88:5E:D3:" + hueUniqueId(nextId));
|
theDevice.setUniqueid(hueUniqueId(nextId));
|
||||||
nextId++;
|
nextId++;
|
||||||
}
|
}
|
||||||
newdevices.put(theDevice.getId(), theDevice);
|
newdevices.put(theDevice.getId(), theDevice);
|
||||||
@@ -297,27 +298,51 @@ public class DeviceRepository extends BackupHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String hueUniqueId(Integer anId) {
|
private String hueUniqueId(Integer anId) {
|
||||||
String theUniqueId;
|
String theUniqueId = null;
|
||||||
Integer newValue;
|
Integer newValue;
|
||||||
String hexValueLeft;
|
String hexValueLeft;
|
||||||
String hexValueRight;
|
String hexValueRight;
|
||||||
|
|
||||||
newValue = anId % 256;
|
MessageDigest md = null;
|
||||||
if (newValue <= 0)
|
|
||||||
newValue = 1;
|
|
||||||
else if (newValue > 255)
|
|
||||||
newValue = 255;
|
|
||||||
hexValueLeft = HexLibrary.byteToHex(newValue.byteValue());
|
|
||||||
newValue = anId / 256;
|
|
||||||
newValue = newValue % 256;
|
|
||||||
if (newValue < 0)
|
|
||||||
newValue = 0;
|
|
||||||
else if (newValue > 255)
|
|
||||||
newValue = 255;
|
|
||||||
hexValueRight = HexLibrary.byteToHex(newValue.byteValue());
|
|
||||||
|
|
||||||
theUniqueId = String.format("%s-%s", hexValueLeft, hexValueRight).toUpperCase();
|
try {
|
||||||
|
md = MessageDigest.getInstance("MD5");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
log.warn("Cannot get MD5 utility to hash unique ids.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(md != null) {
|
||||||
|
md.update(anId.toString().getBytes());
|
||||||
|
byte[] digest = md.digest();
|
||||||
|
theUniqueId = String.format("%s:%s:%s:%s:%s:%s:%s-%s",
|
||||||
|
HexLibrary.encodeHexString(digest).substring(0, 2),
|
||||||
|
HexLibrary.encodeHexString(digest).substring(2, 4),
|
||||||
|
HexLibrary.encodeHexString(digest).substring(4, 6),
|
||||||
|
HexLibrary.encodeHexString(digest).substring(6, 8),
|
||||||
|
HexLibrary.encodeHexString(digest).substring(8, 10),
|
||||||
|
HexLibrary.encodeHexString(digest).substring(10, 12),
|
||||||
|
HexLibrary.encodeHexString(digest).substring(12, 14),
|
||||||
|
HexLibrary.encodeHexString(digest).substring(14, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(theUniqueId == null) {
|
||||||
|
newValue = anId % 256;
|
||||||
|
if (newValue <= 0)
|
||||||
|
newValue = 1;
|
||||||
|
else if (newValue > 255)
|
||||||
|
newValue = 255;
|
||||||
|
hexValueLeft = HexLibrary.byteToHex(newValue.byteValue());
|
||||||
|
newValue = anId / 256;
|
||||||
|
newValue = newValue % 256;
|
||||||
|
if (newValue < 0)
|
||||||
|
newValue = 0;
|
||||||
|
else if (newValue > 255)
|
||||||
|
newValue = 255;
|
||||||
|
hexValueRight = HexLibrary.byteToHex(newValue.byteValue());
|
||||||
|
|
||||||
|
theUniqueId = String.format("11:22:33:44:55:66:%s-%s", hexValueLeft, hexValueRight).toUpperCase();
|
||||||
|
}
|
||||||
return theUniqueId;
|
return theUniqueId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -630,69 +616,69 @@ public class ColorConverter {
|
|||||||
public static int[] HunterLABtoRGB(float l, float a, float b){
|
public static int[] HunterLABtoRGB(float l, float a, float b){
|
||||||
float[] xyz = HunterLABtoXYZ(l, a, b);
|
float[] xyz = HunterLABtoXYZ(l, a, b);
|
||||||
return XYZtoRGB(xyz[0], xyz[1], xyz[2]);
|
return XYZtoRGB(xyz[0], xyz[1], xyz[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
|
|
||||||
|
if (Math.abs(max - r) <= EPSILON) {
|
||||||
|
h = 60d * (g - b) / diff;
|
||||||
|
}
|
||||||
|
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;
|
hsl[0] = h.floatValue();
|
||||||
hsl[1] = s;
|
hsl[1] = s.floatValue();
|
||||||
hsl[2] = l;
|
hsl[2] = l.floatValue();
|
||||||
|
|
||||||
return hsl;
|
return hsl;
|
||||||
}
|
}
|
||||||
@@ -931,14 +917,19 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int[] normalizeRGB(int[] rgb) {
|
public static int[] normalizeRGB(int[] rgb) {
|
||||||
int[] newRGB = new int[3];
|
int[] newRGB = new int[3];
|
||||||
|
|
||||||
|
|||||||
@@ -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,75 +27,83 @@ 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
|
||||||
|
{
|
||||||
|
// the color wheel consists of 6 sectors.
|
||||||
|
Float sectorPos = hue / 60.0f;
|
||||||
|
int sectorNumber = (int)(Math.floor(sectorPos));
|
||||||
|
// get the fractional part of the sector
|
||||||
|
Float fractionalSector = sectorPos - sectorNumber;
|
||||||
|
|
||||||
|
// calculate values for the three axes of the color.
|
||||||
|
Float p = brightness * (1.0f - saturation);
|
||||||
|
Float q = brightness * (1.0f - (saturation * 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.
|
||||||
|
switch (sectorNumber)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
r = brightness;
|
||||||
|
g = t;
|
||||||
|
b = p;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r = q;
|
||||||
|
g = brightness;
|
||||||
|
b = p;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r = p;
|
||||||
|
g = brightness;
|
||||||
|
b = t;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r = p;
|
||||||
|
g = q;
|
||||||
|
b = brightness;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
r = t;
|
||||||
|
g = p;
|
||||||
|
b = brightness;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
r = brightness;
|
||||||
|
g = p;
|
||||||
|
b = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// the color wheel consists of 6 sectors.
|
|
||||||
Float sectorPos = hue / 60.0f;
|
|
||||||
int sectorNumber = (int)(Math.floor(sectorPos));
|
|
||||||
// get the fractional part of the sector
|
|
||||||
Float fractionalSector = sectorPos - sectorNumber;
|
|
||||||
|
|
||||||
// calculate values for the three axes of the color.
|
|
||||||
Float p = brightness * (1.0f - saturation);
|
|
||||||
Float q = brightness * (1.0f - (saturation * 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.
|
|
||||||
switch (sectorNumber)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
r = brightness;
|
|
||||||
g = t;
|
|
||||||
b = p;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
r = q;
|
|
||||||
g = brightness;
|
|
||||||
b = p;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
r = p;
|
|
||||||
g = brightness;
|
|
||||||
b = t;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
r = p;
|
|
||||||
g = q;
|
|
||||||
b = brightness;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
r = t;
|
|
||||||
g = p;
|
|
||||||
b = brightness;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
r = brightness;
|
|
||||||
g = p;
|
|
||||||
b = q;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if any value is out of byte range
|
//Check if any value is out of byte range
|
||||||
if (r < 0f)
|
if (r < 0f)
|
||||||
{
|
{
|
||||||
@@ -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));
|
||||||
|
|||||||
@@ -1221,12 +1221,41 @@ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 +1274,7 @@ public class HueMulator {
|
|||||||
isColorRequest = false;
|
isColorRequest = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (isOnRequest) {
|
if (isOnRequest) {
|
||||||
if (bridgeSettings.isTracestate())
|
if (bridgeSettings.isTracestate())
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class UpnpListener {
|
|||||||
private String upnpConfigIP;
|
private String upnpConfigIP;
|
||||||
// private boolean strict;
|
// private boolean strict;
|
||||||
private boolean upnpOriginal;
|
private boolean upnpOriginal;
|
||||||
|
private boolean upnpAdvanced;
|
||||||
private boolean traceupnp;
|
private boolean traceupnp;
|
||||||
private boolean useUpnpIface;
|
private boolean useUpnpIface;
|
||||||
private BridgeControlDescriptor bridgeControl;
|
private BridgeControlDescriptor bridgeControl;
|
||||||
@@ -38,31 +39,37 @@ public class UpnpListener {
|
|||||||
private String httpType;
|
private String httpType;
|
||||||
private HuePublicConfig aHueConfig;
|
private HuePublicConfig aHueConfig;
|
||||||
private Integer theUpnpSendDelay;
|
private Integer theUpnpSendDelay;
|
||||||
|
|
||||||
|
/* This is the minimum response needed, all others are for the advanced setting */
|
||||||
private String responseTemplate1 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
private String responseTemplate1 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
||||||
+ "EXT:\r\n" + "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/"
|
+ "EXT:\r\n" + "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/"
|
||||||
+ HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: upnp:rootdevice\r\n" + "USN: uuid:"
|
+ HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: urn:schemas-upnp-org:device:basic:1\r\n"
|
||||||
+ HueConstants.UUID_PREFIX + "%s::upnp:rootdevice\r\n\r\n";
|
+ "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
||||||
|
|
||||||
|
/* These next 2 templates are for the advanced upnp option */
|
||||||
private String responseTemplate2 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
private String responseTemplate2 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
||||||
+ "EXT:\r\n" + "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/"
|
+ "EXT:\r\n" + "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/"
|
||||||
+ HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: uuid:" + HueConstants.UUID_PREFIX
|
+ HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: uuid:" + HueConstants.UUID_PREFIX
|
||||||
+ "%s\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
+ "%s\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
||||||
private String responseTemplate3 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
private String responseTemplate3 = "HTTP/1.1 200 OK\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
||||||
+ "EXT:\r\n" + "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/"
|
+ "EXT:\r\n" + "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/"
|
||||||
+ HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: urn:schemas-upnp-org:device:basic:1\r\n"
|
+ HueConstants.API_VERSION + "\r\n" + "hue-bridgeid: %s\r\n" + "ST: upnp:rootdevice\r\n" + "USN: uuid:"
|
||||||
+ "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
+ HueConstants.UUID_PREFIX + "%s::upnp:rootdevice\r\n\r\n";
|
||||||
|
|
||||||
|
|
||||||
|
/* These notify templates are for the advanced upnp option */
|
||||||
private String notifyTemplate1 = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
private String notifyTemplate1 = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
||||||
+ "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/"
|
+ "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/"
|
||||||
+ HueConstants.API_VERSION + "\r\n" + "NTS: ssdp:alive\r\n" + "hue-bridgeid: %s\r\n" + "NT: uuid:"
|
+ HueConstants.API_VERSION + "\r\n" + "NTS: ssdp:alive\r\n" + "hue-bridgeid: %s\r\n" + "NT: uuid:"
|
||||||
+ HueConstants.UUID_PREFIX + "%s\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
+ HueConstants.UUID_PREFIX + "%s\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
||||||
|
|
||||||
private String notifyTemplate2 = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
private String notifyTemplate2 = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
||||||
+ "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/"
|
+ "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/"
|
||||||
+ HueConstants.API_VERSION + "\r\n" + "NTS: ssdp:alive\r\n" + "hue-bridgeid: %s\r\n"
|
+ HueConstants.API_VERSION + "\r\n" + "NTS: ssdp:alive\r\n" + "hue-bridgeid: %s\r\n"
|
||||||
+ "NT: upnp:rootdevice\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s::upnp:rootdevice\r\n\r\n";
|
+ "NT: upnp:rootdevice\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s::upnp:rootdevice\r\n\r\n";
|
||||||
|
|
||||||
private String notifyTemplate3 = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
private String notifyTemplate3 = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n"
|
||||||
+ "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/"
|
+ "LOCATION: %s://%s:%s/description.xml\r\n" + "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/"
|
||||||
+ HueConstants.API_VERSION + "\r\n" + "NTS: ssdp:alive\r\n" + "hue-bridgeid: %s\r\n"
|
+ HueConstants.API_VERSION + "\r\n" + "NTS: ssdp:alive\r\n" + "hue-bridgeid: %s\r\n"
|
||||||
+ "NT: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
+ "NT: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
||||||
|
|
||||||
@@ -75,6 +82,7 @@ public class UpnpListener {
|
|||||||
upnpConfigIP = theSettings.getBridgeSettingsDescriptor().getUpnpConfigAddress();
|
upnpConfigIP = theSettings.getBridgeSettingsDescriptor().getUpnpConfigAddress();
|
||||||
// strict = theSettings.isUpnpStrict();
|
// strict = theSettings.isUpnpStrict();
|
||||||
upnpOriginal = theSettings.getBridgeSettingsDescriptor().isUpnporiginal();
|
upnpOriginal = theSettings.getBridgeSettingsDescriptor().isUpnporiginal();
|
||||||
|
upnpAdvanced = theSettings.getBridgeSettingsDescriptor().isUpnpadvanced();
|
||||||
traceupnp = theSettings.getBridgeSettingsDescriptor().isTraceupnp();
|
traceupnp = theSettings.getBridgeSettingsDescriptor().isTraceupnp();
|
||||||
useUpnpIface = theSettings.getBridgeSettingsDescriptor().isUseupnpiface();
|
useUpnpIface = theSettings.getBridgeSettingsDescriptor().isUseupnpiface();
|
||||||
theUpnpSendDelay = theSettings.getBridgeSettingsDescriptor().getUpnpsenddelay();
|
theUpnpSendDelay = theSettings.getBridgeSettingsDescriptor().getUpnpsenddelay();
|
||||||
@@ -192,10 +200,13 @@ public class UpnpListener {
|
|||||||
log.info("UPNP Discovery Listener running and ready....");
|
log.info("UPNP Discovery Listener running and ready....");
|
||||||
boolean loopControl = true;
|
boolean loopControl = true;
|
||||||
boolean error = false;
|
boolean error = false;
|
||||||
try {
|
|
||||||
upnpMulticastSocket.setSoTimeout((int) Configuration.UPNP_NOTIFY_TIMEOUT);
|
if(upnpAdvanced) {
|
||||||
} catch (SocketException e1) {
|
try {
|
||||||
log.warn("Could not sent soTimeout on multi-cast socket");
|
upnpMulticastSocket.setSoTimeout((int) Configuration.UPNP_NOTIFY_TIMEOUT);
|
||||||
|
} catch (SocketException e1) {
|
||||||
|
log.warn("Could not sent soTimeout on multi-cast socket");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Instant current, previous;
|
// Instant current, previous;
|
||||||
// previous = Instant.now();
|
// previous = Instant.now();
|
||||||
@@ -326,37 +337,39 @@ public class UpnpListener {
|
|||||||
+ " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
+ " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
||||||
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||||
|
|
||||||
try {
|
if(upnpAdvanced) {
|
||||||
Thread.sleep(theUpnpSendDelay);
|
try {
|
||||||
} catch (InterruptedException e) {
|
Thread.sleep(theUpnpSendDelay);
|
||||||
// noop
|
} catch (InterruptedException e) {
|
||||||
}
|
// noop
|
||||||
discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS,
|
}
|
||||||
Configuration.UPNP_DISCOVERY_PORT, httpType, httpLocationAddress, httpServerPort, bridgeId,
|
discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS,
|
||||||
bridgeSNUUID, bridgeSNUUID);
|
Configuration.UPNP_DISCOVERY_PORT, httpType, httpLocationAddress, httpServerPort, bridgeId,
|
||||||
if (traceupnp) {
|
bridgeSNUUID, bridgeSNUUID);
|
||||||
log.info("Traceupnp: send upnp discovery template 2 with response address: " + httpLocationAddress + ":"
|
if (traceupnp) {
|
||||||
+ httpServerPort + " to address: " + requester.getHostAddress() + ":" + sourcePort);
|
log.info("Traceupnp: send upnp discovery template 2 with response address: " + httpLocationAddress + ":"
|
||||||
}
|
+ httpServerPort + " to address: " + requester.getHostAddress() + ":" + sourcePort);
|
||||||
log.debug("sendUpnpResponse to address: " + requester.getHostAddress() + ":" + sourcePort
|
}
|
||||||
+ " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
|
log.debug("sendUpnpResponse to address: " + requester.getHostAddress() + ":" + sourcePort
|
||||||
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
+ " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
|
||||||
|
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(theUpnpSendDelay);
|
Thread.sleep(theUpnpSendDelay);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// noop
|
// noop
|
||||||
|
}
|
||||||
|
discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS,
|
||||||
|
Configuration.UPNP_DISCOVERY_PORT, httpType, httpLocationAddress, httpServerPort, bridgeId,
|
||||||
|
bridgeSNUUID);
|
||||||
|
if (traceupnp) {
|
||||||
|
log.info("Traceupnp: send upnp discovery template 3 with response address: " + httpLocationAddress + ":"
|
||||||
|
+ httpServerPort + " to address: " + requester.getHostAddress() + ":" + sourcePort);
|
||||||
|
}
|
||||||
|
log.debug("sendUpnpResponse to address: " + requester.getHostAddress() + ":" + sourcePort
|
||||||
|
+ " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
||||||
|
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||||
}
|
}
|
||||||
discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS,
|
|
||||||
Configuration.UPNP_DISCOVERY_PORT, httpType, httpLocationAddress, httpServerPort, bridgeId,
|
|
||||||
bridgeSNUUID);
|
|
||||||
if (traceupnp) {
|
|
||||||
log.info("Traceupnp: send upnp discovery template 3 with response address: " + httpLocationAddress + ":"
|
|
||||||
+ httpServerPort + " to address: " + requester.getHostAddress() + ":" + sourcePort);
|
|
||||||
}
|
|
||||||
log.debug("sendUpnpResponse to address: " + requester.getHostAddress() + ":" + sourcePort
|
|
||||||
+ " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
|
||||||
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendUDPResponse(byte[] udpMessage, InetAddress requester, int sourcePort) throws IOException {
|
private void sendUDPResponse(byte[] udpMessage, InetAddress requester, int sourcePort) throws IOException {
|
||||||
|
|||||||
@@ -55,10 +55,12 @@ public class UpnpSettingsResource {
|
|||||||
+ "<depth>24</depth>\n"
|
+ "<depth>24</depth>\n"
|
||||||
+ "<url>hue_logo_3.png</url>\n"
|
+ "<url>hue_logo_3.png</url>\n"
|
||||||
+ "</icon>\n"
|
+ "</icon>\n"
|
||||||
+ "</iconList>\n"
|
+ "</iconList>\n";
|
||||||
+ "</device>\n"
|
|
||||||
+ "</root>\n";
|
|
||||||
|
|
||||||
|
private String hueTemplate_end = "</device>\n"
|
||||||
|
+ "</root>\n";
|
||||||
|
|
||||||
|
/* not utilizing this section any more
|
||||||
private String hueTemplate_mid_orig = "<serviceList>\n"
|
private String hueTemplate_mid_orig = "<serviceList>\n"
|
||||||
+ "<service>\n"
|
+ "<service>\n"
|
||||||
+ "<serviceType>(null)</serviceType>\n"
|
+ "<serviceType>(null)</serviceType>\n"
|
||||||
@@ -68,7 +70,7 @@ public class UpnpSettingsResource {
|
|||||||
+ "<SCPDURL>(null)</SCPDURL>\n"
|
+ "<SCPDURL>(null)</SCPDURL>\n"
|
||||||
+ "</service>\n"
|
+ "</service>\n"
|
||||||
+ "</serviceList>\n";
|
+ "</serviceList>\n";
|
||||||
|
*/
|
||||||
|
|
||||||
public UpnpSettingsResource(BridgeSettings theBridgeSettings) {
|
public UpnpSettingsResource(BridgeSettings theBridgeSettings) {
|
||||||
super();
|
super();
|
||||||
@@ -92,16 +94,24 @@ public class UpnpSettingsResource {
|
|||||||
String hueTemplate = null;
|
String hueTemplate = null;
|
||||||
if(theSettings.isUpnporiginal()) {
|
if(theSettings.isUpnporiginal()) {
|
||||||
httpLocationAddr = theSettings.getUpnpConfigAddress();
|
httpLocationAddr = theSettings.getUpnpConfigAddress();
|
||||||
hueTemplate = hueTemplate_pre + hueTemplate_mid_orig + hueTemplate_post;
|
hueTemplate = hueTemplate_pre + hueTemplate_end;
|
||||||
} else {
|
} else if(!theSettings.isUpnpadvanced()) {
|
||||||
|
|
||||||
if(theSettings.isUseupnpiface()) {
|
if(theSettings.isUseupnpiface()) {
|
||||||
httpLocationAddr = theSettings.getUpnpConfigAddress();
|
httpLocationAddr = theSettings.getUpnpConfigAddress();
|
||||||
} else {
|
} else {
|
||||||
log.debug("Get Outbound address for ip:" + request.ip() + " and port:" + request.port());
|
log.debug("Get Outbound address for ip:" + request.ip() + " and port:" + request.port());
|
||||||
httpLocationAddr = AddressUtil.getOutboundAddress(request.ip(), request.port()).getHostAddress();
|
httpLocationAddr = AddressUtil.getOutboundAddress(request.ip(), request.port()).getHostAddress();
|
||||||
}
|
}
|
||||||
hueTemplate = hueTemplate_pre + hueTemplate_post;
|
hueTemplate = hueTemplate_pre + hueTemplate_end;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if(theSettings.isUseupnpiface()) {
|
||||||
|
httpLocationAddr = theSettings.getUpnpConfigAddress();
|
||||||
|
} else {
|
||||||
|
log.debug("Get Outbound address for ip:" + request.ip() + " and port:" + request.port());
|
||||||
|
httpLocationAddr = AddressUtil.getOutboundAddress(request.ip(), request.port()).getHostAddress();
|
||||||
|
}
|
||||||
|
hueTemplate = hueTemplate_pre + hueTemplate_post + hueTemplate_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
String bridgeIdMac = HuePublicConfig.createConfig("temp", httpLocationAddr, HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac();
|
String bridgeIdMac = HuePublicConfig.createConfig("temp", httpLocationAddr, HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac();
|
||||||
|
|||||||
@@ -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);
|
|
||||||
|
//R
|
||||||
|
if ( r > 0.04045)
|
||||||
|
r = Math.pow(( ( r + 0.055 ) / 1.055 ), 2.4);
|
||||||
|
else
|
||||||
|
r /= 12.92;
|
||||||
|
|
||||||
|
//G
|
||||||
|
if ( g > 0.04045)
|
||||||
|
g = Math.pow(( ( g + 0.055 ) / 1.055 ), 2.4);
|
||||||
|
else
|
||||||
|
g /= 12.92;
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
//Apply wide gamut conversion D65
|
return [newX.toPrecision(6), newY.toPrecision(6), newBright];
|
||||||
var X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
|
|
||||||
var Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
|
|
||||||
var Z = red * 0.000088 + green * 0.072310 + blue * 0.986039;
|
|
||||||
|
|
||||||
var fx = X / (X + Y + Z);
|
|
||||||
var fy = Y / (X + Y + Z);
|
|
||||||
if (isNaN(fx)) {
|
|
||||||
fx = 0.0;
|
|
||||||
}
|
|
||||||
if (isNaN(fy)) {
|
|
||||||
fy = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [fx.toPrecision(4), fy.toPrecision(4)];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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 === "{}") {
|
||||||
|
|||||||
@@ -114,6 +114,12 @@
|
|||||||
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>
|
<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"
|
||||||
|
|||||||
@@ -824,6 +824,11 @@
|
|||||||
<td><input type="checkbox" ng-model="bridge.settings.upnporiginal" ng-true-value=true
|
<td><input type="checkbox" ng-model="bridge.settings.upnporiginal" ng-true-value=true
|
||||||
ng-false-value=false> {{bridge.settings.upnporiginal}}</td>
|
ng-false-value=false> {{bridge.settings.upnporiginal}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>UPNP Advanced (use multiple responses and notifies)</td>
|
||||||
|
<td><input type="checkbox" ng-model="bridge.settings.upnpadvanced" ng-true-value=true
|
||||||
|
ng-false-value=false> {{bridge.settings.upnpadvanced}}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Trace UPNP Calls</td>
|
<td>Trace UPNP Calls</td>
|
||||||
<td><input type="checkbox" ng-model="bridge.settings.traceupnp" ng-true-value=true
|
<td><input type="checkbox" ng-model="bridge.settings.traceupnp" ng-true-value=true
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user