From cfe25607ac6289b83cb70e70c0087e64a4b4e64f Mon Sep 17 00:00:00 2001 From: Lars Finander Date: Wed, 24 Aug 2016 13:56:06 -0600 Subject: [PATCH 1/3] PROB-1352 Hue colors rendering incorrectly -Disable color conversion algorithm for hue/sat --- .../smartthings/hue-connect.src/hue-connect.groovy | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 415dd44..2d0649c 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -1017,12 +1017,12 @@ def setColor(childDevice, huesettings) { log.debug "Executing 'setColor($huesettings)'" updateInProgress() - + def value = [:] def hue = null def sat = null def xy = null - + // For now ignore model to get a consistent color if same color is set across multiple devices // def model = state.bulbs[getId(childDevice)]?.modelid if (huesettings.hex != null) { @@ -1038,11 +1038,12 @@ def setColor(childDevice, huesettings) { else value.hue = Math.min(Math.round(childDevice.device?.currentValue("hue") * 65535 / 100), 65535) - if (huesettings.saturation != null) + if (huesettings.saturation != null) value.sat = Math.min(Math.round(huesettings.saturation * 254 / 100), 254) else value.sat = Math.min(Math.round(childDevice.device?.currentValue("saturation") * 254 / 100), 254) +/* Disabled for now due to bad behavior via Lightning Wizard if (!value.xy) { // Below will translate values to hex->XY to take into account the color support of the different hue types def hex = colorUtil.hslToHex((int) huesettings.hue, (int) huesettings.saturation) @@ -1050,6 +1051,7 @@ def setColor(childDevice, huesettings) { // Once groups, or scenes are introduced it might be a good idea to use unique models again value.xy = calculateXY(hex) } +*/ // Default behavior is to turn light on value.on = true @@ -1059,7 +1061,7 @@ def setColor(childDevice, huesettings) { value.on = false else if (huesettings.level == 1) value.bri = 1 - else + else value.bri = Math.min(Math.round(huesettings.level * 254 / 100), 254) } value.alert = huesettings.alert ? huesettings.alert : "none" From cdf5d21e8fa1cc5a8c686e028ff8148b3d0bdda5 Mon Sep 17 00:00:00 2001 From: Lars Finander Date: Mon, 29 Aug 2016 15:17:40 -0600 Subject: [PATCH 2/3] SSVD-2603 Prevent removing of Hue bridge -Moved warning messages to top of bridge DTH screen -User is now presented with a warning message when removing --- .../hue-bridge.src/hue-bridge.groovy | 6 +-- .../hue-connect.src/hue-connect.groovy | 46 ++++++++++++------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy b/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy index dc0a9f0..0986ae8 100644 --- a/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy +++ b/devicetypes/smartthings/hue-bridge.src/hue-bridge.groovy @@ -28,8 +28,8 @@ metadata { } } valueTile("doNotRemove", "v", decoration: "flat", height: 2, width: 6, inactiveLabel: false) { - state "default", label:'Do not remove' - } + state "default", label:'If removed, Hue lights will not work properly' + } valueTile("idNumber", "device.idNumber", decoration: "flat", height: 2, width: 6, inactiveLabel: false) { state "default", label:'ID: ${currentValue}' } @@ -38,7 +38,7 @@ metadata { } main (["rich-control"]) - details(["rich-control", "idNumber", "networkAddress", "doNotRemove"]) + details(["rich-control", "doNotRemove", "idNumber", "networkAddress"]) } } diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 415dd44..6a6859c 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -290,8 +290,11 @@ def manualRefresh() { } def uninstalled(){ + // Remove bridgedevice connection to allow uninstall of smartapp even though bridge is listed + // as user of smartapp + app.updateSetting("bridgeDevice", null) state.bridges = [:] - state.username = null + state.username = null } // Handles events to add new bulbs @@ -415,23 +418,32 @@ def addBridge() { // Hue uses last 6 digits of MAC address as ID number, this number is shown on the bottom of the bridge def idNumber = getBridgeIdNumber(selectedHue) d = addChildDevice("smartthings", "Hue Bridge", selectedHue, vbridge.value.hub, ["label": "Hue Bridge ($idNumber)"]) - d?.completedSetup = true - log.debug "created ${d.displayName} with id ${d.deviceNetworkId}" - def childDevice = getChildDevice(d.deviceNetworkId) - updateBridgeStatus(childDevice) - childDevice.sendEvent(name: "idNumber", value: idNumber) - if (vbridge.value.ip && vbridge.value.port) { - if (vbridge.value.ip.contains(".")) { - childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port) - childDevice.updateDataValue("networkAddress", vbridge.value.ip + ":" + vbridge.value.port) - } else { - childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) - childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) - } + if (d) { + // Associate smartapp to bridge so user will be warned if trying to delete bridge + app.updateSetting("bridgeDevice", [type: "device.hueBridge", value: d.id]) + + d.completedSetup = true + log.debug "created ${d.displayName} with id ${d.deviceNetworkId}" + def childDevice = getChildDevice(d.deviceNetworkId) + updateBridgeStatus(childDevice) + childDevice.sendEvent(name: "idNumber", value: idNumber) + + + if (vbridge.value.ip && vbridge.value.port) { + if (vbridge.value.ip.contains(".")) { + childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port) + childDevice.updateDataValue("networkAddress", vbridge.value.ip + ":" + vbridge.value.port) + } else { + childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) + childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) + } + } else { + childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) + childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) + } } else { - childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) - childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) - } + log.error "Failed to create Hue Bridge device" + } } } else { log.debug "found ${d.displayName} with id $selectedHue already exists" From 9c8398b7a062070f616064d0442b525dc21a7441 Mon Sep 17 00:00:00 2001 From: Lars Finander Date: Mon, 29 Aug 2016 15:45:25 -0600 Subject: [PATCH 3/3] SSVD-2613 UX for Hue when adding lights is confusing -Split lights list in SmartApp into already added lights and new lights -Also fixed WWST-39 Sort list of bulbs by name during discovery --- .../hue-connect.src/hue-connect.groovy | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 415dd44..c83f9ed 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -133,14 +133,23 @@ def bulbDiscovery() { state.inBulbDiscovery = true def bridge = null if (selectedHue) { - bridge = getChildDevice(selectedHue) - subscribe(bridge, "bulbList", bulbListData) + bridge = getChildDevice(selectedHue) + subscribe(bridge, "bulbList", bulbListData) } - state.bridgeRefreshCount = 0 - def bulboptions = bulbsDiscovered() ?: [:] - def numFound = bulboptions.size() ?: 0 - if (numFound == 0) - app.updateSetting("selectedBulbs", "") + state.bridgeRefreshCount = 0 + def allLightsFound = bulbsDiscovered() ?: [:] + + // List lights currently not added to the user (editable) + def newLights = allLightsFound.findAll {getChildDevice(it.key) == null} ?: [:] + newLights = newLights.sort {it.value.toLowerCase()} + + // List lights already added to the user (not editable) + def existingLights = allLightsFound.findAll {getChildDevice(it.key) != null} ?: [:] + existingLights = existingLights.sort {it.value.toLowerCase()} + + def numFound = newLights.size() ?: 0 + if (numFound == 0) + app.updateSetting("selectedBulbs", "") if((bulbRefreshCount % 5) == 0) { discoverHueBulbs() @@ -148,14 +157,25 @@ def bulbDiscovery() { def selectedBridge = state.bridges.find { key, value -> value?.serialNumber?.equalsIgnoreCase(selectedHue) } def title = selectedBridge?.value?.name ?: "Find bridges" + // List of all lights previously added shown to user + def existingLightsDescription = "" + if (existingLights) { + existingLights.each { + if (existingLightsDescription.isEmpty()) { + existingLightsDescription += it.value + } else { + existingLightsDescription += ", ${it.value}" + } + } + } return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) { section("Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { - input "selectedBulbs", "enum", required:false, title:"Select Hue Lights (${numFound} found)", multiple:true, options:bulboptions + input "selectedBulbs", "enum", required:false, title:"Select Hue Lights to add (${numFound} found)", multiple:true, options:newLights + paragraph title: "Previously added Hue Lights (${existingLights.size()} added)", existingLightsDescription } section { href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true] - } } }