mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-08 05:31:56 +00:00
DVCSMP-1597 Philips HUE: Bloom and Strip lights need temperature control removed
-Added new device type for Hue lights that have color control but no temperature control (Bloom/Strip) -Add missing event to setLevel
This commit is contained in:
227
devicetypes/smartthings/hue-bloom.src/hue-bloom.groovy
Normal file
227
devicetypes/smartthings/hue-bloom.src/hue-bloom.groovy
Normal file
@@ -0,0 +1,227 @@
|
||||
/**
|
||||
* Hue Bloom
|
||||
*
|
||||
* Philips Hue Type "Color Light"
|
||||
*
|
||||
* Author: SmartThings
|
||||
*/
|
||||
|
||||
// for the UI
|
||||
metadata {
|
||||
// Automatically generated. Make future change here.
|
||||
definition (name: "Hue Bloom", namespace: "smartthings", author: "SmartThings") {
|
||||
capability "Switch Level"
|
||||
capability "Actuator"
|
||||
capability "Color Control"
|
||||
capability "Switch"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
|
||||
command "setAdjustedColor"
|
||||
command "reset"
|
||||
command "refresh"
|
||||
}
|
||||
|
||||
simulator {
|
||||
// TODO: define status and reply messages here
|
||||
}
|
||||
|
||||
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:"#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)"
|
||||
}
|
||||
tileAttribute ("device.level", key: "SECONDARY_CONTROL") {
|
||||
attributeState "level", label: 'Level ${currentValue}%'
|
||||
}
|
||||
tileAttribute ("device.color", key: "COLOR_CONTROL") {
|
||||
attributeState "color", action:"setAdjustedColor"
|
||||
}
|
||||
}
|
||||
|
||||
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.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
|
||||
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||
}
|
||||
|
||||
main(["rich-control"])
|
||||
details(["rich-control", "colorTempSliderControl", "colorTemp", "reset", "refresh"])
|
||||
}
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(description) {
|
||||
log.debug "parse() - $description"
|
||||
def results = []
|
||||
|
||||
def map = description
|
||||
if (description instanceof String) {
|
||||
log.debug "Hue Bulb stringToMap - ${map}"
|
||||
map = stringToMap(description)
|
||||
}
|
||||
|
||||
if (map?.name && map?.value) {
|
||||
results << createEvent(name: "${map?.name}", value: "${map?.value}")
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
// handle commands
|
||||
void on() {
|
||||
log.trace parent.on(this)
|
||||
sendEvent(name: "switch", value: "on")
|
||||
}
|
||||
|
||||
void off() {
|
||||
log.trace parent.off(this)
|
||||
sendEvent(name: "switch", value: "off")
|
||||
}
|
||||
|
||||
void nextLevel() {
|
||||
def level = device.latestValue("level") as Integer ?: 0
|
||||
if (level <= 100) {
|
||||
level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer
|
||||
}
|
||||
else {
|
||||
level = 25
|
||||
}
|
||||
setLevel(level)
|
||||
}
|
||||
|
||||
void setLevel(percent) {
|
||||
log.debug "Executing 'setLevel'"
|
||||
if (verifyPercent(percent)) {
|
||||
parent.setLevel(this, percent)
|
||||
sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%")
|
||||
sendEvent(name: "switch", value: "on")
|
||||
}
|
||||
}
|
||||
|
||||
void setSaturation(percent) {
|
||||
log.debug "Executing 'setSaturation'"
|
||||
if (verifyPercent(percent)) {
|
||||
parent.setSaturation(this, percent)
|
||||
sendEvent(name: "saturation", value: percent, displayed: false)
|
||||
}
|
||||
}
|
||||
|
||||
void setHue(percent) {
|
||||
log.debug "Executing 'setHue'"
|
||||
if (verifyPercent(percent)) {
|
||||
parent.setHue(this, percent)
|
||||
sendEvent(name: "hue", value: percent, displayed: false)
|
||||
}
|
||||
}
|
||||
|
||||
void setColor(value) {
|
||||
log.debug "setColor: ${value}, $this"
|
||||
def events = []
|
||||
def validValues = [:]
|
||||
|
||||
if (verifyPercent(value.hue)) {
|
||||
events << createEvent(name: "hue", value: value.hue, displayed: false)
|
||||
validValues.hue = value.hue
|
||||
}
|
||||
if (verifyPercent(value.saturation)) {
|
||||
events << createEvent(name: "saturation", value: value.saturation, displayed: false)
|
||||
validValues.saturation = value.saturation
|
||||
}
|
||||
if (value.hex != null) {
|
||||
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
|
||||
events << createEvent(name: "color", value: value.hex)
|
||||
validValues.hex = value.hex
|
||||
} else {
|
||||
log.warn "$value.hex is not a valid color"
|
||||
}
|
||||
}
|
||||
if (verifyPercent(value.level)) {
|
||||
events << createEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")
|
||||
validValues.level = value.level
|
||||
}
|
||||
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
|
||||
events << createEvent(name: "switch", value: "off")
|
||||
validValues.switch = "off"
|
||||
} else {
|
||||
events << createEvent(name: "switch", value: "on")
|
||||
validValues.switch = "on"
|
||||
}
|
||||
if (!events.isEmpty()) {
|
||||
parent.setColor(this, validValues)
|
||||
}
|
||||
events.each {
|
||||
sendEvent(it)
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
log.debug "Executing 'reset'"
|
||||
def value = [level:100, saturation:56, hue:23]
|
||||
setAdjustedColor(value)
|
||||
parent.poll()
|
||||
}
|
||||
|
||||
void setAdjustedColor(value) {
|
||||
if (value) {
|
||||
log.trace "setAdjustedColor: ${value}"
|
||||
def adjusted = value + [:]
|
||||
adjusted.hue = adjustOutgoingHue(value.hue)
|
||||
// Needed because color picker always sends 100
|
||||
adjusted.level = null
|
||||
setColor(adjusted)
|
||||
} else {
|
||||
log.warn "Invalid color input"
|
||||
}
|
||||
}
|
||||
|
||||
void setColorTemperature(value) {
|
||||
if (value) {
|
||||
log.trace "setColorTemperature: ${value}k"
|
||||
parent.setColorTemperature(this, value)
|
||||
sendEvent(name: "colorTemperature", value: value)
|
||||
sendEvent(name: "switch", value: "on")
|
||||
} else {
|
||||
log.warn "Invalid color temperature"
|
||||
}
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
log.debug "Executing 'refresh'"
|
||||
parent.manualRefresh()
|
||||
}
|
||||
|
||||
def adjustOutgoingHue(percent) {
|
||||
def adjusted = percent
|
||||
if (percent > 31) {
|
||||
if (percent < 63.0) {
|
||||
adjusted = percent + (7 * (percent -30 ) / 32)
|
||||
}
|
||||
else if (percent < 73.0) {
|
||||
adjusted = 69 + (5 * (percent - 62) / 10)
|
||||
}
|
||||
else {
|
||||
adjusted = percent + (2 * (100 - percent) / 28)
|
||||
}
|
||||
}
|
||||
log.info "percent: $percent, adjusted: $adjusted"
|
||||
adjusted
|
||||
}
|
||||
|
||||
def verifyPercent(percent) {
|
||||
if (percent == null)
|
||||
return false
|
||||
else if (percent >= 0 && percent <= 100) {
|
||||
return true
|
||||
} else {
|
||||
log.warn "$percent is not 0-100"
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* Hue Bulb
|
||||
*
|
||||
* Philips Hue Type "Extended Color Light"
|
||||
*
|
||||
* Author: SmartThings
|
||||
*/
|
||||
|
||||
@@ -69,11 +71,13 @@ metadata {
|
||||
def parse(description) {
|
||||
log.debug "parse() - $description"
|
||||
def results = []
|
||||
|
||||
def map = description
|
||||
if (description instanceof String) {
|
||||
log.debug "Hue Bulb stringToMap - ${map}"
|
||||
map = stringToMap(description)
|
||||
}
|
||||
|
||||
if (map?.name && map?.value) {
|
||||
results << createEvent(name: "${map?.name}", value: "${map?.value}")
|
||||
}
|
||||
@@ -229,4 +233,4 @@ def verifyPercent(percent) {
|
||||
log.warn "$percent is not 0-100"
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* Hue Lux Bulb
|
||||
*
|
||||
* Philips Hue Type "Dimmable Light"
|
||||
*
|
||||
* Author: SmartThings
|
||||
*/
|
||||
// for the UI
|
||||
@@ -68,12 +70,12 @@ def parse(description) {
|
||||
|
||||
// handle commands
|
||||
void on() {
|
||||
parent.on(this)
|
||||
log.trace parent.on(this)
|
||||
sendEvent(name: "switch", value: "on")
|
||||
}
|
||||
|
||||
void off() {
|
||||
parent.off(this)
|
||||
log.trace parent.off(this)
|
||||
sendEvent(name: "switch", value: "off")
|
||||
}
|
||||
|
||||
@@ -82,6 +84,7 @@ void setLevel(percent) {
|
||||
if (percent != null && percent >= 0 && percent <= 100) {
|
||||
parent.setLevel(this, percent)
|
||||
sendEvent(name: "level", value: percent)
|
||||
sendEvent(name: "switch", value: "on")
|
||||
} else {
|
||||
log.warn "$percent is not 0-100"
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ def bulbListHandler(hub, data = "") {
|
||||
def object = new groovy.json.JsonSlurper().parseText(data)
|
||||
object.each { k,v ->
|
||||
if (v instanceof Map)
|
||||
bulbs[k] = [id: k, name: v.name, type: v.type, hub:hub]
|
||||
bulbs[k] = [id: k, name: v.name, type: v.type, modelid: v.modelid, hub:hub]
|
||||
}
|
||||
}
|
||||
def bridge = null
|
||||
@@ -300,6 +300,40 @@ def bulbListHandler(hub, data = "") {
|
||||
return msg
|
||||
}
|
||||
|
||||
private upgradeDeviceType(device, newHueType) {
|
||||
def deviceType = getDeviceType(newHueType)
|
||||
|
||||
// Automatically change users Hue bulbs to correct device types
|
||||
if (deviceType && !(device?.typeName?.equalsIgnoreCase(deviceType))) {
|
||||
log.debug "Update device type: \"$device.label\" ${device?.typeName}->$deviceType"
|
||||
device.setDeviceType(deviceType)
|
||||
}
|
||||
}
|
||||
|
||||
private getDeviceType(hueType) {
|
||||
// Determine ST device type based on Hue classification of light
|
||||
if (hueType?.equalsIgnoreCase("Dimmable light"))
|
||||
return "Hue Lux Bulb"
|
||||
else if (hueType?.equalsIgnoreCase("Extended Color Light"))
|
||||
return "Hue Bulb"
|
||||
else if (hueType?.equalsIgnoreCase("Color Light"))
|
||||
return "Hue Bloom"
|
||||
else
|
||||
return null
|
||||
}
|
||||
|
||||
private addChildBulb(dni, hueType, name, hub, update=false, device = null) {
|
||||
def deviceType = getDeviceType(hueType)
|
||||
|
||||
if (deviceType) {
|
||||
return addChildDevice("smartthings", deviceType, dni, hub, ["label": name])
|
||||
}
|
||||
else {
|
||||
log.warn "Device type $hueType not supported"
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
def addBulbs() {
|
||||
def bulbs = getHueBulbs()
|
||||
selectedBulbs?.each { dni ->
|
||||
@@ -309,11 +343,7 @@ def addBulbs() {
|
||||
if (bulbs instanceof java.util.Map) {
|
||||
newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
|
||||
if (newHueBulb != null) {
|
||||
if (newHueBulb?.value?.type?.equalsIgnoreCase("Dimmable light") ) {
|
||||
d = addChildDevice("smartthings", "Hue Lux Bulb", dni, newHueBulb?.value.hub, ["label":newHueBulb?.value.name])
|
||||
} else {
|
||||
d = addChildDevice("smartthings", "Hue Bulb", dni, newHueBulb?.value.hub, ["label":newHueBulb?.value.name])
|
||||
}
|
||||
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub)
|
||||
log.debug "created ${d.displayName} with id $dni"
|
||||
d.refresh()
|
||||
} else {
|
||||
@@ -322,16 +352,15 @@ def addBulbs() {
|
||||
} else {
|
||||
//backwards compatable
|
||||
newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni }
|
||||
d = addChildDevice("smartthings", "Hue Bulb", dni, newHueBulb?.hub, ["label":newHueBulb?.name])
|
||||
d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub)
|
||||
d.refresh()
|
||||
}
|
||||
} else {
|
||||
log.debug "found ${d.displayName} with id $dni already exists, type: '$d.typeName'"
|
||||
if (bulbs instanceof java.util.Map) {
|
||||
// Update device type if incorrect
|
||||
def newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
|
||||
if (newHueBulb?.value?.type?.equalsIgnoreCase("Dimmable light") && d.typeName == "Hue Bulb") {
|
||||
d.setDeviceType("Hue Lux Bulb")
|
||||
}
|
||||
upgradeDeviceType(d, newHueBulb?.value?.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -473,7 +502,7 @@ def locationHandler(evt) {
|
||||
def bulbs = getHueBulbs()
|
||||
log.debug "Adding bulbs to state!"
|
||||
body.each { k,v ->
|
||||
bulbs[k] = [id: k, name: v.name, type: v.type, hub:parsedEvent.hub]
|
||||
bulbs[k] = [id: k, name: v.name, type: v.type, modelid: v.modelid, hub:parsedEvent.hub]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -836,7 +865,7 @@ def convertBulbListToMap() {
|
||||
if (state.bulbs instanceof java.util.List) {
|
||||
def map = [:]
|
||||
state.bulbs.unique {it.id}.each { bulb ->
|
||||
map << ["${bulb.id}":["id":bulb.id, "name":bulb.name, "hub":bulb.hub]]
|
||||
map << ["${bulb.id}":["id":bulb.id, "name":bulb.name, "type": bulb.type, "modelid": bulb.modelid, "hub":bulb.hub]]
|
||||
}
|
||||
state.bulbs = map
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user