diff --git a/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy b/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy index f49ec95..a5d41ef 100644 --- a/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy +++ b/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy @@ -3,6 +3,7 @@ * * Author: SmartThings */ + // for the UI metadata { // Automatically generated. Make future change here. @@ -27,10 +28,10 @@ metadata { tiles (scale: 2){ multiAttributeTile(name:"rich-control", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" + attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#C6C7CC", nextState:"turningOn" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" + attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#C6C7CC", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { attributeState "level", action:"switch level.setLevel", range:"(0..100)" @@ -43,16 +44,10 @@ metadata { } } - standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - } - controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") { state "colorTemperature", action:"color temperature.setColorTemperature" } + valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { state "colorTemperature", label: '${currentValue} K' } @@ -60,29 +55,12 @@ metadata { standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") { state "default", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single" } - standardTile("refresh", "device.switch", height: 2, width: 2, inactiveLabel: false, decoration: "flat") { + + standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") { state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" } - controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range:"(0..100)") { - state "level", action:"switch level.setLevel" - } - valueTile("level", "device.level", inactiveLabel: false, decoration: "flat") { - state "level", label: 'Level ${currentValue}%' - } - controlTile("saturationSliderControl", "device.saturation", "slider", height: 1, width: 2, inactiveLabel: false) { - state "saturation", action:"color control.setSaturation" - } - valueTile("saturation", "device.saturation", inactiveLabel: false, decoration: "flat") { - state "saturation", label: 'Sat ${currentValue} ' - } - controlTile("hueSliderControl", "device.hue", "slider", height: 1, width: 2, inactiveLabel: false) { - state "hue", action:"color control.setHue" - } - valueTile("hue", "device.hue", inactiveLabel: false, decoration: "flat") { - state "hue", label: 'Hue ${currentValue} ' - } - main(["switch"]) + main(["rich-control"]) details(["rich-control", "colorTempSliderControl", "colorTemp", "reset", "refresh"]) } } @@ -127,34 +105,34 @@ void nextLevel() { void setLevel(percent) { log.debug "Executing 'setLevel'" parent.setLevel(this, percent) - sendEvent(name: "level", value: percent) + sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%") } void setSaturation(percent) { log.debug "Executing 'setSaturation'" parent.setSaturation(this, percent) - sendEvent(name: "saturation", value: percent) + sendEvent(name: "saturation", value: percent, displayed: false) } void setHue(percent) { log.debug "Executing 'setHue'" parent.setHue(this, percent) - sendEvent(name: "hue", value: percent) + sendEvent(name: "hue", value: percent, displayed: false) } void setColor(value) { log.debug "setColor: ${value}, $this" parent.setColor(this, value) - if (value.hue) { sendEvent(name: "hue", value: value.hue)} - if (value.saturation) { sendEvent(name: "saturation", value: value.saturation)} + if (value.hue) { sendEvent(name: "hue", value: value.hue, displayed: false)} + if (value.saturation) { sendEvent(name: "saturation", value: value.saturation, displayed: false)} if (value.hex) { sendEvent(name: "color", value: value.hex)} - if (value.level) { sendEvent(name: "level", value: value.level)} - if (value.switch) { sendEvent(name: "switch", value: value.switch)} + if (value.level) { sendEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")} + sendEvent(name: "switch", value: "on") } void reset() { log.debug "Executing 'reset'" - def value = [level:100, hex:"#90C638", saturation:56, hue:23] + def value = [level:100, saturation:56, hue:23] setAdjustedColor(value) parent.poll() } diff --git a/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy b/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy index 49e7f2f..18affa4 100644 --- a/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy +++ b/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy @@ -36,13 +36,6 @@ metadata { } } - standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - } - controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range:"(0..100)") { state "level", action:"switch level.setLevel" } @@ -51,7 +44,7 @@ metadata { state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" } - main(["switch"]) + main(["rich-control"]) details(["rich-control", "refresh"]) } } diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 93453ac..5b908d8 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -24,7 +24,7 @@ definition( category: "SmartThings Labs", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png", - //singleInstance: true + singleInstance: true ) preferences { @@ -643,21 +643,25 @@ def setColorTemperature(childDevice, huesettings) { def setColor(childDevice, huesettings) { log.debug "Executing 'setColor($huesettings)'" - def hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535) - def sat = Math.min(Math.round(huesettings.saturation * 255 / 100), 255) + def hue = null + def sat = null + def xy = null + if (huesettings.hex) { + xy = getHextoXY(huesettings.hex) + } else if (huesettings.hue && huesettings.saturation) { + hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535) + sat = Math.min(Math.round(huesettings.saturation * 255 / 100), 255) + } def alert = huesettings.alert ? huesettings.alert : "none" def transition = huesettings.transition ? huesettings.transition : 4 - def value = [sat: sat, hue: hue, alert: alert, transitiontime: transition] + def value = [xy: xy, sat: sat, hue: hue, alert: alert, transitiontime: transition, on: true] + if (huesettings.level != null) { if (huesettings.level == 1) value.bri = 1 else value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255) value.on = value.bri > 0 } - if (huesettings.switch) { - value.on = huesettings.switch == "on" - } - log.debug "sending command $value" put("lights/${getId(childDevice)}/state", value) } @@ -743,6 +747,59 @@ private getBridgeIP() { return host } +private getHextoXY(String colorStr) { + // For the hue bulb the corners of the triangle are: + // -Red: 0.675, 0.322 + // -Green: 0.4091, 0.518 + // -Blue: 0.167, 0.04 + + def cred = Integer.valueOf( colorStr.substring( 1, 3 ), 16 ) + def cgreen = Integer.valueOf( colorStr.substring( 3, 5 ), 16 ) + def cblue = Integer.valueOf( colorStr.substring( 5, 7 ), 16 ) + + double[] normalizedToOne = new double[3]; + normalizedToOne[0] = (cred / 255); + normalizedToOne[1] = (cgreen / 255); + normalizedToOne[2] = (cblue / 255); + float red, green, blue; + + // Make red more vivid + if (normalizedToOne[0] > 0.04045) { + red = (float) Math.pow( + (normalizedToOne[0] + 0.055) / (1.0 + 0.055), 2.4); + } else { + red = (float) (normalizedToOne[0] / 12.92); + } + + // Make green more vivid + if (normalizedToOne[1] > 0.04045) { + green = (float) Math.pow((normalizedToOne[1] + 0.055) + / (1.0 + 0.055), 2.4); + } else { + green = (float) (normalizedToOne[1] / 12.92); + } + + // Make blue more vivid + if (normalizedToOne[2] > 0.04045) { + blue = (float) Math.pow((normalizedToOne[2] + 0.055) + / (1.0 + 0.055), 2.4); + } else { + blue = (float) (normalizedToOne[2] / 12.92); + } + + float X = (float) (red * 0.649926 + green * 0.103455 + blue * 0.197109); + float Y = (float) (red * 0.234327 + green * 0.743075 + blue * 0.022598); + float Z = (float) (red * 0.0000000 + green * 0.053077 + blue * 1.035763); + + float x = X / (X + Y + Z); + float y = Y / (X + Y + Z); + + double[] xy = new double[2]; + xy[0] = x; + xy[1] = y; + return xy; +} + private Integer convertHexToInt(hex) { Integer.parseInt(hex,16) }