|
|
|
|
@@ -95,7 +95,8 @@ def bridgeDiscoveryFailed() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def bridgeLinking() {
|
|
|
|
|
def bridgeLinking()
|
|
|
|
|
{
|
|
|
|
|
int linkRefreshcount = !state.linkRefreshcount ? 0 : state.linkRefreshcount as int
|
|
|
|
|
state.linkRefreshcount = linkRefreshcount + 1
|
|
|
|
|
def refreshInterval = 3
|
|
|
|
|
@@ -327,7 +328,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, modelid: v.modelid, hub:hub, online: v.state?.reachable]
|
|
|
|
|
bulbs[k] = [id: k, name: v.name, type: v.type, modelid: v.modelid, hub:hub]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
def bridge = null
|
|
|
|
|
@@ -447,6 +448,7 @@ def addBridge() {
|
|
|
|
|
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)
|
|
|
|
|
@@ -647,7 +649,8 @@ def locationHandler(evt) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (parsedEvent.headers && parsedEvent.body) {
|
|
|
|
|
}
|
|
|
|
|
else if (parsedEvent.headers && parsedEvent.body) {
|
|
|
|
|
log.trace "HUE BRIDGE RESPONSES"
|
|
|
|
|
def headerString = parsedEvent.headers.toString()
|
|
|
|
|
if (headerString?.contains("xml")) {
|
|
|
|
|
@@ -730,7 +733,7 @@ private void updateBridgeStatus(childDevice) {
|
|
|
|
|
private void checkBridgeStatus() {
|
|
|
|
|
def bridges = getHueBridges()
|
|
|
|
|
// Check if each bridge has been heard from within the last 16 minutes (3 poll intervals times 5 minutes plus buffer)
|
|
|
|
|
def time = now() - (1000 * 60 * 30)
|
|
|
|
|
def time = now() - (1000 * 60 * 16)
|
|
|
|
|
bridges.each {
|
|
|
|
|
def d = getChildDevice(it.value.mac)
|
|
|
|
|
if(d) {
|
|
|
|
|
@@ -743,8 +746,6 @@ private void checkBridgeStatus() {
|
|
|
|
|
if (it.value.lastActivity < time) { // it.value.lastActivity != null &&
|
|
|
|
|
log.warn "Bridge $it.key is Offline"
|
|
|
|
|
d.sendEvent(name: "status", value: "Offline")
|
|
|
|
|
// set all lights to offline since bridge is not reachable
|
|
|
|
|
state.bulbs?.each {it.value.online = false}
|
|
|
|
|
} else {
|
|
|
|
|
d.sendEvent(name: "status", value: "Online")//setOnline(false)
|
|
|
|
|
}
|
|
|
|
|
@@ -784,7 +785,8 @@ def parse(childDevice, description) {
|
|
|
|
|
if (body instanceof java.util.Map) {
|
|
|
|
|
// get (poll) reponse
|
|
|
|
|
return handlePoll(body)
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
//put response
|
|
|
|
|
return handleCommandResponse(body)
|
|
|
|
|
}
|
|
|
|
|
@@ -905,14 +907,10 @@ private handleCommandResponse(body) {
|
|
|
|
|
// send events for each update found above (order of events should be same as handlePoll())
|
|
|
|
|
updates.each { childDeviceNetworkId, params ->
|
|
|
|
|
def device = getChildDevice(childDeviceNetworkId)
|
|
|
|
|
def id = getId(device)
|
|
|
|
|
// If device is offline, then don't send events which will update device watch
|
|
|
|
|
if (isOnline(id)) {
|
|
|
|
|
sendBasicEvents(device, "on", params.on)
|
|
|
|
|
sendBasicEvents(device, "bri", params.bri)
|
|
|
|
|
sendColorEvents(device, params.xy, params.hue, params.sat, params.ct)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -934,26 +932,20 @@ private handleCommandResponse(body) {
|
|
|
|
|
* @return empty array
|
|
|
|
|
*/
|
|
|
|
|
private handlePoll(body) {
|
|
|
|
|
if (state.updating) {
|
|
|
|
|
// If user just executed commands, then ignore poll to not confuse the turning on/off state
|
|
|
|
|
return []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def bulbs = getChildDevices()
|
|
|
|
|
for (bulb in body) {
|
|
|
|
|
def device = bulbs.find{it.deviceNetworkId == "${app.id}/${bulb.key}"}
|
|
|
|
|
if (device) {
|
|
|
|
|
if (bulb.value.state?.reachable) {
|
|
|
|
|
if (state.bulbs[bulb.key]?.online == false) {
|
|
|
|
|
// light just came back online, notify device watch
|
|
|
|
|
def lastActivity = now()
|
|
|
|
|
device.sendEvent(name: "deviceWatch-status", value: "ONLINE", description: "Last Activity is on ${new Date((long) lastActivity)}", displayed: false, isStateChange: true)
|
|
|
|
|
}
|
|
|
|
|
state.bulbs[bulb.key]?.online = true
|
|
|
|
|
|
|
|
|
|
// If user just executed commands, then do not send events to avoid confusing the turning on/off state
|
|
|
|
|
if (!state.updating) {
|
|
|
|
|
sendBasicEvents(device, "on", bulb.value?.state?.on)
|
|
|
|
|
sendBasicEvents(device, "bri", bulb.value?.state?.bri)
|
|
|
|
|
sendColorEvents(device, bulb.value?.state?.xy, bulb.value?.state?.hue, bulb.value?.state?.sat, bulb.value?.state?.ct, bulb.value?.state?.colormode)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
state.bulbs[bulb.key]?.online = false
|
|
|
|
|
log.warn "$device is not reachable by Hue bridge"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -988,34 +980,22 @@ def hubVerification(bodytext) {
|
|
|
|
|
|
|
|
|
|
def on(childDevice) {
|
|
|
|
|
log.debug "Executing 'on'"
|
|
|
|
|
def id = getId(childDevice)
|
|
|
|
|
if (!isOnline(id)) {
|
|
|
|
|
return "Bulb is unreachable"
|
|
|
|
|
}
|
|
|
|
|
updateInProgress()
|
|
|
|
|
createSwitchEvent(childDevice, "on")
|
|
|
|
|
put("lights/$id/state", [on: true])
|
|
|
|
|
put("lights/${getId(childDevice)}/state", [on: true])
|
|
|
|
|
return "Bulb is turning On"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def off(childDevice) {
|
|
|
|
|
log.debug "Executing 'off'"
|
|
|
|
|
def id = getId(childDevice)
|
|
|
|
|
if (!isOnline(id)) {
|
|
|
|
|
return "Bulb is unreachable"
|
|
|
|
|
}
|
|
|
|
|
updateInProgress()
|
|
|
|
|
createSwitchEvent(childDevice, "off")
|
|
|
|
|
put("lights/$id/state", [on: false])
|
|
|
|
|
put("lights/${getId(childDevice)}/state", [on: false])
|
|
|
|
|
return "Bulb is turning Off"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def setLevel(childDevice, percent) {
|
|
|
|
|
log.debug "Executing 'setLevel'"
|
|
|
|
|
def id = getId(childDevice)
|
|
|
|
|
if (!isOnline(id)) {
|
|
|
|
|
return "Bulb is unreachable"
|
|
|
|
|
}
|
|
|
|
|
updateInProgress()
|
|
|
|
|
// 1 - 254
|
|
|
|
|
def level
|
|
|
|
|
@@ -1030,64 +1010,48 @@ def setLevel(childDevice, percent) {
|
|
|
|
|
// that means that the light will still be on when on is called next time
|
|
|
|
|
// Lets emulate that here
|
|
|
|
|
if (percent > 0) {
|
|
|
|
|
put("lights/$id/state", [bri: level, on: true])
|
|
|
|
|
put("lights/${getId(childDevice)}/state", [bri: level, on: true])
|
|
|
|
|
} else {
|
|
|
|
|
put("lights/$id/state", [on: false])
|
|
|
|
|
put("lights/${getId(childDevice)}/state", [on: false])
|
|
|
|
|
}
|
|
|
|
|
return "Setting level to $percent"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def setSaturation(childDevice, percent) {
|
|
|
|
|
log.debug "Executing 'setSaturation($percent)'"
|
|
|
|
|
def id = getId(childDevice)
|
|
|
|
|
if (!isOnline(id)) {
|
|
|
|
|
return "Bulb is unreachable"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateInProgress()
|
|
|
|
|
// 0 - 254
|
|
|
|
|
def level = Math.min(Math.round(percent * 254 / 100), 254)
|
|
|
|
|
// TODO should this be done by app only or should we default to on?
|
|
|
|
|
createSwitchEvent(childDevice, "on")
|
|
|
|
|
put("lights/$id/state", [sat: level, on: true])
|
|
|
|
|
put("lights/${getId(childDevice)}/state", [sat: level, on: true])
|
|
|
|
|
return "Setting saturation to $percent"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def setHue(childDevice, percent) {
|
|
|
|
|
log.debug "Executing 'setHue($percent)'"
|
|
|
|
|
def id = getId(childDevice)
|
|
|
|
|
if (!isOnline(id)) {
|
|
|
|
|
return "Bulb is unreachable"
|
|
|
|
|
}
|
|
|
|
|
updateInProgress()
|
|
|
|
|
// 0 - 65535
|
|
|
|
|
def level = Math.min(Math.round(percent * 65535 / 100), 65535)
|
|
|
|
|
// TODO should this be done by app only or should we default to on?
|
|
|
|
|
createSwitchEvent(childDevice, "on")
|
|
|
|
|
put("lights/$id/state", [hue: level, on: true])
|
|
|
|
|
put("lights/${getId(childDevice)}/state", [hue: level, on: true])
|
|
|
|
|
return "Setting hue to $percent"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def setColorTemperature(childDevice, huesettings) {
|
|
|
|
|
log.debug "Executing 'setColorTemperature($huesettings)'"
|
|
|
|
|
def id = getId(childDevice)
|
|
|
|
|
if (!isOnline(id)) {
|
|
|
|
|
return "Bulb is unreachable"
|
|
|
|
|
}
|
|
|
|
|
updateInProgress()
|
|
|
|
|
// 153 (6500K) to 500 (2000K)
|
|
|
|
|
def ct = hueSettings == 6500 ? 153 : Math.round(1000000/huesettings)
|
|
|
|
|
createSwitchEvent(childDevice, "on")
|
|
|
|
|
put("lights/$id/state", [ct: ct, on: true])
|
|
|
|
|
put("lights/${getId(childDevice)}/state", [ct: ct, on: true])
|
|
|
|
|
return "Setting color temperature to $percent"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def setColor(childDevice, huesettings) {
|
|
|
|
|
log.debug "Executing 'setColor($huesettings)'"
|
|
|
|
|
def id = getId(childDevice)
|
|
|
|
|
if (!isOnline(id)) {
|
|
|
|
|
return "Bulb is unreachable"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateInProgress()
|
|
|
|
|
|
|
|
|
|
def value = [:]
|
|
|
|
|
@@ -1144,23 +1108,15 @@ def setColor(childDevice, huesettings) {
|
|
|
|
|
value.on = false
|
|
|
|
|
|
|
|
|
|
createSwitchEvent(childDevice, value.on ? "on" : "off")
|
|
|
|
|
put("lights/$id/state", value)
|
|
|
|
|
put("lights/${getId(childDevice)}/state", value)
|
|
|
|
|
return "Setting color to $value"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def ping(childDevice) {
|
|
|
|
|
if (isOnline(getId(childDevice))) {
|
|
|
|
|
childDevice.sendEvent(name: "deviceWatch-ping", value: "ONLINE", description: "Hue Light is reachable", displayed: false, isStateChange: true)
|
|
|
|
|
return "Device is Online"
|
|
|
|
|
} else {
|
|
|
|
|
return "Device is Offline"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getId(childDevice) {
|
|
|
|
|
if (childDevice.device?.deviceNetworkId?.startsWith("HUE")) {
|
|
|
|
|
return childDevice.device?.deviceNetworkId[3..-1]
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return childDevice.device?.deviceNetworkId.split("/")[-1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1171,11 +1127,8 @@ private poll() {
|
|
|
|
|
log.debug "GET: $host$uri"
|
|
|
|
|
sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1
|
|
|
|
|
HOST: ${host}
|
|
|
|
|
""", physicalgraph.device.Protocol.LAN, selectedHue))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private isOnline(id) {
|
|
|
|
|
return (state.bulbs[id].online != null && state.bulbs[id].online) || state.bulbs[id].online == null
|
|
|
|
|
""", physicalgraph.device.Protocol.LAN, selectedHue))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private put(path, body) {
|
|
|
|
|
@@ -1245,7 +1198,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, "type": bulb.type, "modelid": bulb.modelid, "hub":bulb.hub, "online": bulb.online]]
|
|
|
|
|
map << ["${bulb.id}":["id":bulb.id, "name":bulb.name, "type": bulb.type, "modelid": bulb.modelid, "hub":bulb.hub]]
|
|
|
|
|
}
|
|
|
|
|
state.bulbs = map
|
|
|
|
|
}
|
|
|
|
|
|