mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-17 21:03:30 +00:00
Merge pull request #106 from juano2310/PR_hue
Hue update to match the new UI
This commit is contained in:
@@ -15,19 +15,27 @@ metadata {
|
|||||||
// TODO: define status and reply messages here
|
// TODO: define status and reply messages here
|
||||||
}
|
}
|
||||||
|
|
||||||
tiles {
|
tiles(scale: 2) {
|
||||||
|
multiAttributeTile(name:"rich-control"){
|
||||||
|
tileAttribute ("", key: "PRIMARY_CONTROL") {
|
||||||
|
attributeState "default", label: "Hue Bridge", action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#F3C200"
|
||||||
|
}
|
||||||
|
tileAttribute ("serialNumber", key: "SECONDARY_CONTROL") {
|
||||||
|
attributeState "default", label:'SN: ${currentValue}'
|
||||||
|
}
|
||||||
|
}
|
||||||
standardTile("icon", "icon", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) {
|
standardTile("icon", "icon", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) {
|
||||||
state "default", label: "Hue Bridge", action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#FFFFFF"
|
state "default", label: "Hue Bridge", action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#FFFFFF"
|
||||||
}
|
}
|
||||||
valueTile("serialNumber", "device.serialNumber", decoration: "flat", height: 1, width: 2, inactiveLabel: false) {
|
valueTile("serialNumber", "device.serialNumber", decoration: "flat", height: 1, width: 2, inactiveLabel: false) {
|
||||||
state "default", label:'SN: ${currentValue}'
|
state "default", label:'SN: ${currentValue}'
|
||||||
}
|
}
|
||||||
valueTile("networkAddress", "device.networkAddress", decoration: "flat", height: 1, width: 2, inactiveLabel: false) {
|
valueTile("networkAddress", "device.networkAddress", decoration: "flat", height: 2, width: 4, inactiveLabel: false) {
|
||||||
state "default", label:'${currentValue}', height: 1, width: 2, inactiveLabel: false
|
state "default", label:'${currentValue}', height: 1, width: 2, inactiveLabel: false
|
||||||
}
|
}
|
||||||
|
|
||||||
main (["icon"])
|
main (["icon"])
|
||||||
details(["networkAddress","serialNumber"])
|
details(["rich-control", "networkAddress"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +44,6 @@ def parse(description) {
|
|||||||
log.debug "Parsing '${description}'"
|
log.debug "Parsing '${description}'"
|
||||||
def results = []
|
def results = []
|
||||||
def result = parent.parse(this, description)
|
def result = parent.parse(this, description)
|
||||||
|
|
||||||
if (result instanceof physicalgraph.device.HubAction){
|
if (result instanceof physicalgraph.device.HubAction){
|
||||||
log.trace "HUE BRIDGE HubAction received -- DOES THIS EVER HAPPEN?"
|
log.trace "HUE BRIDGE HubAction received -- DOES THIS EVER HAPPEN?"
|
||||||
results << result
|
results << result
|
||||||
@@ -44,32 +51,30 @@ def parse(description) {
|
|||||||
//do nothing
|
//do nothing
|
||||||
log.trace "HUE BRIDGE was updated"
|
log.trace "HUE BRIDGE was updated"
|
||||||
} else {
|
} else {
|
||||||
log.trace "HUE BRIDGE, OTHER"
|
|
||||||
def map = description
|
def map = description
|
||||||
if (description instanceof String) {
|
if (description instanceof String) {
|
||||||
map = stringToMap(description)
|
map = stringToMap(description)
|
||||||
}
|
}
|
||||||
if (map?.name && map?.value) {
|
if (map?.name && map?.value) {
|
||||||
log.trace "HUE BRIDGE, GENERATING EVENT: $map.name: $map.value"
|
log.trace "HUE BRIDGE, GENERATING EVENT: $map.name: $map.value"
|
||||||
results << createEvent(name: "${map?.name}", value: "${map?.value}")
|
results << createEvent(name: "${map.name}", value: "${map.value}")
|
||||||
}
|
} else {
|
||||||
else {
|
log.trace "Parsing description"
|
||||||
log.trace "HUE BRIDGE, OTHER"
|
|
||||||
def msg = parseLanMessage(description)
|
def msg = parseLanMessage(description)
|
||||||
if (msg.body) {
|
if (msg.body) {
|
||||||
def contentType = msg.headers["Content-Type"]
|
def contentType = msg.headers["Content-Type"]
|
||||||
if (contentType?.contains("json")) {
|
if (contentType?.contains("json")) {
|
||||||
def bulbs = new groovy.json.JsonSlurper().parseText(msg.body)
|
def bulbs = new groovy.json.JsonSlurper().parseText(msg.body)
|
||||||
if (bulbs.state) {
|
if (bulbs.state) {
|
||||||
log.warn "NOT PROCESSED: $msg.body"
|
log.info "Bridge response: $msg.body"
|
||||||
}
|
} else {
|
||||||
else {
|
// Sending Bulbs List to parent"
|
||||||
log.debug "HUE BRIDGE, GENERATING BULB LIST EVENT: $bulbs"
|
if (parent.state.inBulbDiscovery)
|
||||||
sendEvent(name: "bulbList", value: device.hub.id, isStateChange: true, data: bulbs, displayed: false)
|
log.info parent.bulbListHandler(device.hub.id, msg.body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (contentType?.contains("xml")) {
|
else if (contentType?.contains("xml")) {
|
||||||
log.debug "HUE BRIDGE, SWALLOWING BRIDGE DESCRIPTION RESPONSE -- BRIDGE ALREADY PRESENT"
|
log.debug "HUE BRIDGE ALREADY PRESENT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Hue Bulb
|
* Hue Bulb
|
||||||
*
|
*
|
||||||
@@ -49,7 +50,6 @@ metadata {
|
|||||||
|
|
||||||
main(["switch"])
|
main(["switch"])
|
||||||
details(["switch", "levelSliderControl", "rgbSelector", "refresh", "reset"])
|
details(["switch", "levelSliderControl", "rgbSelector", "refresh", "reset"])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse events into attributes
|
// parse events into attributes
|
||||||
@@ -68,13 +68,13 @@ def parse(description) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle commands
|
// handle commands
|
||||||
def on(transition = "4") {
|
def on() {
|
||||||
log.trace parent.on(this,transition)
|
log.trace parent.on(this)
|
||||||
sendEvent(name: "switch", value: "on")
|
sendEvent(name: "switch", value: "on")
|
||||||
}
|
}
|
||||||
|
|
||||||
def off(transition = "4") {
|
def off() {
|
||||||
log.trace parent.off(this,transition)
|
log.trace parent.off(this)
|
||||||
sendEvent(name: "switch", value: "off")
|
sendEvent(name: "switch", value: "off")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,9 +107,9 @@ def setHue(percent) {
|
|||||||
sendEvent(name: "hue", value: percent)
|
sendEvent(name: "hue", value: percent)
|
||||||
}
|
}
|
||||||
|
|
||||||
def setColor(value,alert = "none",transition = 4) {
|
def setColor(value) {
|
||||||
log.debug "setColor: ${value}, $this"
|
log.debug "setColor: ${value}, $this"
|
||||||
parent.setColor(this, value, alert, transition)
|
parent.setColor(this, value)
|
||||||
if (value.hue) { sendEvent(name: "hue", value: value.hue)}
|
if (value.hue) { sendEvent(name: "hue", value: value.hue)}
|
||||||
if (value.saturation) { sendEvent(name: "saturation", value: value.saturation)}
|
if (value.saturation) { sendEvent(name: "saturation", value: value.saturation)}
|
||||||
if (value.hex) { sendEvent(name: "color", value: value.hex)}
|
if (value.hex) { sendEvent(name: "color", value: value.hex)}
|
||||||
|
|||||||
@@ -20,23 +20,40 @@ metadata {
|
|||||||
// TODO: define status and reply messages here
|
// TODO: define status and reply messages here
|
||||||
}
|
}
|
||||||
|
|
||||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
tiles(scale: 2) {
|
||||||
state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821"
|
multiAttributeTile(name:"rich-control", type: "lighting", canChangeIcon: true){
|
||||||
state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff"
|
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
||||||
}
|
attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
|
||||||
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
|
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||||
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
|
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"
|
||||||
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range:"(0..100)") {
|
}
|
||||||
state "level", action:"switch level.setLevel"
|
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
|
||||||
}
|
attributeState "level", action:"switch level.setLevel", range:"(0..100)"
|
||||||
valueTile("level", "device.level", inactiveLabel: false, decoration: "flat") {
|
}
|
||||||
state "level", label: 'Level ${currentValue}%'
|
tileAttribute ("device.level", key: "SECONDARY_CONTROL") {
|
||||||
}
|
attributeState "level", label: 'Level ${currentValue}%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
main(["switch"])
|
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||||
details(["switch", "levelSliderControl", "refresh"])
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
standardTile("refresh", "device.switch", inactiveLabel: false, height: 2, width: 2, decoration: "flat") {
|
||||||
|
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||||
|
}
|
||||||
|
|
||||||
|
main(["switch"])
|
||||||
|
details(["rich-control", "refresh"])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse events into attributes
|
// parse events into attributes
|
||||||
|
|||||||
@@ -64,10 +64,12 @@ def bridgeDiscovery(params=[:])
|
|||||||
def options = bridges ?: []
|
def options = bridges ?: []
|
||||||
def numFound = options.size() ?: 0
|
def numFound = options.size() ?: 0
|
||||||
|
|
||||||
if(!state.subscribe) {
|
if (numFound == 0 && state.bridgeRefreshCount > 5) {
|
||||||
subscribe(location, null, locationHandler, [filterEvents:false])
|
log.trace "Cleaning old bridges memory"
|
||||||
state.subscribe = true
|
atomicState.bridges = [:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subscribe(location, null, locationHandler, [filterEvents:false])
|
||||||
|
|
||||||
//bridge discovery request every 15 //25 seconds
|
//bridge discovery request every 15 //25 seconds
|
||||||
if((bridgeRefreshCount % 5) == 0) {
|
if((bridgeRefreshCount % 5) == 0) {
|
||||||
@@ -117,7 +119,8 @@ def bulbDiscovery()
|
|||||||
int bulbRefreshCount = !state.bulbRefreshCount ? 0 : state.bulbRefreshCount as int
|
int bulbRefreshCount = !state.bulbRefreshCount ? 0 : state.bulbRefreshCount as int
|
||||||
state.bulbRefreshCount = bulbRefreshCount + 1
|
state.bulbRefreshCount = bulbRefreshCount + 1
|
||||||
def refreshInterval = 3
|
def refreshInterval = 3
|
||||||
|
state.inBulbDiscovery = true
|
||||||
|
state.bridgeRefreshCount = 0
|
||||||
def options = bulbsDiscovered() ?: []
|
def options = bulbsDiscovered() ?: []
|
||||||
def numFound = options.size() ?: 0
|
def numFound = options.size() ?: 0
|
||||||
|
|
||||||
@@ -194,29 +197,30 @@ Map bridgesDiscovered() {
|
|||||||
|
|
||||||
Map bulbsDiscovered() {
|
Map bulbsDiscovered() {
|
||||||
def bulbs = getHueBulbs()
|
def bulbs = getHueBulbs()
|
||||||
def map = [:]
|
def bulbmap = [:]
|
||||||
if (bulbs instanceof java.util.Map) {
|
if (bulbs instanceof java.util.Map) {
|
||||||
bulbs.each {
|
bulbs.each {
|
||||||
def value = "${it?.value?.name}"
|
def value = "${it.value.name}"
|
||||||
def key = app.id +"/"+ it?.value?.id
|
def key = app.id +"/"+ it.value.id
|
||||||
map["${key}"] = value
|
bulbmap["${key}"] = value
|
||||||
}
|
}
|
||||||
} else { //backwards compatable
|
} else { //backwards compatable
|
||||||
bulbs.each {
|
bulbs.each {
|
||||||
def value = "${it?.name}"
|
def value = "${it.name}"
|
||||||
def key = app.id +"/"+ it?.id
|
def key = app.id +"/"+ it.id
|
||||||
map["${key}"] = value
|
logg += "$value - $key, "
|
||||||
|
bulbmap["${key}"] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
map
|
bulbmap
|
||||||
}
|
}
|
||||||
|
|
||||||
def getHueBulbs() {
|
def getHueBulbs() {
|
||||||
state.bulbs = state.bulbs ?: [:]
|
atomicState.bulbs = atomicState.bulbs ?: [:]
|
||||||
}
|
}
|
||||||
|
|
||||||
def getHueBridges() {
|
def getHueBridges() {
|
||||||
state.bridges = state.bridges ?: [:]
|
atomicState.bridges = atomicState.bridges ?: [:]
|
||||||
}
|
}
|
||||||
|
|
||||||
def getVerifiedHueBridges() {
|
def getVerifiedHueBridges() {
|
||||||
@@ -237,18 +241,10 @@ def updated() {
|
|||||||
|
|
||||||
def initialize() {
|
def initialize() {
|
||||||
log.debug "Initializing"
|
log.debug "Initializing"
|
||||||
state.subscribe = false
|
state.inBulbDiscovery = false
|
||||||
state.bridgeSelectedOverride = false
|
|
||||||
def bridge = null
|
|
||||||
|
|
||||||
if (selectedHue) {
|
if (selectedHue) {
|
||||||
addBridge()
|
addBridge()
|
||||||
bridge = getChildDevice(selectedHue)
|
addBulbs()
|
||||||
subscribe(bridge, "bulbList", bulbListHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedBulbs) {
|
|
||||||
addBulbs()
|
|
||||||
doDeviceSync()
|
doDeviceSync()
|
||||||
runEvery5Minutes("doDeviceSync")
|
runEvery5Minutes("doDeviceSync")
|
||||||
}
|
}
|
||||||
@@ -262,23 +258,27 @@ def manualRefresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def uninstalled(){
|
def uninstalled(){
|
||||||
state.bridges = [:]
|
atomicState.bridges = [:]
|
||||||
state.subscribe = false
|
state.username = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles events to add new bulbs
|
// Handles events to add new bulbs
|
||||||
def bulbListHandler(evt) {
|
def bulbListHandler(hub, data) {
|
||||||
def bulbs = [:]
|
def msg = "Bulbs list not processed. Only while in settings menu."
|
||||||
log.trace "Adding bulbs to state..."
|
if (state.inBulbDiscovery) {
|
||||||
state.bridgeProcessedLightList = true
|
def bulbs = [:]
|
||||||
evt.jsonData.each { k,v ->
|
def logg = ""
|
||||||
log.trace "$k: $v"
|
log.trace "Adding bulbs to state..."
|
||||||
if (v instanceof Map) {
|
state.bridgeProcessedLightList = true
|
||||||
bulbs[k] = [id: k, name: v.name, type: v.type, hub:evt.value]
|
def object = new groovy.json.JsonSlurper().parseText(data)
|
||||||
}
|
object.each { k,v ->
|
||||||
}
|
if (v instanceof Map)
|
||||||
state.bulbs = bulbs
|
bulbs[k] = [id: k, name: v.name, type: v.type, hub:hub]
|
||||||
log.info "${bulbs.size()} bulbs found"
|
}
|
||||||
|
atomicState.bulbs = bulbs
|
||||||
|
msg = "${bulbs.size()} bulbs found. $atomicState.bulbs"
|
||||||
|
}
|
||||||
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
def addBulbs() {
|
def addBulbs() {
|
||||||
@@ -342,12 +342,17 @@ def addBridge() {
|
|||||||
def childDevice = getChildDevice(d.deviceNetworkId)
|
def childDevice = getChildDevice(d.deviceNetworkId)
|
||||||
childDevice.sendEvent(name: "serialNumber", value: vbridge.value.serialNumber)
|
childDevice.sendEvent(name: "serialNumber", value: vbridge.value.serialNumber)
|
||||||
if (vbridge.value.ip && vbridge.value.port) {
|
if (vbridge.value.ip && vbridge.value.port) {
|
||||||
if (vbridge.value.ip.contains("."))
|
if (vbridge.value.ip.contains(".")) {
|
||||||
childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port)
|
childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port)
|
||||||
else
|
childDevice.updateDataValue("networkAddress", vbridge.value.ip + ":" + vbridge.value.port)
|
||||||
|
} else {
|
||||||
childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port))
|
childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port))
|
||||||
} else
|
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.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress))
|
||||||
|
childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug "found ${d.displayName} with id $selectedHue already exists"
|
log.debug "found ${d.displayName} with id $selectedHue already exists"
|
||||||
@@ -398,7 +403,10 @@ def locationHandler(evt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
networkAddress = d.latestState('networkAddress').stringValue
|
if (d.getDeviceDataByName("networkAddress"))
|
||||||
|
networkAddress = d.getDeviceDataByName("networkAddress")
|
||||||
|
else
|
||||||
|
networkAddress = d.latestState('networkAddress').stringValue
|
||||||
log.trace "Host: $host - $networkAddress"
|
log.trace "Host: $host - $networkAddress"
|
||||||
if(host != networkAddress) {
|
if(host != networkAddress) {
|
||||||
log.debug "Device's port or ip changed for device $d..."
|
log.debug "Device's port or ip changed for device $d..."
|
||||||
@@ -406,6 +414,7 @@ def locationHandler(evt) {
|
|||||||
dstate.port = port
|
dstate.port = port
|
||||||
dstate.name = "Philips hue ($ip)"
|
dstate.name = "Philips hue ($ip)"
|
||||||
d.sendEvent(name:"networkAddress", value: host)
|
d.sendEvent(name:"networkAddress", value: host)
|
||||||
|
d.updateDataValue("networkAddress", host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,15 +445,6 @@ def locationHandler(evt) {
|
|||||||
} else if (body.error != null) {
|
} else if (body.error != null) {
|
||||||
//TODO: handle retries...
|
//TODO: handle retries...
|
||||||
log.error "ERROR: application/json ${body.error}"
|
log.error "ERROR: application/json ${body.error}"
|
||||||
} else {
|
|
||||||
//GET /api/${state.username}/lights response (application/json)
|
|
||||||
if (!body?.state?.on) { //check if first time poll made it here by mistake
|
|
||||||
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]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -454,17 +454,13 @@ def locationHandler(evt) {
|
|||||||
|
|
||||||
def doDeviceSync(){
|
def doDeviceSync(){
|
||||||
log.trace "Doing Hue Device Sync!"
|
log.trace "Doing Hue Device Sync!"
|
||||||
|
|
||||||
//shrink the large bulb lists
|
|
||||||
convertBulbListToMap()
|
convertBulbListToMap()
|
||||||
|
|
||||||
poll()
|
poll()
|
||||||
|
try {
|
||||||
if(!state.subscribe) {
|
|
||||||
subscribe(location, null, locationHandler, [filterEvents:false])
|
subscribe(location, null, locationHandler, [filterEvents:false])
|
||||||
state.subscribe = true
|
} catch (all) {
|
||||||
}
|
log.trace "Subscription already exist"
|
||||||
|
}
|
||||||
discoverBridges()
|
discoverBridges()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,40 +472,45 @@ def parse(childDevice, description) {
|
|||||||
def parsedEvent = parseLanMessage(description)
|
def parsedEvent = parseLanMessage(description)
|
||||||
if (parsedEvent.headers && parsedEvent.body) {
|
if (parsedEvent.headers && parsedEvent.body) {
|
||||||
def headerString = parsedEvent.headers.toString()
|
def headerString = parsedEvent.headers.toString()
|
||||||
|
def bodyString = parsedEvent.body.toString()
|
||||||
if (headerString?.contains("json")) {
|
if (headerString?.contains("json")) {
|
||||||
def body = new groovy.json.JsonSlurper().parseText(parsedEvent.body)
|
def body
|
||||||
if (body instanceof java.util.HashMap)
|
try {
|
||||||
{ //poll response
|
body = new groovy.json.JsonSlurper().parseText(bodyString)
|
||||||
|
} catch (all) {
|
||||||
|
log.warn "Parsing Body failed - trying again..."
|
||||||
|
poll()
|
||||||
|
}
|
||||||
|
if (body instanceof java.util.HashMap) {
|
||||||
|
//poll response
|
||||||
def bulbs = getChildDevices()
|
def bulbs = getChildDevices()
|
||||||
//for each bulb
|
|
||||||
for (bulb in body) {
|
for (bulb in body) {
|
||||||
def d = bulbs.find{it.deviceNetworkId == "${app.id}/${bulb.key}"}
|
def d = bulbs.find{it.deviceNetworkId == "${app.id}/${bulb.key}"}
|
||||||
if (d) {
|
if (d) {
|
||||||
if (bulb.value.state?.reachable) {
|
if (bulb.value.state?.reachable) {
|
||||||
sendEvent(d.deviceNetworkId, [name: "switch", value: bulb.value?.state?.on ? "on" : "off"])
|
sendEvent(d.deviceNetworkId, [name: "switch", value: bulb.value?.state?.on ? "on" : "off"])
|
||||||
sendEvent(d.deviceNetworkId, [name: "level", value: Math.round(bulb.value.state.bri * 100 / 255)])
|
sendEvent(d.deviceNetworkId, [name: "level", value: Math.round(bulb.value.state.bri * 100 / 255)])
|
||||||
if (bulb.value.state.sat) {
|
if (bulb.value.state.sat) {
|
||||||
def hue = Math.min(Math.round(bulb.value.state.hue * 100 / 65535), 65535) as int
|
def hue = Math.min(Math.round(bulb.value.state.hue * 100 / 65535), 65535) as int
|
||||||
def sat = Math.round(bulb.value.state.sat * 100 / 255) as int
|
def sat = Math.round(bulb.value.state.sat * 100 / 255) as int
|
||||||
def hex = colorUtil.hslToHex(hue, sat)
|
def hex = colorUtil.hslToHex(hue, sat)
|
||||||
sendEvent(d.deviceNetworkId, [name: "color", value: hex])
|
sendEvent(d.deviceNetworkId, [name: "color", value: hex])
|
||||||
sendEvent(d.deviceNetworkId, [name: "hue", value: hue])
|
sendEvent(d.deviceNetworkId, [name: "hue", value: hue])
|
||||||
sendEvent(d.deviceNetworkId, [name: "saturation", value: sat])
|
sendEvent(d.deviceNetworkId, [name: "saturation", value: sat])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendEvent(d.deviceNetworkId, [name: "switch", value: "off"])
|
sendEvent(d.deviceNetworkId, [name: "switch", value: "off"])
|
||||||
sendEvent(d.deviceNetworkId, [name: "level", value: 100])
|
sendEvent(d.deviceNetworkId, [name: "level", value: 100])
|
||||||
if (bulb.value.state.sat) {
|
if (bulb.value.state.sat) {
|
||||||
def hue = 23
|
def hue = 23
|
||||||
def sat = 56
|
def sat = 56
|
||||||
def hex = colorUtil.hslToHex(23, 56)
|
def hex = colorUtil.hslToHex(23, 56)
|
||||||
sendEvent(d.deviceNetworkId, [name: "color", value: hex])
|
sendEvent(d.deviceNetworkId, [name: "color", value: hex])
|
||||||
sendEvent(d.deviceNetworkId, [name: "hue", value: hue])
|
sendEvent(d.deviceNetworkId, [name: "hue", value: hue])
|
||||||
sendEvent(d.deviceNetworkId, [name: "saturation", value: sat])
|
sendEvent(d.deviceNetworkId, [name: "saturation", value: sat])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -566,18 +567,18 @@ def parse(childDevice, description) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def on(childDevice, transition = 4) {
|
def on(childDevice, transition_deprecated = 0) {
|
||||||
log.debug "Executing 'on'"
|
log.debug "Executing 'on'"
|
||||||
// Assume bulb is off if no current state is found for level to avoid bulbs getting stuck in off after initial discovery
|
def percent = childDevice.device?.currentValue("level") as Integer
|
||||||
def percent = childDevice.device?.currentValue("level") as Integer ?: 0
|
|
||||||
def level = Math.min(Math.round(percent * 255 / 100), 255)
|
def level = Math.min(Math.round(percent * 255 / 100), 255)
|
||||||
put("lights/${getId(childDevice)}/state", [bri: level, on: true, transitiontime: transition])
|
put("lights/${getId(childDevice)}/state", [bri: level, on: true])
|
||||||
return "level: $percent"
|
return "level: $percent"
|
||||||
}
|
}
|
||||||
|
|
||||||
def off(childDevice, transition = 4) {
|
def off(childDevice, transition_deprecated = 0) {
|
||||||
log.debug "Executing 'off'"
|
log.debug "Executing 'off'"
|
||||||
put("lights/${getId(childDevice)}/state", [on: false, transitiontime: transition])
|
put("lights/${getId(childDevice)}/state", [on: false])
|
||||||
|
return "level: 0"
|
||||||
}
|
}
|
||||||
|
|
||||||
def setLevel(childDevice, percent) {
|
def setLevel(childDevice, percent) {
|
||||||
@@ -598,19 +599,21 @@ def setHue(childDevice, percent) {
|
|||||||
put("lights/${getId(childDevice)}/state", [hue: level])
|
put("lights/${getId(childDevice)}/state", [hue: level])
|
||||||
}
|
}
|
||||||
|
|
||||||
def setColor(childDevice, color, alert = "none", transition = 4) {
|
def setColor(childDevice, huesettings, alert_deprecated = "", transition_deprecated = 0) {
|
||||||
log.debug "Executing 'setColor($color)'"
|
log.debug "Executing 'setColor($huesettings)'"
|
||||||
def hue = Math.min(Math.round(color.hue * 65535 / 100), 65535)
|
def hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535)
|
||||||
def sat = Math.min(Math.round(color.saturation * 255 / 100), 255)
|
def 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 = [sat: sat, hue: hue, alert: alert, transitiontime: transition]
|
||||||
if (color.level != null) {
|
if (huesettings.level != null) {
|
||||||
value.bri = Math.min(Math.round(color.level * 255 / 100), 255)
|
value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255)
|
||||||
value.on = value.bri > 0
|
value.on = value.bri > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color.switch) {
|
if (huesettings.switch) {
|
||||||
value.on = color.switch == "on"
|
value.on = huesettings.switch == "on"
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug "sending command $value"
|
log.debug "sending command $value"
|
||||||
@@ -640,11 +643,15 @@ private getId(childDevice) {
|
|||||||
private poll() {
|
private poll() {
|
||||||
def host = getBridgeIP()
|
def host = getBridgeIP()
|
||||||
def uri = "/api/${state.username}/lights/"
|
def uri = "/api/${state.username}/lights/"
|
||||||
log.debug "GET: $host$uri"
|
try {
|
||||||
sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1
|
sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1
|
||||||
HOST: ${host}
|
HOST: ${host}
|
||||||
|
|
||||||
""", physicalgraph.device.Protocol.LAN, selectedHue))
|
""", physicalgraph.device.Protocol.LAN, selectedHue))
|
||||||
|
} catch (all) {
|
||||||
|
log.warn "Parsing Body failed - trying again..."
|
||||||
|
doDeviceSync()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private put(path, body) {
|
private put(path, body) {
|
||||||
@@ -668,9 +675,13 @@ ${bodyJSON}
|
|||||||
private getBridgeIP() {
|
private getBridgeIP() {
|
||||||
def host = null
|
def host = null
|
||||||
if (selectedHue) {
|
if (selectedHue) {
|
||||||
def d = getChildDevice(dni)
|
def d = getChildDevice(selectedHue)
|
||||||
if (d)
|
if (d) {
|
||||||
host = d.latestState('networkAddress').stringValue
|
if (d.getDeviceDataByName("networkAddress"))
|
||||||
|
host = d.getDeviceDataByName("networkAddress")
|
||||||
|
else
|
||||||
|
host = d.latestState('networkAddress').stringValue
|
||||||
|
}
|
||||||
if (host == null || host == "") {
|
if (host == null || host == "") {
|
||||||
def serialNumber = selectedHue
|
def serialNumber = selectedHue
|
||||||
def bridge = getHueBridges().find { it?.value?.serialNumber?.equalsIgnoreCase(serialNumber) }?.value
|
def bridge = getHueBridges().find { it?.value?.serialNumber?.equalsIgnoreCase(serialNumber) }?.value
|
||||||
|
|||||||
Reference in New Issue
Block a user