From 79d5b5da286768a5874b83b1ee2e58aaa994aa19 Mon Sep 17 00:00:00 2001 From: BWS Systems Date: Wed, 22 May 2019 15:30:50 -0500 Subject: [PATCH] Fixed color handling, starter Mozilla IOT integration --- .../bwssystems/HABridge/BridgeSettings.java | 1 + .../HABridge/BridgeSettingsDescriptor.java | 282 +++++-- .../bwssystems/HABridge/hue/ColorData.java | 6 + .../bwssystems/HABridge/hue/ColorDecode.java | 65 +- .../bwssystems/HABridge/hue/HueMulator.java | 727 +++++++++++------- .../bwssystems/HABridge/hue/HueSatBri.java | 38 + src/main/resources/public/views/system.html | 74 ++ 7 files changed, 828 insertions(+), 365 deletions(-) create mode 100644 src/main/java/com/bwssystems/HABridge/hue/HueSatBri.java diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java index 1b03df7..40396c5 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java @@ -216,6 +216,7 @@ public class BridgeSettings extends BackupHandler { theBridgeSettings.setHomeWizardConfigured(theBridgeSettings.isValidHomeWizard()); theBridgeSettings.setOpenhabconfigured(theBridgeSettings.isValidOpenhab()); theBridgeSettings.setFhemconfigured(theBridgeSettings.isValidFhem()); + theBridgeSettings.setMoziotconfigured(theBridgeSettings.isValidMozIot()); // Lifx is either configured or not, so it does not need an update. if(serverPortOverride != null) theBridgeSettings.setServerPort(serverPortOverride); diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java index 57f6ac9..a72edb7 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java @@ -90,6 +90,9 @@ public class BridgeSettingsDescriptor { @SerializedName("openhabaddress") @Expose private IpList openhabaddress; + @SerializedName("moziotgateway") + @Expose + private IpList moziotgateway; @SerializedName("hubversion") @Expose private String hubversion; @@ -114,10 +117,13 @@ public class BridgeSettingsDescriptor { @SerializedName("broadlinkconfigured") @Expose private boolean broadlinkconfigured; -// @SerializedName("activeloggers") -// @Expose -// private List activeloggers; - + @SerializedName("tracestate") + @Expose + private boolean tracestate; + // @SerializedName("activeloggers") + // @Expose + // private List activeloggers; + private boolean settingsChanged; private boolean veraconfigured; private boolean fibaroconfigured; @@ -132,11 +138,12 @@ public class BridgeSettingsDescriptor { private boolean homewizardconfigured; private boolean openhabconfigured; private boolean fhemconfigured; - + private boolean moziotconfigured; + // Deprecated settings private String haltoken; private boolean upnpstrict; - + public BridgeSettingsDescriptor() { super(); this.upnpstrict = true; @@ -156,6 +163,7 @@ public class BridgeSettingsDescriptor { this.homewizardconfigured = false; this.lifxconfigured = false; this.openhabconfigured = false; + this.moziotconfigured = false; this.farenheit = true; this.securityData = null; this.settingsChanged = false; @@ -163,456 +171,612 @@ public class BridgeSettingsDescriptor { this.webaddress = "0.0.0.0"; this.hubversion = HueConstants.HUB_VERSION; this.hubmac = null; -// this.activeloggers = null; + // this.activeloggers = null; this.upnpsenddelay = Configuration.UPNP_SEND_DELAY; this.broadlinkconfigured = false; + this.tracestate = false; } + public String getUpnpConfigAddress() { return upnpconfigaddress; } + public void setUpnpConfigAddress(String upnpConfigAddress) { this.upnpconfigaddress = upnpConfigAddress; } + public boolean isUseupnpiface() { return useupnpiface; } + public void setUseupnpiface(boolean useupnpiface) { this.useupnpiface = useupnpiface; } + public boolean isUserooms() { return userooms; } + public void setUserooms(boolean userooms) { this.userooms = userooms; } - public Integer getServerPort() { + + public Integer getServerPort() { return serverport; } + public void setServerPort(Integer serverPort) { this.serverport = serverPort; } + public void setServerPort(String serverPort) { this.serverport = Integer.valueOf(serverPort); } + public Integer getUpnpResponsePort() { return upnpresponseport; } + public void setUpnpResponsePort(Integer upnpResponsePort) { this.upnpresponseport = upnpResponsePort; } + public void setUpnpResponsePort(String upnpResponsePort) { this.upnpresponseport = Integer.valueOf(upnpResponsePort); } + public String getUpnpDeviceDb() { return upnpdevicedb; } + public void setUpnpDeviceDb(String upnpDeviceDb) { this.upnpdevicedb = upnpDeviceDb; } + public String getUpnpGroupDb() { return upnpgroupdb; } + public void setUpnpGroupDb(String upnpGroupDb) { this.upnpgroupdb = upnpGroupDb; } + public IpList getVeraAddress() { return veraaddress; } + public IpList getFibaroAddress() { return fibaroaddress; } + public IpList getSomfyAddress() { return somfyaddress; } + public IpList getHomeWizardAddress() { return homewizardaddress; - } + } + public void setVeraAddress(IpList veraAddress) { this.veraaddress = veraAddress; } + public void setFibaroAddress(IpList fibaroAddress) { this.fibaroaddress = fibaroAddress; } + public void setSomfyAddress(IpList somfyAddress) { this.somfyaddress = somfyAddress; } + public void setHomeWizardAddress(IpList homewizardaddress) { this.homewizardaddress = homewizardaddress; } + public IpList getHarmonyAddress() { return harmonyaddress; } + public void setHarmonyAddress(IpList harmonyaddress) { this.harmonyaddress = harmonyaddress; } + public boolean isUpnpStrict() { return upnpstrict; } + public void setUpnpStrict(boolean upnpStrict) { this.upnpstrict = upnpStrict; } + public boolean isTraceupnp() { return traceupnp; } + public void setTraceupnp(boolean traceupnp) { this.traceupnp = traceupnp; } + public String getNestuser() { return nestuser; } + public void setNestuser(String nestuser) { this.nestuser = nestuser; } + public String getNestpwd() { return nestpwd; } + public void setNestpwd(String nestpwd) { this.nestpwd = nestpwd; } + public boolean isVeraconfigured() { return veraconfigured; } + public boolean isFibaroconfigured() { return fibaroconfigured; } + public boolean isSomfyconfigured() { return somfyconfigured; } + public boolean isHomeWizardConfigured() { return homewizardconfigured; - } + } + public void setVeraconfigured(boolean veraconfigured) { this.veraconfigured = veraconfigured; } + public void setFibaroconfigured(boolean fibaroconfigured) { this.fibaroconfigured = fibaroconfigured; } + public void setSomfyconfigured(boolean somfyconfigured) { this.somfyconfigured = somfyconfigured; } + public void setHomeWizardConfigured(boolean homewizardconfigured) { this.homewizardconfigured = homewizardconfigured; } + public boolean isHarmonyconfigured() { return harmonyconfigured; } + public void setHarmonyconfigured(boolean harmonyconfigured) { this.harmonyconfigured = harmonyconfigured; } + public boolean isNestConfigured() { return nestconfigured; } + public void setNestConfigured(boolean isNestConfigured) { this.nestconfigured = isNestConfigured; } + public Integer getButtonsleep() { return buttonsleep; } + public void setButtonsleep(Integer buttonsleep) { this.buttonsleep = buttonsleep; } + public String getConfigfile() { return configfile; } + public void setConfigfile(String configfile) { this.configfile = configfile; } + public Integer getNumberoflogmessages() { return numberoflogmessages; } + public void setNumberoflogmessages(Integer numberoflogmessages) { this.numberoflogmessages = numberoflogmessages; } + public boolean isFarenheit() { return farenheit; } + public void setFarenheit(boolean farenheit) { this.farenheit = farenheit; } + public IpList getHueaddress() { return hueaddress; } + public void setHueaddress(IpList hueaddress) { this.hueaddress = hueaddress; } + public boolean isHueconfigured() { return hueconfigured; } + public void setHueconfigured(boolean hueconfigured) { this.hueconfigured = hueconfigured; } + public IpList getHaladdress() { return haladdress; } + public void setHaladdress(IpList haladdress) { this.haladdress = haladdress; } + public String getHaltoken() { return haltoken; } + public void setHaltoken(String haltoken) { this.haltoken = haltoken; } + public boolean isHalconfigured() { return halconfigured; } + public void setHalconfigured(boolean halconfigured) { this.halconfigured = halconfigured; } + public Map getWhitelist() { return whitelist; } + protected void removeWhitelist() { whitelist = null; } + public boolean isSettingsChanged() { return settingsChanged; } + public void setSettingsChanged(boolean settingsChanged) { this.settingsChanged = settingsChanged; } + public String getMyechourl() { return myechourl; } + public void setMyechourl(String myechourl) { this.myechourl = myechourl; } + public String getWebaddress() { return webaddress; } + public void setWebaddress(String webaddress) { this.webaddress = webaddress; } + public IpList getMqttaddress() { return mqttaddress; } + public void setMqttaddress(IpList mqttaddress) { this.mqttaddress = mqttaddress; } + public boolean isMqttconfigured() { return mqttconfigured; } + public void setMqttconfigured(boolean mqttconfigured) { this.mqttconfigured = mqttconfigured; } + public IpList getHassaddress() { return hassaddress; } + public void setHassaddress(IpList hassaddress) { this.hassaddress = hassaddress; } + public boolean isHassconfigured() { return hassconfigured; } + public void setHassconfigured(boolean hassconfigured) { this.hassconfigured = hassconfigured; } + public IpList getOpenhabaddress() { return openhabaddress; } + public void setOpenhabaddress(IpList openhabaddress) { this.openhabaddress = openhabaddress; } + public boolean isOpenhabconfigured() { return openhabconfigured; } + public void setOpenhabconfigured(boolean openhabconfigured) { this.openhabconfigured = openhabconfigured; } + public String getHubversion() { return hubversion; } + public void setHubversion(String hubversion) { this.hubversion = hubversion; } + public String getHubmac() { return hubmac; } + public void setHubmac(String hubmac) { this.hubmac = hubmac; } + public IpList getDomoticzaddress() { return domoticzaddress; } + public void setDomoticzaddress(IpList domoticzaddress) { this.domoticzaddress = domoticzaddress; } + public boolean isDomoticzconfigured() { return domoticzconfigured; } + public void setDomoticzconfigured(boolean domoticzconfigured) { this.domoticzconfigured = domoticzconfigured; } + public boolean isLifxconfigured() { return lifxconfigured; } + public void setLifxconfigured(boolean lifxconfigured) { this.lifxconfigured = lifxconfigured; } + public String getSecurityData() { return securityData; } + public void setSecurityData(String securityData) { this.securityData = securityData; } + public Integer getUpnpsenddelay() { return upnpsenddelay; } + public void setUpnpsenddelay(Integer upnpsenddelay) { this.upnpsenddelay = upnpsenddelay; } + public IpList getFhemaddress() { return fhemaddress; } + public void setFhemaddress(IpList fhemaddress) { this.fhemaddress = fhemaddress; } + public boolean isFhemconfigured() { return fhemconfigured; } + public void setFhemconfigured(boolean fhemconfigured) { this.fhemconfigured = fhemconfigured; } -// public List getActiveloggers() { -// return activeloggers; -// } -// public void setActiveloggers(List activeloggers) { -// this.activeloggers = activeloggers; -// } + + // public List getActiveloggers() { + // return activeloggers; + // } + // public void setActiveloggers(List activeloggers) { + // this.activeloggers = activeloggers; + // } public boolean isBroadlinkconfigured() { return broadlinkconfigured; } + public void setBroadlinkconfigured(boolean broadlinkconfigured) { this.broadlinkconfigured = broadlinkconfigured; } + public Boolean isValidVera() { - if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0) + if (this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0) return false; List devicesList = this.getVeraAddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidFibaro() { - if(this.getFibaroAddress() == null || this.getFibaroAddress().getDevices().size() <= 0) + if (this.getFibaroAddress() == null || this.getFibaroAddress().getDevices().size() <= 0) return false; List devicesList = this.getFibaroAddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidHarmony() { - if(this.getHarmonyAddress() == null || this.getHarmonyAddress().getDevices().size() <= 0) - return false; + if (this.getHarmonyAddress() == null || this.getHarmonyAddress().getDevices().size() <= 0) + return false; List devicesList = this.getHarmonyAddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidNest() { - if(this.getNestpwd() == null || this.getNestpwd().equals("")) + if (this.getNestpwd() == null || this.getNestpwd().equals("")) return false; - if(this.getNestuser() == null || this.getNestuser().equals("")) + if (this.getNestuser() == null || this.getNestuser().equals("")) return false; return true; } + public Boolean isValidHue() { - if(this.getHueaddress() == null || this.getHueaddress().getDevices().size() <= 0) + if (this.getHueaddress() == null || this.getHueaddress().getDevices().size() <= 0) return false; List devicesList = this.getHueaddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidHal() { - if(this.getHaladdress() == null || this.getHaladdress().getDevices().size() <= 0) - return false; - List devicesList = this.getHaladdress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (this.getHaladdress() == null || this.getHaladdress().getDevices().size() <= 0) return false; - if(devicesList.get(0).getPassword() == null || devicesList.get(0).getPassword().trim().isEmpty()) { - if(this.getHaltoken() == null || this.getHaltoken().equals("")) + List devicesList = this.getHaladdress().getDevices(); + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + return false; + if (devicesList.get(0).getPassword() == null || devicesList.get(0).getPassword().trim().isEmpty()) { + if (this.getHaltoken() == null || this.getHaltoken().equals("")) return false; } return true; } + public Boolean isValidMQTT() { - if(this.getMqttaddress() == null || this.getMqttaddress().getDevices().size() <= 0) - return false; + if (this.getMqttaddress() == null || this.getMqttaddress().getDevices().size() <= 0) + return false; List devicesList = this.getMqttaddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidHass() { - if(this.getHassaddress() == null || this.getHassaddress().getDevices().size() <= 0) - return false; + if (this.getHassaddress() == null || this.getHassaddress().getDevices().size() <= 0) + return false; List devicesList = this.getHassaddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidDomoticz() { - if(this.getDomoticzaddress() == null || this.getDomoticzaddress().getDevices().size() <= 0) - return false; + if (this.getDomoticzaddress() == null || this.getDomoticzaddress().getDevices().size() <= 0) + return false; List devicesList = this.getDomoticzaddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidSomfy() { - if(this.getSomfyAddress() == null || this.getSomfyAddress().getDevices().size() <= 0) + if (this.getSomfyAddress() == null || this.getSomfyAddress().getDevices().size() <= 0) return false; List devicesList = this.getSomfyAddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; return true; } + public Boolean isValidLifx() { return this.isLifxconfigured(); } + public void updateHue(NamedIP aHue) { int indexHue = -1; - for( int i = 0; i < hueaddress.getDevices().size(); i++) { - if(hueaddress.getDevices().get(i).getName().equals(aHue.getName())) + for (int i = 0; i < hueaddress.getDevices().size(); i++) { + if (hueaddress.getDevices().get(i).getName().equals(aHue.getName())) indexHue = i; } - if(indexHue >= 0) { + if (indexHue >= 0) { hueaddress.getDevices().set(indexHue, aHue); this.setSettingsChanged(true); } } + public Boolean isValidHomeWizard() { - if(this.getHomeWizardAddress() == null || this.getHomeWizardAddress().getDevices().size() <= 0) + if (this.getHomeWizardAddress() == null || this.getHomeWizardAddress().getDevices().size() <= 0) return false; - + List devicesList = this.getHomeWizardAddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; - + return true; } + public Boolean isValidOpenhab() { - if(this.getOpenhabaddress() == null || this.getOpenhabaddress().getDevices().size() <= 0) + if (this.getOpenhabaddress() == null || this.getOpenhabaddress().getDevices().size() <= 0) return false; - + List devicesList = this.getOpenhabaddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; - + return true; } + public Boolean isValidFhem() { - if(this.getFhemaddress() == null || this.getFhemaddress().getDevices().size() <= 0) + if (this.getFhemaddress() == null || this.getFhemaddress().getDevices().size() <= 0) return false; - + List devicesList = this.getFhemaddress().getDevices(); - if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) return false; - + return true; } + public Boolean isValidBroadlink() { return this.isBroadlinkconfigured(); } + + public boolean isTracestate() { + return tracestate; + } + + public void setTracestate(boolean tracestate) { + this.tracestate = tracestate; + } + + public IpList getMoziotgateway() { + return moziotgateway; + } + + public void setMoziotgateway(IpList moziotgateway) { + this.moziotgateway = moziotgateway; + } + + public Boolean isValidMozIot() { + if (this.getMoziotgateway() == null || this.getMoziotgateway().getDevices().size() <= 0) + return false; + + List devicesList = this.getMoziotgateway().getDevices(); + if (devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) + return false; + + return true; + } + + public boolean isMoziotconfigured() { + return moziotconfigured; + } + + public void setMoziotconfigured(boolean moziotconfigured) { + this.moziotconfigured = moziotconfigured; + } } diff --git a/src/main/java/com/bwssystems/HABridge/hue/ColorData.java b/src/main/java/com/bwssystems/HABridge/hue/ColorData.java index 6fd417c..700fa5b 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/ColorData.java +++ b/src/main/java/com/bwssystems/HABridge/hue/ColorData.java @@ -19,4 +19,10 @@ public class ColorData { return mode; } + public String toString() { + String formatString; + + formatString = "Color Data mode: " + mode + ", data: " + data; + return formatString; + } } \ No newline at end of file diff --git a/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java b/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java index 89b97f9..4fee010 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java +++ b/src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java @@ -23,7 +23,7 @@ public class ColorDecode { private static final String COLOR_HSL = "${color.hsl}"; private static final Pattern COLOR_MILIGHT = Pattern.compile("\\$\\{color.milight\\:([01234])\\}"); - public static List convertHSLtoRGB(int hue, int sat, int brightness) { + public static List convertHSLtoRGB(HueSatBri hsl) { List rgb; float decimalBrightness = (float) 0.0; float var_1 = (float) 0.0; @@ -35,25 +35,25 @@ public class ColorDecode { double g = 0.0; double b = 0.0; - if(brightness > 0) - decimalBrightness = (float) (brightness / 255.0); + if(hsl.getBri() > 0) + decimalBrightness = (float) (hsl.getBri() / 255.0); - if(hue > 0) { - h = (float)(hue / 65535.0); + if(hsl.getHue() > 0) { + h = ((float)hsl.getHue() / (float)65535.0); h2 = h + (float)0.5; - if(h2 > 1) { - h2 = h2 * (float) -1.0; + if(h2 > 1.0) { + h2 = h2 - (float)1.0; } } - if(sat > 0) { - s = (float)(sat / 254.0); + if(hsl.getSat() > 0) { + s = (float)(hsl.getSat() / 254.0); } if (s == 0) { - r = decimalBrightness * 255; - g = decimalBrightness * 255; - b = decimalBrightness * 255; + r = decimalBrightness * (float)255; + g = decimalBrightness * (float)255; + b = decimalBrightness * (float)255; } else { @@ -66,44 +66,51 @@ public class ColorDecode { 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)); + var_1 = 2 * decimalBrightness - var_2; + float onethird = (float)0.33333; + float h2Plus = (h2 + onethird); + float h2Minus = (h2 - onethird); + log.debug("calculate HSL vars - var1: " + var_1 + ", var_2: " + var_2 + ", h2: " + h2 + ", h2 + 1/3: " + h2Plus + ", h2 - 1/3: " + h2Minus); + r = 255 * hue_2_rgb(var_1, var_2, h2Plus); + g = 255 * hue_2_rgb(var_1, var_2, h2); + b = 255 * hue_2_rgb(var_1, var_2, h2Minus); }; rgb = new ArrayList(); - rgb.add((int) Math.round(r * 255)); - rgb.add((int) Math.round(g * 255)); - rgb.add((int) Math.round(b * 255)); + rgb.add((int) Math.round(r)); + rgb.add((int) Math.round(g)); + rgb.add((int) Math.round(b)); + log.debug("Color change with HSL: " + hsl + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + + rgb.get(2)); return rgb; } public static float hue_2_rgb(float v1, float v2, float vh) { - if (vh < 0) + log.debug("hue_2_rgb vh: " + vh); + if (vh < 0.0) { - vh += 1; + vh = vh + (float)1; }; - if (vh > 1) + if (vh > 1.0) { - vh -= 1; + vh = vh - (float)1; }; - if ((6 * vh) < 1) + if (((float)6.0 * vh) < 1.0) { - return (v1 + (v2 - v1) * 6 * vh); + return (v1 + (v2 - v1) * (float)6.0 * vh); }; - if ((2 * vh) < 1) + if (((float)2.0 * vh) < 1.0) { return (v2); }; - if ((3 * vh) < 2) + if ((3.0 * vh) < 2.0) { - return (v1 + (v2 - v1) * ((2 / 3 - vh) * 6)); + return (v1 + (v2 - v1) * (((float)2.0 / (float)3.0 - vh) * (float)6.0)); }; return (v1); @@ -245,6 +252,8 @@ public class ColorDecode { rgb = convertCIEtoRGB((List) colorData.getData(), setIntensity); } else if (colorMode == ColorData.ColorMode.CT) { rgb = convertCTtoRGB((Integer) colorData.getData()); + } else if (colorMode == ColorData.ColorMode.HS) { + rgb = convertHSLtoRGB((HueSatBri) colorData.getData()); } while (notDone) { diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index 80174b1..4b7de93 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -44,7 +44,8 @@ import java.util.Map; import java.util.Arrays; /** - * Based on Armzilla's HueMulator - a Philips Hue emulator using sparkjava rest server + * Based on Armzilla's HueMulator - a Philips Hue emulator using sparkjava rest + * server */ public class HueMulator { @@ -60,14 +61,15 @@ public class HueMulator { private Gson aGsonHandler; private DeviceMapTypes validMapTypes; - public HueMulator(BridgeSettings bridgeMaster, DeviceRepository aDeviceRepository, GroupRepository aGroupRepository, HomeManager aHomeManager) { + public HueMulator(BridgeSettings bridgeMaster, DeviceRepository aDeviceRepository, GroupRepository aGroupRepository, + HomeManager aHomeManager) { repository = aDeviceRepository; groupRepository = aGroupRepository; validMapTypes = new DeviceMapTypes(); bridgeSettingMaster = bridgeMaster; bridgeSettings = bridgeSettingMaster.getBridgeSettingsDescriptor(); - - homeManager= aHomeManager; + + homeManager = aHomeManager; myHueHome = (HueHome) homeManager.findHome(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex]); aGsonHandler = new GsonBuilder().create(); } @@ -77,21 +79,22 @@ public class HueMulator { log.info("Hue emulator service started...."); before(HUE_CONTEXT + "/*", (request, response) -> { // This currently causes an error with Spark replies -// String path = request.pathInfo(); -// if (path.endsWith("/")) { // it should work with or without a trailing slash -// response.redirect(path.substring(0, path.length() - 1)); -// } - log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + ">>>, and body <<<" + request.body() + ">>>"); - if(bridgeSettingMaster.getBridgeSecurity().isSecure()) { + // String path = request.pathInfo(); + // if (path.endsWith("/")) { // it should work with or without a trailing slash + // response.redirect(path.substring(0, path.length() - 1)); + // } + log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + + ">>>, and body <<<" + request.body() + ">>>"); + if (bridgeSettingMaster.getBridgeSecurity().isSecure()) { String pathInfo = request.pathInfo(); - if(pathInfo != null && pathInfo.contains(HUE_CONTEXT + "/devices")) { + if (pathInfo != null && pathInfo.contains(HUE_CONTEXT + "/devices")) { User authUser = bridgeSettingMaster.getBridgeSecurity().getAuthenticatedUser(request); - if(authUser == null) { + if (authUser == null) { halt(401, "{\"message\":\"User not authenticated\"}"); } } else if (bridgeSettingMaster.getBridgeSecurity().isSecureHueApi()) { User authUser = bridgeSettingMaster.getBridgeSecurity().getAuthenticatedUser(request); - if(authUser == null) { + if (authUser == null) { halt(401, "{\"message\":\"User not authenticated\"}"); } } @@ -103,16 +106,16 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return groupsListHandler(request.params(":userid"), request.ip()); - } , new JsonTransformer()); + return groupsListHandler(request.params(":userid"), request.ip()); + }, new JsonTransformer()); // http://ip_address:port/api/{userId}/groups/{groupId} returns json // object for specified group. get(HUE_CONTEXT + "/:userid/groups/:groupid", "application/json", (request, response) -> { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return groupsIdHandler(request.params(":groupid"), request.params(":userid"), request.ip()); - } , new JsonTransformer()); + return groupsIdHandler(request.params(":groupid"), request.params(":userid"), request.ip()); + }, new JsonTransformer()); // http://ip_address:port/:userid/groups CORS request options(HUE_CONTEXT + "/:userid/groups", "application/json", (request, response) -> { response.status(HttpStatus.SC_OK); @@ -152,15 +155,16 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false); - }); + return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), + false); + }); // http://ip_address:port/api/{userId}/scenes returns json objects of // all scenes configured get(HUE_CONTEXT + "/:userid/scenes", "application/json", (request, response) -> { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return basicListHandler("scenes", request.params(":userid"), request.ip()); + return basicListHandler("scenes", request.params(":userid"), request.ip()); }); // http://ip_address:port/:userid/scenes CORS request options(HUE_CONTEXT + "/:userid/scenes", "application/json", (request, response) -> { @@ -177,7 +181,8 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - log.debug("scene add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + log.debug("scene add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + + request.body()); return "[{\"success\":{\"id\":\"1\"}}]"; }); // http://ip_address:port/api/{userId}/schedules returns json objects of @@ -186,7 +191,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return basicListHandler("schedules", request.params(":userid"), request.ip()); + return basicListHandler("schedules", request.params(":userid"), request.ip()); }); // http://ip_address:port/:userid/schedules CORS request options(HUE_CONTEXT + "/:userid/schedules", "application/json", (request, response) -> { @@ -203,7 +208,8 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - log.debug("schedules add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + log.debug("schedules add requested from " + request.ip() + " user " + request.params(":userid") + + " with body " + request.body()); return "[{\"success\":{\"id\":\"1\"}}]"; }); // http://ip_address:port/api/{userId}/sensors returns json objects of @@ -212,7 +218,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return basicListHandler("sensors", request.params(":userid"), request.ip()); + return basicListHandler("sensors", request.params(":userid"), request.ip()); }); // http://ip_address:port/:userid/sensors CORS request options(HUE_CONTEXT + "/:userid/sensors", "application/json", (request, response) -> { @@ -229,7 +235,8 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - log.debug("sensors add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + log.debug("sensors add requested from " + request.ip() + " user " + request.params(":userid") + + " with body " + request.body()); return "[{\"success\":{\"id\":\"1\"}}]"; }); // http://ip_address:port/api/{userId}/rules returns json objects of all @@ -238,7 +245,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return basicListHandler("rules", request.params(":userid"), request.ip()); + return basicListHandler("rules", request.params(":userid"), request.ip()); }); // http://ip_address:port/:userid/rules CORS request options(HUE_CONTEXT + "/:userid/rules", "application/json", (request, response) -> { @@ -255,7 +262,8 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - log.debug("rules add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + log.debug("rules add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + + request.body()); return "[{\"success\":{\"id\":\"1\"}}]"; }); // http://ip_address:port/api/{userId}/resourcelinks returns json @@ -264,7 +272,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - return basicListHandler("resourcelinks", request.params(":userid"), request.ip()); + return basicListHandler("resourcelinks", request.params(":userid"), request.ip()); }); // http://ip_address:port/:userid/resourcelinks CORS request options(HUE_CONTEXT + "/:userid/resourcelinks", "application/json", (request, response) -> { @@ -281,7 +289,8 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - log.debug("resourcelinks add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + log.debug("resourcelinks add requested from " + request.ip() + " user " + request.params(":userid") + + " with body " + request.body()); return "[{\"success\":{\"id\":\"1\"}}]"; }); // http://ip_address:port/api/{userId}/lights returns json objects of @@ -291,7 +300,7 @@ public class HueMulator { response.type("application/json"); response.status(HttpStatus.SC_OK); return lightsListHandler(request.params(":userid"), request.ip()); - } , new JsonTransformer()); + }, new JsonTransformer()); // http://ip_address:port/api/{userId}/lights/ returns json objects of // all lights configured @@ -300,7 +309,7 @@ public class HueMulator { response.type("application/json"); response.status(HttpStatus.SC_OK); return lightsListHandler(request.params(":userid"), request.ip()); - } , new JsonTransformer()); + }, new JsonTransformer()); // http://ip_address:port/api CORS request options(HUE_CONTEXT, "application/json", (request, response) -> { @@ -345,7 +354,7 @@ public class HueMulator { response.type("application/json"); response.status(HttpStatus.SC_OK); return getConfig(null, request.ip()); - } , new JsonTransformer()); + }, new JsonTransformer()); // http://ip_address:port/api/{userId}/config returns json objects for // the config @@ -354,7 +363,7 @@ public class HueMulator { response.type("application/json"); response.status(HttpStatus.SC_OK); return getConfig(request.params(":userid"), request.ip()); - } , new JsonTransformer()); + }, new JsonTransformer()); // http://ip_address:port/:userid/config CORS request options(HUE_CONTEXT + "/:userid/config", "application/json", (request, response) -> { response.status(HttpStatus.SC_OK); @@ -370,9 +379,10 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - log.debug("Config change requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); + log.debug("Config change requested from " + request.ip() + " user " + request.params(":userid") + + " with body " + request.body()); HueConfig aConfig = aGsonHandler.fromJson(request.body(), HueConfig.class); - if(aConfig.getPortalservices() != null) { + if (aConfig.getPortalservices() != null) { return "[{\"success\":{\"/config/portalservices\":true}}]"; } return "[{\"success\":{\"/config/name\":\"My bridge\"}}]"; @@ -385,7 +395,7 @@ public class HueMulator { response.type("application/json"); response.status(HttpStatus.SC_OK); return getFullState(request.params(":userid"), request.ip()); - } , new JsonTransformer()); + }, new JsonTransformer()); // http://ip_address:port/api/{userId}/ returns json objects for the full // state @@ -394,7 +404,7 @@ public class HueMulator { response.type("application/json"); response.status(HttpStatus.SC_OK); return getFullState(request.params(":userid"), request.ip()); - } , new JsonTransformer()); + }, new JsonTransformer()); // http://ip_address:port/api/{userId}/lights/{lightId} returns json // object for a given light @@ -403,7 +413,7 @@ public class HueMulator { response.type("application/json"); response.status(HttpStatus.SC_OK); return getLight(request.params(":userid"), request.params(":id"), request.ip()); - } , new JsonTransformer()); + }, new JsonTransformer()); // http://ip_address:port/api/:userid/lights/:id/bridgeupdatestate CORS // request @@ -444,7 +454,7 @@ public class HueMulator { return changeState(request.params(":userid"), request.params(":id"), request.body(), request.ip(), false); }); } - + @SuppressWarnings("unchecked") private String formatSuccessHueResponse(StateChangeBody stateChanges, String body, String lightId, DeviceState deviceState, Integer targetBri, Integer targetBriInc, ColorData colorData, boolean offState) { @@ -460,9 +470,9 @@ public class HueMulator { } if (deviceState != null) { deviceState.setOn(stateChanges.isOn()); - if(!deviceState.isOn() && deviceState.getBri() == 254) + if (!deviceState.isOn() && deviceState.getBri() == 254) deviceState.setBri(0); - if(!deviceState.isOn() && offState) + if (!deviceState.isOn() && offState) deviceState.setBri(0); } notFirstChange = true; @@ -471,8 +481,8 @@ public class HueMulator { if (body.contains("\"bri\"")) { if (notFirstChange) responseString = responseString + ","; - responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/bri\":" + stateChanges.getBri() - + "}}"; + responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/bri\":" + + stateChanges.getBri() + "}}"; if (deviceState != null) deviceState.setBri(stateChanges.getBri()); notFirstChange = true; @@ -494,16 +504,16 @@ public class HueMulator { if (body.contains("\"xy\"")) { if (notFirstChange) responseString = responseString + ","; - responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/xy\":" + stateChanges.getXy() - + "}}"; + responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/xy\":" + + stateChanges.getXy() + "}}"; if (deviceState != null) deviceState.setXy(stateChanges.getXy()); notFirstChange = true; } else if (body.contains("\"ct\"")) { if (notFirstChange) responseString = responseString + ","; - responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/ct\":" + stateChanges.getCt() - + "}}"; + responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/ct\":" + + stateChanges.getCt() + "}}"; if (deviceState != null) deviceState.setCt(stateChanges.getCt()); notFirstChange = true; @@ -511,8 +521,8 @@ public class HueMulator { if (body.contains("\"hue\"")) { if (notFirstChange) responseString = responseString + ","; - responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/hue\":" + stateChanges.getHue() - + "}}"; + responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/hue\":" + + stateChanges.getHue() + "}}"; if (deviceState != null) deviceState.setHue(stateChanges.getHue()); notFirstChange = true; @@ -521,12 +531,12 @@ public class HueMulator { if (body.contains("\"sat\"")) { if (notFirstChange) responseString = responseString + ","; - responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/sat\":" + stateChanges.getSat() - + "}}"; + responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/sat\":" + + stateChanges.getSat() + "}}"; if (deviceState != null) deviceState.setSat(stateChanges.getSat()); notFirstChange = true; - } + } } if (body.contains("\"xy_inc\"")) { @@ -564,7 +574,7 @@ public class HueMulator { if (deviceState != null) deviceState.setSat(deviceState.getSat() + stateChanges.getSat_inc()); notFirstChange = true; - } + } } if (body.contains("\"effect\"")) { @@ -597,11 +607,12 @@ public class HueMulator { notFirstChange = true; } - if((deviceState != null) && deviceState.isOn() && deviceState.getBri() <= 0) + if ((deviceState != null) && deviceState.isOn() && deviceState.getBri() <= 0) deviceState.setBri(254); - -// if((deviceState != null) && !deviceState.isOn() && (targetBri != null || targetBriInc != null)) -// deviceState.setOn(true); + + // if((deviceState != null) && !deviceState.isOn() && (targetBri != null || + // targetBriInc != null)) + // deviceState.setOn(true); responseString = responseString + "]"; @@ -628,9 +639,10 @@ public class HueMulator { private String basicListHandler(String type, String userId, String requestIp) { log.debug("hue " + type + " list requested by user: " + userId + " from address: " + requestIp); - HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors != null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); return aGsonHandler.toJson(theErrors); @@ -642,9 +654,10 @@ public class HueMulator { private Object addGroup(String userId, String ip, String body) { HueError[] theErrors = null; log.debug("group add requested from " + ip + " user " + userId + " with body " + body); - theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors == null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); GroupResponse theGroup = null; @@ -655,13 +668,14 @@ public class HueMulator { } if (theGroup == null) { log.warn("Could not parse add group body. No group created."); - return aGsonHandler.toJson(HueErrorResponse.createResponse("5", "/groups/lights", - "invalid/missing parameters in body", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("5", "/groups/lights", "invalid/missing parameters in body", null, null, null) + .getTheErrors(), HueError[].class); } - + List groups = groupRepository.findAll(); GroupDescriptor newGroup = new GroupDescriptor(); - + String type = theGroup.getType(); String groupClass = theGroup.getClass_name(); @@ -675,14 +689,16 @@ public class HueMulator { if (!type.equals("Room")) { if (theGroup.getLights() == null || theGroup.getLights().length == 0) { return aGsonHandler.toJson(HueErrorResponse.createResponse("5", "/groups/lights", - "invalid/missing parameters in body", null, null, null).getTheErrors(), HueError[].class); + "invalid/missing parameters in body", null, null, null).getTheErrors(), HueError[].class); } } else { // check room class if it's a room if (groupClass == null || groupClass.trim().equals("")) { groupClass = GroupClassTypes.OTHER; } else if (!new GroupClassTypes().validateType(groupClass)) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("7", "/groups/class", - "invalid value, " + groupClass + ", for parameter, class", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("7", "/groups/class", + "invalid value, " + groupClass + ", for parameter, class", null, null, null) + .getTheErrors(), HueError[].class); } } String name = theGroup.getName(); @@ -696,7 +712,7 @@ public class HueMulator { newGroup.setLights(theGroup.getLights()); groups.add(newGroup); groupRepository.save(groups.toArray(new GroupDescriptor[0])); - + return "[{\"success\":{\"id\":\"" + newId + "\"}}]"; } @@ -706,15 +722,19 @@ public class HueMulator { private Object deleteGroup(String userId, String groupId, String ip) { HueError[] theErrors = null; log.debug("group delete requested from " + ip + " user " + userId); - theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors == null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); GroupDescriptor group = groupRepository.findOne(groupId); if (group == null || group.isInactive()) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId, - "resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler + .toJson(HueErrorResponse + .createResponse("3", "/groups/" + groupId, + "resource, /groups/" + groupId + ", not available", null, null, null) + .getTheErrors(), HueError[].class); } else { groupRepository.delete(group); return "[{\"success\":\"/groups/" + groupId + " deleted\"}}]"; @@ -726,15 +746,19 @@ public class HueMulator { private Object modifyGroup(String userId, String groupId, String ip, String body) { HueError[] theErrors = null; log.debug("group modify requested from " + ip + " user " + userId + " with body " + body); - theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors == null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); GroupDescriptor group = groupRepository.findOne(groupId); if (group == null || group.isInactive()) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId, - "resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler + .toJson(HueErrorResponse + .createResponse("3", "/groups/" + groupId, + "resource, /groups/" + groupId + ", not available", null, null, null) + .getTheErrors(), HueError[].class); } else { String successString = "["; GroupResponse theGroup = null; @@ -757,37 +781,48 @@ public class HueMulator { } if (!group.getGroupType().equals("Room")) { if (!(groupClass == null || groupClass.trim().equals(""))) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("6", "/groups/" + groupId + "/class", - "parameter, /groups/" + groupId + "/class, not available", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("6", "/groups/" + groupId + "/class", + "parameter, /groups/" + groupId + "/class, not available", null, null, null) + .getTheErrors(), HueError[].class); } if (theGroup.getLights() != null) { if (theGroup.getLights().length == 0) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("7", "/groups/" + groupId + "/lights", - "invalid value, " + Arrays.toString(theGroup.getLights()) + ", for parameter, /groups" + groupId + "/lights", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler + .toJson(HueErrorResponse.createResponse("7", "/groups/" + groupId + "/lights", + "invalid value, " + Arrays.toString(theGroup.getLights()) + + ", for parameter, /groups" + groupId + "/lights", + null, null, null).getTheErrors(), HueError[].class); } else { group.setLights(theGroup.getLights()); - successString += "{\"success\":{\"/groups/" + groupId + "/lights\":\"" + Arrays.toString(theGroup.getLights()) + "\"}},"; + successString += "{\"success\":{\"/groups/" + groupId + "/lights\":\"" + + Arrays.toString(theGroup.getLights()) + "\"}},"; } } } else { // check room class if it's a room if (!(groupClass == null || groupClass.trim().equals(""))) { if (!new GroupClassTypes().validateType(groupClass)) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("7", "/groups/class", - "invalid value, " + groupClass + ", for parameter, class", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("7", "/groups/class", + "invalid value, " + groupClass + ", for parameter, class", null, null, null) + .getTheErrors(), HueError[].class); } else { group.setGroupClass(groupClass); - successString += "{\"success\":{\"/groups/" + groupId + "/class\":\"" + groupClass + "\"}},"; + successString += "{\"success\":{\"/groups/" + groupId + "/class\":\"" + groupClass + + "\"}},"; } } if (theGroup.getLights() != null) { group.setLights(theGroup.getLights()); - successString += "{\"success\":{\"/groups/" + groupId + "/lights\":\"" + Arrays.toString(theGroup.getLights()) + "\"}},"; + successString += "{\"success\":{\"/groups/" + groupId + "/lights\":\"" + + Arrays.toString(theGroup.getLights()) + "\"}},"; } } - + groupRepository.save(); - return (successString.length() == 1) ? "[]" : successString.substring(0, successString.length()-1) + "]"; + return (successString.length() == 1) ? "[]" + : successString.substring(0, successString.length() - 1) + "]"; } } return theErrors; @@ -799,17 +834,19 @@ public class HueMulator { if (bridgeSettings.isTraceupnp()) log.info("Traceupnp: hue group list requested: " + userId + " from " + requestIp); log.debug("hue group list requested: " + userId + " from " + requestIp); - theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors == null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); - List groupList = groupRepository.findAllByRequester(requestIp); + List groupList = groupRepository.findAllByRequester(requestIp); groupResponseMap = new HashMap(); for (GroupDescriptor group : groupList) { GroupResponse groupResponse = null; - if(!group.isInactive()) { - Map lights = repository.findAllByGroupWithState(group.getLights(), requestIp, myHueHome, aGsonHandler); + if (!group.isInactive()) { + Map lights = repository.findAllByGroupWithState(group.getLights(), + requestIp, myHueHome, aGsonHandler); groupResponse = GroupResponse.createResponse(group, lights); groupResponseMap.put(group.getId(), groupResponse); } @@ -822,30 +859,34 @@ public class HueMulator { return groupResponseMap; } - private Object groupsIdHandler(String groupId, String userId, String requestIp) { log.debug("hue group id: <" + groupId + "> requested: " + userId + " from " + requestIp); HueError[] theErrors = null; - theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors == null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); if (groupId.equalsIgnoreCase("0")) { @SuppressWarnings("unchecked") - GroupResponse theResponse = GroupResponse.createDefaultGroupResponse((Map)lightsListHandler(userId, requestIp)); + GroupResponse theResponse = GroupResponse + .createDefaultGroupResponse((Map) lightsListHandler(userId, requestIp)); return theResponse; } else { GroupDescriptor group = groupRepository.findOne(groupId); if (group == null || group.isInactive()) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId, - "resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("3", "/groups/" + groupId, + "resource, /groups/" + groupId + ", not available", null, null, null) + .getTheErrors(), HueError[].class); } else { - Map lights = repository.findAllByGroupWithState(group.getLights(), requestIp, myHueHome, aGsonHandler); + Map lights = repository.findAllByGroupWithState(group.getLights(), + requestIp, myHueHome, aGsonHandler); GroupResponse theResponse = GroupResponse.createResponse(group, lights); - return theResponse; + return theResponse; } - + } } @@ -858,52 +899,56 @@ public class HueMulator { if (bridgeSettings.isTraceupnp()) log.info("Traceupnp: hue lights list requested by user: " + userId + " from address: " + requestIp); log.debug("hue lights list requested: " + userId + " from " + requestIp); - theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors == null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); - List deviceList = repository.findAllByRequester(requestIp); + List deviceList = repository.findAllByRequester(requestIp); deviceResponseMap = new HashMap(); for (DeviceDescriptor device : deviceList) { DeviceResponse deviceResponse = null; - if(!device.isInactive()) { + if (!device.isInactive()) { if (device.containsType(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { CallItem[] callItems = null; try { - if(device.getOnUrl() != null) + if (device.getOnUrl() != null) callItems = aGsonHandler.fromJson(device.getOnUrl(), CallItem[].class); - } catch(JsonSyntaxException e) { - log.warn("Could not decode Json for url items to get Hue state for device: " + device.getName()); + } catch (JsonSyntaxException e) { + log.warn("Could not decode Json for url items to get Hue state for device: " + + device.getName()); callItems = null; } - + for (int i = 0; callItems != null && i < callItems.length; i++) { - if((callItems[i].getType() != null && callItems[i].getType().equals(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) || - (callItems[i].getItem().getAsString().contains("hueName"))) { + if ((callItems[i].getType() != null && callItems[i].getType() + .equals(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) + || (callItems[i].getItem().getAsString().contains("hueName"))) { deviceResponse = myHueHome.getHueDeviceInfo(callItems[i], device); i = callItems.length; } } } - + if (deviceResponse == null) deviceResponse = DeviceResponse.createResponse(device); deviceResponseMap.put(device.getId(), deviceResponse); } } - // handle groups which shall be exposed as fake lights to selected devices like amazon echos + // handle groups which shall be exposed as fake lights to selected devices like + // amazon echos List groups = groupRepository.findVirtualLights(requestIp); for (GroupDescriptor group : groups) { - deviceResponseMap.put(String.valueOf(Integer.parseInt(group.getId()) + 10000), - DeviceResponse.createResponseForVirtualLight(group)); + deviceResponseMap.put(String.valueOf(Integer.parseInt(group.getId()) + 10000), + DeviceResponse.createResponseForVirtualLight(group)); } } - + if (theErrors != null) return theErrors; - + return deviceResponseMap; } @@ -917,58 +962,62 @@ public class HueMulator { log.info("Traceupnp: hue api user create requested: " + body + " from address: " + ipAddress); else log.debug("hue api user create requested: " + body + " from address: " + ipAddress); - - if(bridgeSettingMaster.getBridgeSecurity().isUseLinkButton() && bridgeSettingMaster.getBridgeControl().isLinkButton()) + + if (bridgeSettingMaster.getBridgeSecurity().isUseLinkButton() + && bridgeSettingMaster.getBridgeControl().isLinkButton()) toContinue = true; - else if(!bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) + else if (!bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) toContinue = true; - - if(toContinue) { + + if (toContinue) { log.debug("user add toContinue was true, creating user."); - + if (body != null && !body.isEmpty()) { try { aNewUser = aGsonHandler.fromJson(body, UserCreateRequest.class); } catch (Exception e) { log.warn("Could not add user. Request garbled: " + body); - return aGsonHandler.toJson(HueErrorResponse.createResponse("2", "/", - "Could not add user.", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("2", "/", "Could not add user.", null, null, null).getTheErrors(), + HueError[].class); } newUser = aNewUser.getUsername(); aDeviceType = aNewUser.getDevicetype(); } - + if (aDeviceType == null) aDeviceType = ""; else aDeviceType = aDeviceType + "#" + ipAddress; - + if (newUser == null) { newUser = bridgeSettingMaster.getBridgeSecurity().createWhitelistUser(aDeviceType); - } - else { + } else { bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(newUser, aDeviceType, false); } - - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); - + if (bridgeSettings.isTraceupnp() && !aDeviceType.equals("test_ha_bridge")) log.info("Traceupnp: hue api user create requested for device type: " + aDeviceType + " and username: " + newUser + (followingSlash ? " /api/ called" : "")); - log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser + (followingSlash ? " /api/ called" : "")); + log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser + + (followingSlash ? " /api/ called" : "")); return "[{\"success\":{\"username\":\"" + newUser + "\"}}]"; - } - else + } else log.debug("user add toContinue was false, returning not authorized"); - return aGsonHandler.toJson(HueErrorResponse.createResponse("101", "/api/", "link button not pressed", null, null, null).getTheErrors()); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("101", "/api/", "link button not pressed", null, null, null).getTheErrors()); } - + private Object getConfig(String userId, String ipAddress) { if (bridgeSettings.isTraceupnp()) - log.info("Traceupnp: hue api/:userid/config config requested from user: " + userId + " from address: " + ipAddress); + log.info("Traceupnp: hue api/:userid/config config requested from user: " + userId + " from address: " + + ipAddress); log.debug("hue api config requested: " + userId + " from " + ipAddress); - if (bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) != null) { + if (bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) != null) { log.debug("hue api config requested, User invalid, returning public config"); HuePublicConfig apiResponse = HuePublicConfig.createConfig("HA-Bridge", bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion(), bridgeSettings.getHubmac()); @@ -976,31 +1025,35 @@ public class HueMulator { } HueApiResponse apiResponse = new HueApiResponse("HA-Bridge", bridgeSettings.getUpnpConfigAddress(), - bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton(), bridgeSettings.getHubmac()); + bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), + bridgeSettingMaster.getBridgeControl().isLinkButton(), bridgeSettings.getHubmac()); log.debug("api response config <<<" + aGsonHandler.toJson(apiResponse.getConfig()) + ">>>"); return apiResponse.getConfig(); } - + @SuppressWarnings("unchecked") private Object getFullState(String userId, String ipAddress) { log.debug("hue api full state requested: " + userId + " from " + ipAddress); - HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors != null) { log.debug("full state error occurred <<<" + aGsonHandler.toJson(theErrors) + ">>>"); return theErrors; } HueApiResponse apiResponse = new HueApiResponse("HA-Bridge", bridgeSettings.getUpnpConfigAddress(), - bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton(), bridgeSettings.getHubmac()); + bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), + bridgeSettingMaster.getBridgeControl().isLinkButton(), bridgeSettings.getHubmac()); apiResponse.setLights((Map) this.lightsListHandler(userId, ipAddress)); apiResponse.setGroups((Map) this.groupsListHandler(userId, ipAddress)); return apiResponse; } - + private Object getLight(String userId, String lightId, String ipAddress) { log.debug("hue light requested: " + lightId + " for user: " + userId + " from " + ipAddress); - HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors != null) return theErrors; @@ -1011,8 +1064,10 @@ public class HueMulator { DeviceDescriptor device = repository.findOne(lightId); if (device == null) { -// response.status(HttpStatus.SC_NOT_FOUND); - return HueErrorResponse.createResponse("3", "/api/" + userId + "/lights/" + lightId, "Object not found", null, null, null).getTheErrors(); + // response.status(HttpStatus.SC_NOT_FOUND); + return HueErrorResponse + .createResponse("3", "/api/" + userId + "/lights/" + lightId, "Object not found", null, null, null) + .getTheErrors(); } else { log.debug("found device named: " + device.getName()); } @@ -1020,15 +1075,17 @@ public class HueMulator { if (device.containsType(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { CallItem[] callItems = null; try { - if(device.getOnUrl() != null) + if (device.getOnUrl() != null) callItems = aGsonHandler.fromJson(device.getOnUrl(), CallItem[].class); - } catch(JsonSyntaxException e) { + } catch (JsonSyntaxException e) { log.warn("Could not decode Json for url items to get Hue state for device: " + device.getName()); callItems = null; } - + for (int i = 0; callItems != null && i < callItems.length; i++) { - if((callItems[i].getType() != null && callItems[i].getType().equals(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) || callItems[i].getItem().getAsString().startsWith("{\"ipAddress\":\"")) { + if ((callItems[i].getType() != null + && callItems[i].getType().equals(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) + || callItems[i].getItem().getAsString().startsWith("{\"ipAddress\":\"")) { lightResponse = myHueHome.getHueDeviceInfo(callItems[i], device); i = callItems.length; } @@ -1039,7 +1096,7 @@ public class HueMulator { lightResponse = DeviceResponse.createResponse(device); return lightResponse; - + } private String updateState(String userId, String lightId, String body, String ipAddress) { @@ -1050,9 +1107,13 @@ public class HueMulator { Integer targetBriInc = null; ColorData colorData = null; + if (bridgeSettings.isTracestate()) + log.info("Tracestate: Update state requested: " + userId + " from " + ipAddress + " body: " + body); + log.debug("Update state requested: " + userId + " from " + ipAddress + " body: " + body); - HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors != null) return aGsonHandler.toJson(theErrors); @@ -1060,8 +1121,9 @@ public class HueMulator { theStateChanges = aGsonHandler.fromJson(body, StateChangeBody.class); } catch (Exception e) { log.warn("Could not parse state change body. Light state not changed."); - return aGsonHandler.toJson(HueErrorResponse.createResponse("2", "/lights/" + lightId, - "Could not parse state change body.", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("2", "/lights/" + lightId, "Could not parse state change body.", null, null, null) + .getTheErrors(), HueError[].class); } DeviceDescriptor device = repository.findOne(lightId); @@ -1075,33 +1137,17 @@ public class HueMulator { if (body.contains("\"bri_inc\"")) targetBriInc = Integer.valueOf(theStateChanges.getBri_inc()); else if (body.contains("\"bri\"")) { - targetBri =Integer.valueOf(theStateChanges.getBri()); + targetBri = Integer.valueOf(theStateChanges.getBri()); } state = device.getDeviceState(); if (state == null) state = DeviceState.createDeviceState(device.isColorDevice()); - if (body.contains("\"xy\"") || body.contains("\"ct\"") || body.contains("\"hue\"") || body.contains("\"xy_inc\"") || body.contains("\"ct_inc\"") || body.contains("\"hue_inc\"")) { - List xy = theStateChanges.getXy(); - List xyInc = theStateChanges.getXy_inc(); - Integer ct = theStateChanges.getCt(); - Integer ctInc = theStateChanges.getCt_inc(); - if (xy != null && xy.size() == 2) { - colorData = new ColorData(ColorData.ColorMode.XY, xy); - } else if (xyInc != null && xyInc.size() == 2) { - List current = state.getXy(); - current.set(0, current.get(0) + xyInc.get(0)); - current.set(1, current.get(1) + xyInc.get(1)); - colorData = new ColorData(ColorData.ColorMode.XY, current); - } else if (ct != null && ct != 0) { - colorData = new ColorData(ColorData.ColorMode.CT, ct); - } else if (ctInc != null && ctInc != 0) { - colorData = new ColorData(ColorData.ColorMode.CT, state.getCt() + ctInc); - } - } - - responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, colorData, device.isOffState()); + colorData = parseColorInfo(body, theStateChanges, state, targetBri, targetBriInc); + + responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, + colorData, device.isOffState()); device.setDeviceState(state); return responseString; @@ -1121,8 +1167,12 @@ public class HueMulator { boolean isDimRequest = false; boolean isOnRequest = false; ColorData colorData = null; + if (bridgeSettings.isTracestate()) + log.info("Tracestate: hue state change requested: " + userId + " from " + ipAddress + " body: " + body); + log.debug("hue state change requested: " + userId + " from " + ipAddress + " body: " + body); - HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors != null) { log.warn("Errors in security: <<<" + aGsonHandler.toJson(theErrors) + ">>>"); return aGsonHandler.toJson(theErrors); @@ -1134,8 +1184,9 @@ public class HueMulator { } if (theStateChanges == null) { log.warn("Could not parse state change body. Light state not changed."); - return aGsonHandler.toJson(HueErrorResponse.createResponse("2", "/lights/" + lightId, - "Could not parse state change body.", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("2", "/lights/" + lightId, "Could not parse state change body.", null, null, null) + .getTheErrors(), HueError[].class); } DeviceDescriptor device = repository.findOne(lightId); @@ -1155,51 +1206,33 @@ public class HueMulator { if (body.contains("\"bri_inc\"")) { targetBriInc = Integer.valueOf(theStateChanges.getBri_inc()); isDimRequest = true; - } - else if (body.contains("\"bri\"")) { + } else if (body.contains("\"bri\"")) { targetBri = Integer.valueOf(theStateChanges.getBri()); isDimRequest = true; } - if (body.contains("\"xy\"") || body.contains("\"ct\"") || body.contains("\"hue\"") || body.contains("\"xy_inc\"") || body.contains("\"ct_inc\"") || body.contains("\"hue_inc\"")) { - List xy = theStateChanges.getXy(); - List xyInc = theStateChanges.getXy_inc(); - Integer ct = theStateChanges.getCt(); - Integer ctInc = theStateChanges.getCt_inc(); - if (xy != null && xy.size() == 2) { - colorData = new ColorData(ColorData.ColorMode.XY, xy); - } else if (xyInc != null && xyInc.size() == 2) { - List current = state.getXy(); - current.set(0, current.get(0) + xyInc.get(0)); - current.set(1, current.get(1) + xyInc.get(1)); - colorData = new ColorData(ColorData.ColorMode.XY, current); - } else if (ct != null && ct != 0) { - colorData = new ColorData(ColorData.ColorMode.CT, ct); - } else if (ctInc != null && ctInc != 0) { - colorData = new ColorData(ColorData.ColorMode.CT, state.getCt() + ctInc); - } - if(colorData != null) - isColorRequest = true; - } - + colorData = parseColorInfo(body, theStateChanges, state, targetBri, targetBriInc); + if (colorData != null) + isColorRequest = true; + if (body.contains("\"on\"")) { isOnRequest = true; } - - if(!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest && !isOnRequest) { + + if (!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest && !isOnRequest) { isOnRequest = true; theStateChanges.setOn(true); - } else if(!device.isOnFirstDim() && !device.isOnWhenDimPresent() && isDimRequest) { + } else if (!device.isOnFirstDim() && !device.isOnWhenDimPresent() && isDimRequest) { // isOnRequest = false; } - if(device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) { + if (device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) { isOnRequest = true; theStateChanges.setOn(true); isDimRequest = false; isColorRequest = false; - } else if(device.isOnFirstDim() && isDimRequest && device.getDeviceState().isOn()) { - if(device.getDeviceState().getBri() == theStateChanges.getBri()) { + } else if (device.isOnFirstDim() && isDimRequest && device.getDeviceState().isOn()) { + if (device.getDeviceState().getBri() == theStateChanges.getBri()) { isOnRequest = true; theStateChanges.setOn(true); isDimRequest = false; @@ -1210,8 +1243,11 @@ public class HueMulator { isColorRequest = false; } } - - if(isOnRequest) { + + if (isOnRequest) { + if (bridgeSettings.isTracestate()) + log.info("Tracestate: Calling on-off as requested."); + log.debug("Calling on-off as requested."); if (theStateChanges.isOn()) { url = device.getOnUrl(); @@ -1220,91 +1256,212 @@ public class HueMulator { } // code for backwards compatibility - if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { - if(url == null) + if (device.getMapType() != null + && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { + if (url == null) url = device.getOnUrl(); } if (url != null && !url.equals("")) { - responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, targetBriInc, colorData); + responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, + targetBriInc, colorData); } else { - log.info("On/off url not available for state change, lightId: " + lightId + ", userId: " + userId + ", from IP: " - + ipAddress + ", body: " + body); + log.info("On/off url not available for state change, lightId: " + lightId + ", userId: " + userId + + ", from IP: " + ipAddress + ", body: " + body); } } if (isDimRequest) { + if (bridgeSettings.isTracestate()) + log.info("Tracestate: Calling dim as requested."); + log.debug("Calling dim as requested."); url = device.getDimUrl(); // code for backwards compatibility - if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { - if(url == null) + if (device.getMapType() != null + && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { + if (url == null) url = device.getOnUrl(); } if (url != null && !url.equals("")) { - if(isOnRequest) { + if (isOnRequest) { try { Thread.sleep(bridgeSettings.getButtonsleep()); } catch (InterruptedException e) { // ignore } } - responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, targetBriInc, colorData); + responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, + targetBriInc, colorData); } else { - log.info("Dim url not available for state change, lightId: " + lightId + ", userId: " + userId + ", from IP: " - + ipAddress + ", body: " + body); + log.info("Dim url not available for state change, lightId: " + lightId + ", userId: " + userId + + ", from IP: " + ipAddress + ", body: " + body); } } if (isColorRequest) { + if (bridgeSettings.isTracestate()) + log.info("Tracestate: Calling color as requested. With " + colorData); + log.debug("Calling color as requested."); url = device.getColorUrl(); // code for backwards compatibility - if(device.getMapType() != null && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { - if(url == null) + if (device.getMapType() != null + && device.getMapType().equalsIgnoreCase(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) { + if (url == null) url = device.getOnUrl(); } if (url != null && !url.equals("")) { - if((isOnRequest && !isDimRequest) || isDimRequest) { + if ((isOnRequest && !isDimRequest) || isDimRequest) { try { Thread.sleep(bridgeSettings.getButtonsleep()); } catch (InterruptedException e) { // ignore } } - responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, targetBriInc, colorData); + responseString = callUrl(url, device, userId, lightId, body, ipAddress, ignoreRequester, targetBri, + targetBriInc, colorData); } else { - log.info("Color url not available for state change, lightId: " + lightId + ", userId: " + userId + ", from IP: " - + ipAddress + ", body: " + body); + log.info("Color url not available for state change, lightId: " + lightId + ", userId: " + userId + + ", from IP: " + ipAddress + ", body: " + body); } } - + if (responseString == null || !responseString.contains("[{\"error\":")) { - if(!device.isNoState()) { - responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, colorData, device.isOffState()); + if (!device.isNoState()) { + responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, + targetBriInc, colorData, device.isOffState()); device.setDeviceState(state); } else { DeviceState dummyState = DeviceState.createDeviceState(device.isColorDevice()); - responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, targetBriInc, colorData, device.isOffState()); + responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, + targetBriInc, colorData, device.isOffState()); } } return responseString; - + } + private ColorData parseColorInfo(String body, StateChangeBody theStateChanges, DeviceState state, Integer targetBri, Integer targetBriInc) { + ColorData colorData = null; + List xy = null; + List xyInc = null; + Integer ct = null; + Integer ctInc = null; + HueSatBri anHSL = null; + Integer hue = null; + Integer sat = null; + Integer hueInc = null; + Integer satInc = null; + + if (body.contains("\"xy\"")) { + xy = theStateChanges.getXy(); + } + + if (body.contains("\"ct\"")) { + ct = theStateChanges.getCt(); + } + if (body.contains("\"hue\"")) { + hue = theStateChanges.getHue(); + } + if (body.contains("\"sat\"")) { + sat = theStateChanges.getSat(); + } + + if (body.contains("\"xy_inc\"")) { + xyInc = theStateChanges.getXy_inc(); + } + + if (body.contains("\"ct_inc\"")) { + ctInc = theStateChanges.getCt_inc(); + } + + if (body.contains("\"hue_inc\"")) { + hueInc = theStateChanges.getHue_inc(); + } + + if (body.contains("\"sat_inc\"")) { + satInc = theStateChanges.getSat_inc(); + } + + if (xy != null && xy.size() == 2) { + colorData = new ColorData(ColorData.ColorMode.XY, xy); + } else if (xyInc != null && xyInc.size() == 2) { + List current = state.getXy(); + current.set(0, current.get(0) + xyInc.get(0)); + current.set(1, current.get(1) + xyInc.get(1)); + colorData = new ColorData(ColorData.ColorMode.XY, current); + } else if (ct != null) { + colorData = new ColorData(ColorData.ColorMode.CT, ct); + } else if (ctInc != null) { + colorData = new ColorData(ColorData.ColorMode.CT, state.getCt() + ctInc); + } else if (hue != null || sat != null) { + anHSL = new HueSatBri(); + int bri = 0; + if(targetBriInc != null) { + bri = state.getBri() - targetBriInc; + if(bri < 0) + bri = 0; + } else if (targetBri != null) { + bri = targetBri; + } else { + bri = state.getBri(); + } + anHSL.setBri(bri); + if(hue != null) + anHSL.setHue(hue); + else + anHSL.setHue(state.getHue()); + + if(sat != null) + anHSL.setSat(sat); + else + anHSL.setSat(state.getSat()); + log.info("hue/sat request - " + anHSL); + colorData = new ColorData(ColorData.ColorMode.HS, anHSL); + } else if (hueInc != null || satInc != null) { + anHSL = new HueSatBri(); + int bri = 0; + if(targetBriInc != null) { + bri = state.getBri() - targetBriInc; + if(bri < 0) + bri = 0; + } else if (targetBri != null) { + bri = targetBri; + } else { + bri = state.getBri(); + } + anHSL.setBri(bri); + if(hueInc != null) + anHSL.setHue(state.getHue() - hueInc); + else + anHSL.setHue(state.getHue()); + + if(satInc != null) + anHSL.setSat(state.getSat() - satInc); + else + anHSL.setSat(state.getSat()); + log.info("hue/sat inc request - " + anHSL); + colorData = new ColorData(ColorData.ColorMode.HS, anHSL); + + } + return colorData; + } @SuppressWarnings("unchecked") - private String changeGroupState(String userId, String groupId, String body, String ipAddress, boolean fakeLightResponse) { + private String changeGroupState(String userId, String groupId, String body, String ipAddress, + boolean fakeLightResponse) { ColorData colorData = null; log.debug("PUT action to group " + groupId + " from " + ipAddress + " user " + userId + " with body " + body); HueError[] theErrors = null; - theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); + theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, + bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); if (theErrors == null) { - if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) + if (bridgeSettingMaster.getBridgeSecurity().isSettingsChanged()) bridgeSettingMaster.updateConfigFile(); GroupDescriptor group = null; @@ -1313,17 +1470,21 @@ public class HueMulator { DeviceState state = null; Map lights = null; if (groupId.equalsIgnoreCase("0")) { - lights = (Map)lightsListHandler(userId, ipAddress); + lights = (Map) lightsListHandler(userId, ipAddress); } else { group = groupRepository.findOne(groupId); if (group == null || group.isInactive()) { - return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId, - "resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson(HueErrorResponse + .createResponse("3", "/groups/" + groupId, + "resource, /groups/" + groupId + ", not available", null, null, null) + .getTheErrors(), HueError[].class); } else { if (fakeLightResponse) { - lights = repository.findAllByGroupWithState(group.getLights(), ipAddress, myHueHome, aGsonHandler, true); + lights = repository.findAllByGroupWithState(group.getLights(), ipAddress, myHueHome, + aGsonHandler, true); } else { - lights = repository.findAllByGroupWithState(group.getLights(), ipAddress, myHueHome, aGsonHandler); + lights = repository.findAllByGroupWithState(group.getLights(), ipAddress, myHueHome, + aGsonHandler); } } } @@ -1337,15 +1498,16 @@ public class HueMulator { } if (theStateChanges == null) { log.warn("Could not parse state change body. Light state not changed."); - return aGsonHandler.toJson(HueErrorResponse.createResponse("2", "/groups/" + groupId + "/action", - "Could not parse state change body.", null, null, null).getTheErrors(), HueError[].class); + return aGsonHandler.toJson( + HueErrorResponse.createResponse("2", "/groups/" + groupId + "/action", + "Could not parse state change body.", null, null, null).getTheErrors(), + HueError[].class); } if (group != null) { if (body.contains("\"bri_inc\"")) { targetBriInc = Integer.valueOf(theStateChanges.getBri_inc()); - } - else if (body.contains("\"bri\"")) { + } else if (body.contains("\"bri\"")) { targetBri = Integer.valueOf(theStateChanges.getBri()); } @@ -1353,9 +1515,8 @@ public class HueMulator { if (state == null) { state = DeviceState.createDeviceState(true); group.setAction(state); - } + } } - boolean turnOn = false; boolean turnOff = false; @@ -1369,7 +1530,8 @@ public class HueMulator { } } for (Map.Entry light : lights.entrySet()) { - log.debug("Processing light" + light.getKey() + ": " + turnOn + " " + turnOff + " " + light.getValue().getState().isOn()); + log.debug("Processing light" + light.getKey() + ": " + turnOn + " " + turnOff + " " + + light.getValue().getState().isOn()); // ignore on/off for devices that are already on/off if (turnOff && !light.getValue().getState().isOn()) continue; @@ -1377,34 +1539,40 @@ public class HueMulator { continue; changeState(userId, light.getKey(), body, ipAddress, fakeLightResponse); } - // construct success response: one success message per changed property, but not per light + // construct success response: one success message per changed property, but not + // per light if (group != null) { // if not group 0 - String response = formatSuccessHueResponse(theStateChanges, body, String.valueOf(Integer.parseInt(groupId) + 10000), - state, targetBri, targetBriInc, colorData, true); - group.setAction(state); - if (fakeLightResponse) { - return response; - } + String response = formatSuccessHueResponse(theStateChanges, body, + String.valueOf(Integer.parseInt(groupId) + 10000), state, targetBri, targetBriInc, + colorData, true); + group.setAction(state); + if (fakeLightResponse) { + return response; + } } String successString = "["; for (String pairStr : body.replaceAll("[{|}]", "").split(",\\s*\"")) { String[] pair = pairStr.split(":"); if (fakeLightResponse) { - successString += "{\"success\":{ \"/lights/" + String.valueOf(Integer.parseInt(groupId) + 10000) + "/state/" + pair[0].replaceAll("\"", "").trim() + "\": " + pair[1].trim() + "}},"; + successString += "{\"success\":{ \"/lights/" + String.valueOf(Integer.parseInt(groupId) + 10000) + + "/state/" + pair[0].replaceAll("\"", "").trim() + "\": " + pair[1].trim() + "}},"; } else { - successString += "{\"success\":{ \"address\": \"/groups/" + groupId + "/action/" + pair[0].replaceAll("\"", "").trim() + "\", \"value\": " + pair[1].trim() + "}},"; + successString += "{\"success\":{ \"address\": \"/groups/" + groupId + "/action/" + + pair[0].replaceAll("\"", "").trim() + "\", \"value\": " + pair[1].trim() + "}},"; } - + } - return (successString.length() == 1) ? "[]" : successString.substring(0, successString.length()-1) + "]"; + return (successString.length() == 1) ? "[]" + : successString.substring(0, successString.length() - 1) + "]"; } } return aGsonHandler.toJson(theErrors); } - - protected String callUrl(String url, DeviceDescriptor device, String userId, String lightId, String body, String ipAddress, boolean ignoreRequester, Integer targetBri, Integer targetBriInc, ColorData colorData) { + + protected String callUrl(String url, DeviceDescriptor device, String userId, String lightId, String body, + String ipAddress, boolean ignoreRequester, Integer targetBri, Integer targetBriInc, ColorData colorData) { String responseString = null; MultiCommandUtil aMultiUtil = new MultiCommandUtil(); aMultiUtil.setTheDelay(bridgeSettings.getButtonsleep()); @@ -1415,42 +1583,44 @@ public class HueMulator { if (url.startsWith("{\"item")) url = "[" + url + "]"; else { - if(url.startsWith("{")) + if (url.startsWith("{")) url = "[{\"item\":" + url + "}]"; else url = "[{\"item\":\"" + url + "\"}]"; } - } else if(!url.startsWith("[{\"item\"")) + } else if (!url.startsWith("[{\"item\"")) url = "[{\"item\":" + url + "}]"; log.debug("Decode Json for url items: " + url); CallItem[] callItems = null; try { callItems = aGsonHandler.fromJson(url, CallItem[].class); - } catch(JsonSyntaxException e) { - log.warn("Could not decode Json for url items: " + lightId + " for hue state change request: " + userId + " from " - + ipAddress + " body: " + body + " url items: " + url); + } catch (JsonSyntaxException e) { + log.warn("Could not decode Json for url items: " + lightId + " for hue state change request: " + userId + + " from " + ipAddress + " body: " + body + " url items: " + url); return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/lights/" + lightId, "Could decode json in request", "/lights/" + lightId, null, null).getTheErrors(), HueError[].class); } - + for (int i = 0; callItems != null && i < callItems.length; i++) { if (!ignoreRequester) { - if(!filterByRequester(device.getRequesterAddress(), ipAddress) || !filterByRequester(callItems[i].getFilterIPs(), ipAddress)) { - log.warn("filter for requester address not present in: (device)" + device.getRequesterAddress() + " OR then (item)" + callItems[i].getFilterIPs() + " with request ip of: " + ipAddress); + if (!filterByRequester(device.getRequesterAddress(), ipAddress) + || !filterByRequester(callItems[i].getFilterIPs(), ipAddress)) { + log.warn("filter for requester address not present in: (device)" + device.getRequesterAddress() + + " OR then (item)" + callItems[i].getFilterIPs() + " with request ip of: " + ipAddress); continue; - } + } } - + if (callItems[i].getCount() != null && callItems[i].getCount() > 0) aMultiUtil.setSetCount(callItems[i].getCount()); else aMultiUtil.setSetCount(1); // code for backwards compatibility - if((callItems[i].getType() == null || callItems[i].getType().trim().isEmpty())) { - if(validMapTypes.validateType(device.getMapType())) + if ((callItems[i].getType() == null || callItems[i].getType().trim().isEmpty())) { + if (validMapTypes.validateType(device.getMapType())) callItems[i].setType(device.getMapType().trim()); - else if(validMapTypes.validateType(device.getDeviceType())) + else if (validMapTypes.validateType(device.getDeviceType())) callItems[i].setType(device.getDeviceType().trim()); else callItems[i].setType(DeviceMapTypes.CUSTOM_DEVICE[DeviceMapTypes.typeIndex]); @@ -1471,13 +1641,14 @@ public class HueMulator { aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault()); log.debug("Calling Home device handler for type : " + callItems[i].getType().trim()); - responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], aMultiUtil, lightId, device.getDeviceState().getBri(), targetBri, targetBriInc, colorData, device, body); - if(responseString != null && responseString.contains("{\"error\":")) { + responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], + aMultiUtil, lightId, device.getDeviceState().getBri(), targetBri, targetBriInc, colorData, + device, body); + if (responseString != null && responseString.contains("{\"error\":")) { x = aMultiUtil.getSetCount(); } } - } - else + } else log.warn("Call Items type is null <<<" + callItems[i] + ">>>"); } diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueSatBri.java b/src/main/java/com/bwssystems/HABridge/hue/HueSatBri.java new file mode 100644 index 0000000..ce60fc6 --- /dev/null +++ b/src/main/java/com/bwssystems/HABridge/hue/HueSatBri.java @@ -0,0 +1,38 @@ +package com.bwssystems.HABridge.hue; + +public class HueSatBri { + int hue; + int sat; + int bri; + + public int getHue() { + return hue; + } + + public void setHue(int hue) { + this.hue = hue; + } + + public int getSat() { + return sat; + } + + public void setSat(int sat) { + this.sat = sat; + } + + public int getBri() { + return bri; + } + + public void setBri(int bri) { + this.bri = bri; + } + + public String toString() { + String formatString = new String(); + + formatString = "Hue: " + Integer.toString(hue) + ", Sat: " + Integer.toString(sat) + ", Bri: " + Integer.toString(bri); + return formatString; + } +} \ No newline at end of file diff --git a/src/main/resources/public/views/system.html b/src/main/resources/public/views/system.html index dfcdd72..eb4c8d6 100644 --- a/src/main/resources/public/views/system.html +++ b/src/main/resources/public/views/system.html @@ -19,6 +19,7 @@
  • HomeWizard Devices
  • OpenHAB Devices
  • FHEM Devices
  • +
  • Mozilla IOT Devices
  • Broadlink Devices
  • Add/Edit
  • @@ -738,6 +739,73 @@ + + Mozilla IOT Names and IP Addresses + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameIPPortUsername (opt)Password (opt)Use SSLManage
    + Nest @@ -803,6 +871,12 @@ ng-model="bridge.settings.traceupnp" ng-true-value=true ng-false-value=false> {{bridge.settings.traceupnp}} + + + +
    Trace State Changes {{bridge.settings.tracestate}}
    UPNP Send Delay