mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-09 21:03:00 +00:00
Compare commits
24 Commits
MSA-1325-3
...
PROD_2016.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1a910f11f | ||
|
|
9f09a4b0b2 | ||
|
|
3c47fe7b60 | ||
|
|
45a0822e9b | ||
|
|
bbba20288e | ||
|
|
ff9dd3f6e2 | ||
|
|
a94a62d34c | ||
|
|
e861d3c256 | ||
|
|
7adff88d0f | ||
|
|
ad1f1b2dc9 | ||
|
|
8d8b039dda | ||
|
|
c875547942 | ||
|
|
1676a9c381 | ||
|
|
5d1b033486 | ||
|
|
31f77513da | ||
|
|
98d7829d1a | ||
|
|
c6f706e47a | ||
|
|
532afd7336 | ||
|
|
ac7f1a0c66 | ||
|
|
cb26f055d7 | ||
|
|
34107f935e | ||
|
|
cc2d19e951 | ||
|
|
038d770691 | ||
|
|
ce28ec2039 |
@@ -403,39 +403,21 @@ def refresh() {
|
||||
|
||||
if (device.getDataValue("manufacturer") == "SmartThings") {
|
||||
log.debug "Refreshing Values for manufacturer: SmartThings "
|
||||
refreshCmds = refreshCmds + [
|
||||
/* These values of Motion Threshold Multiplier(01) and Motion Threshold (7602)
|
||||
seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer.
|
||||
Separating these out in a separate if-else because I do not want to touch Centralite part
|
||||
as of now.
|
||||
*/
|
||||
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global write 0xFC02 0 0x20 {01}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 400",
|
||||
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global write 0xFC02 2 0x21 {7602}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 400",
|
||||
]
|
||||
/* These values of Motion Threshold Multiplier(0x01) and Motion Threshold (0x0276)
|
||||
seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer.
|
||||
Separating these out in a separate if-else because I do not want to touch Centralite part
|
||||
as of now.
|
||||
*/
|
||||
refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x01, [mfgCode: manufacturerCode])
|
||||
refreshCmds += zigbee.writeAttribute(0xFC02, 0x0002, 0x21, 0x0276, [mfgCode: manufacturerCode])
|
||||
} else {
|
||||
refreshCmds = refreshCmds + [
|
||||
/* sensitivity - default value (8) */
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global write 0xFC02 0 0x20 {02}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 400",
|
||||
]
|
||||
refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x02, [mfgCode: manufacturerCode])
|
||||
}
|
||||
|
||||
//Common refresh commands
|
||||
refreshCmds = refreshCmds + [
|
||||
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
|
||||
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200",
|
||||
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global read 0xFC02 0x0010",
|
||||
"send 0x${device.deviceNetworkId} 1 1","delay 400"
|
||||
]
|
||||
refreshCmds += zigbee.readAttribute(0x0402, 0x0000) +
|
||||
zigbee.readAttribute(0x0001, 0x0020) +
|
||||
zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode])
|
||||
|
||||
return refreshCmds + enrollResponse()
|
||||
}
|
||||
@@ -443,38 +425,15 @@ def refresh() {
|
||||
def configure() {
|
||||
sendEvent(name: "checkInterval", value: 7200, displayed: false)
|
||||
|
||||
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
|
||||
log.debug "Configuring Reporting"
|
||||
|
||||
def configCmds = [
|
||||
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
|
||||
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 200",
|
||||
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", "delay 200", //checkin time 6 hrs
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
|
||||
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 200",
|
||||
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
|
||||
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0xFC02 {${device.zigbeeId}} {}", "delay 200",
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global send-me-a-report 0xFC02 0x0010 0x18 10 3600 {01}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global send-me-a-report 0xFC02 0x0012 0x29 1 3600 {0100}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global send-me-a-report 0xFC02 0x0013 0x29 1 3600 {0100}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
|
||||
"zcl mfg-code ${manufacturerCode}", "delay 200",
|
||||
"zcl global send-me-a-report 0xFC02 0x0014 0x29 1 3600 {0100}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
|
||||
]
|
||||
def configCmds = enrollResponse() +
|
||||
zigbee.batteryConfig() +
|
||||
zigbee.temperatureConfig() +
|
||||
zigbee.configureReporting(0xFC02, 0x0010, 0x18, 10, 3600, 0x01, [mfgCode: manufacturerCode]) +
|
||||
zigbee.configureReporting(0xFC02, 0x0012, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
|
||||
zigbee.configureReporting(0xFC02, 0x0013, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
|
||||
zigbee.configureReporting(0xFC02, 0x0014, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode])
|
||||
|
||||
return configCmds + refresh()
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ metadata {
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x72,0x5A,0x80,0x73,0x86,0x84,0x85,0x59,0x71,0x70,0x7A,0x98" // Vision door/window
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98,0x86,0x72,0x5A,0x85,0x59,0x73,0x80,0x71,0x31,0x70,0x84,0x7A" // Vision Motion
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
@@ -263,5 +264,9 @@ def retypeBasedOnMSR() {
|
||||
log.debug "Changing device type to Door / Window Sensor Plus (SG)"
|
||||
setDeviceType("Door / Window Sensor Plus (SG)")
|
||||
break
|
||||
case "0109-2002-0205": // Vision Motion
|
||||
log.debug "Changing device type to Vision Motion Sensor Plus (SG)"
|
||||
setDeviceType("Vision Motion Sensor Plus (SG)")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,13 @@ metadata {
|
||||
capability "Motion Sensor"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
|
||||
fingerprint mfr: "011F", prod: "0001", model: "0001", deviceJoinName: "Schlage Motion Sensor" // Schlage motion
|
||||
fingerprint mfr: "014A", prod: "0001", model: "0001", deviceJoinName: "Ecolink Motion Sensor" // Ecolink motion
|
||||
fingerprint mfr: "014A", prod: "0004", model: "0001", deviceJoinName: "Ecolink Motion Sensor" // Ecolink motion +
|
||||
fingerprint mfr: "0060", prod: "0001", model: "0002", deviceJoinName: "Everspring Motion Sensor" // Everspring SP814
|
||||
fingerprint mfr: "0060", prod: "0001", model: "0003", deviceJoinName: "Everspring Motion Sensor" // Everspring HSP02
|
||||
fingerprint mfr: "011A", prod: "0601", model: "0901", deviceJoinName: "Enerwave Motion Sensor" // Enerwave ZWN-BPC
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -125,9 +132,9 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
|
||||
}
|
||||
if (!state.lastbat || (new Date().time) - state.lastbat > 53*60*60*1000) {
|
||||
result << response(zwave.batteryV1.batteryGet())
|
||||
result << response("delay 1200")
|
||||
} else {
|
||||
result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||
}
|
||||
result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* 이혜진
|
||||
*
|
||||
* Copyright 2016 Leehyejin
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing permissions and limitations under the License.
|
||||
*
|
||||
*/
|
||||
definition(
|
||||
name: "이혜진",
|
||||
namespace: "이혜진",
|
||||
author: "Leehyejin",
|
||||
description: "test",
|
||||
category: "",
|
||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
|
||||
|
||||
|
||||
preferences {
|
||||
section("Title") {
|
||||
// TODO: put inputs here
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
|
||||
unsubscribe()
|
||||
initialize()
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
// TODO: subscribe to attributes, devices, locations, etc.
|
||||
}
|
||||
|
||||
// TODO: implement event handlers
|
||||
@@ -337,10 +337,10 @@ def initialize() {
|
||||
|
||||
settings.devices.each {
|
||||
def deviceId = it
|
||||
def detail = state.deviceDetail[deviceId]
|
||||
def detail = state?.deviceDetail[deviceId]
|
||||
|
||||
try {
|
||||
switch(detail.type) {
|
||||
switch(detail?.type) {
|
||||
case 'NAMain':
|
||||
log.debug "Base station"
|
||||
createChildDevice("Netatmo Basestation", deviceId, "${detail.type}.${deviceId}", detail.module_name)
|
||||
@@ -487,12 +487,12 @@ def poll() {
|
||||
log.debug "State: ${state.deviceState}"
|
||||
|
||||
settings.devices.each { deviceId ->
|
||||
def detail = state.deviceDetail[deviceId]
|
||||
def data = state.deviceState[deviceId]
|
||||
def child = children.find { it.deviceNetworkId == deviceId }
|
||||
def detail = state?.deviceDetail[deviceId]
|
||||
def data = state?.deviceState[deviceId]
|
||||
def child = children?.find { it.deviceNetworkId == deviceId }
|
||||
|
||||
log.debug "Update: $child";
|
||||
switch(detail.type) {
|
||||
switch(detail?.type) {
|
||||
case 'NAMain':
|
||||
log.debug "Updating NAMain $data"
|
||||
child?.sendEvent(name: 'temperature', value: cToPref(data['Temperature']) as float, unit: getTemperatureScale())
|
||||
|
||||
@@ -1,345 +0,0 @@
|
||||
/**
|
||||
* SmartThings service for Prempoint
|
||||
*
|
||||
* Author: Prempoint Inc. (c) 2016
|
||||
*
|
||||
*/
|
||||
definition(
|
||||
name: "Prempoint",
|
||||
namespace: "prempoint.com",
|
||||
author: "Prempoint Inc.",
|
||||
description: "SmartThings service for Prempoint",
|
||||
category: "Connections",
|
||||
iconUrl: "http://www.prempoint.com/images/social_app_emblem_50x50.png",
|
||||
iconX2Url: "http://www.prempoint.com/images/social_app_emblem_100x100.png",
|
||||
iconX3Url: "http://www.prempoint.com/images/social_app_emblem_150x150.png",
|
||||
oauth: [displayName: "Prempoint", displayLink: "http://www.prempoint.com/"])
|
||||
|
||||
preferences {
|
||||
section("Allow Prempoint to Control & Access These Things...") {
|
||||
input "switches", "capability.switch", title: "Which Switches?", multiple: true, required: false
|
||||
input "locks", "capability.lock", title: "Which Locks?", multiple: true, required: false
|
||||
input "garagedoors", "capability.garageDoorControl", title: "Which Garage Doors?", multiple: true, required: false
|
||||
//input "doors", "capability.doorControl", title: "Which Doors?", multiple: true, required: false
|
||||
input "cameras", "capability.imageCapture", title: "Which Cameras?", multiple: true, required: false
|
||||
}
|
||||
}
|
||||
|
||||
mappings {
|
||||
path("/list") {
|
||||
action: [
|
||||
GET: "listDevices"
|
||||
]
|
||||
}
|
||||
path("/switches") {
|
||||
action: [
|
||||
GET: "listSwitches"
|
||||
]
|
||||
}
|
||||
path("/switches/:id") {
|
||||
action: [
|
||||
GET: "showSwitch"
|
||||
]
|
||||
}
|
||||
path("/switches/:id/:command") {
|
||||
action: [
|
||||
GET: "updateSwitch"
|
||||
]
|
||||
}
|
||||
path("/switches/:id/:command/:level") {
|
||||
action: [
|
||||
GET: "updateSwitch"
|
||||
]
|
||||
}
|
||||
path("/locks") {
|
||||
action: [
|
||||
GET: "listLocks"
|
||||
]
|
||||
}
|
||||
path("/locks/:id") {
|
||||
action: [
|
||||
GET: "showLock"
|
||||
]
|
||||
}
|
||||
path("/locks/:id/:command") {
|
||||
action: [
|
||||
GET: "updateLock"
|
||||
]
|
||||
}
|
||||
path("/doors/:id") {
|
||||
action: [
|
||||
GET: "showDoor"
|
||||
]
|
||||
}
|
||||
path("/doors/:id/:command") {
|
||||
action: [
|
||||
GET: "updateDoor"
|
||||
]
|
||||
}
|
||||
path("/garagedoors/:id") {
|
||||
action: [
|
||||
GET: "showGarageDoor"
|
||||
]
|
||||
}
|
||||
path("/garagedoors/:id/:command") {
|
||||
action: [
|
||||
GET: "updateGarageDoor"
|
||||
]
|
||||
}
|
||||
path("/cameras/:id") {
|
||||
action: [
|
||||
GET: "showCamera"
|
||||
]
|
||||
}
|
||||
path("/cameras/:id/:command") {
|
||||
action: [
|
||||
GET: "updateCamera"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {}
|
||||
|
||||
def updated() {}
|
||||
|
||||
def listDevices() {
|
||||
log.debug "entering listDevices"
|
||||
//return listSwitches() + listLocks() + listGarageDoors() + listDoors() + listCameras()
|
||||
return listSwitches() + listLocks() + listGarageDoors() + listCameras()
|
||||
}
|
||||
|
||||
//switches
|
||||
def listSwitches() {
|
||||
log.debug "entering listSwitches"
|
||||
switches.collect{showDevice(it,"switch")}
|
||||
}
|
||||
|
||||
def showSwitch() {
|
||||
log.debug "entering showSwitches"
|
||||
show(switches, "switch")
|
||||
}
|
||||
|
||||
def updateSwitch() {
|
||||
log.debug "entering updateSwitches"
|
||||
update(switches, "switch")
|
||||
}
|
||||
|
||||
//locks
|
||||
def listLocks() {
|
||||
log.debug "entering listLocks"
|
||||
locks.collect{showDevice(it,"lock")}
|
||||
}
|
||||
|
||||
def showLock() {
|
||||
log.debug "entering showLock"
|
||||
show(locks, "lock")
|
||||
}
|
||||
|
||||
def updateLock() {
|
||||
log.debug "entering updateLock"
|
||||
update(locks, "lock")
|
||||
}
|
||||
|
||||
//doors
|
||||
def listDoors() {
|
||||
log.debug "entering listDoors"
|
||||
locks.collect{showDevice(it,"door")}
|
||||
}
|
||||
|
||||
def showDoor() {
|
||||
log.debug "entering showDoors"
|
||||
show(doors, "door")
|
||||
}
|
||||
|
||||
def updateDoor() {
|
||||
log.debug "entering updateDoor"
|
||||
update(doors, "door")
|
||||
}
|
||||
|
||||
//garagedoors
|
||||
def listGarageDoors() {
|
||||
log.debug "entering listGarageDoors"
|
||||
locks.collect{showDevice(it,"garagedoor")}
|
||||
}
|
||||
|
||||
def showGarageDoor() {
|
||||
log.debug "entering showGarageDoors"
|
||||
show(garagedoors, "garagedoor")
|
||||
}
|
||||
|
||||
def updateGarageDoor() {
|
||||
log.debug "entering updateGarageDoor"
|
||||
update(gargedoors, "garagedoor")
|
||||
}
|
||||
|
||||
//cameras
|
||||
def listCameras() {
|
||||
log.debug "entering listCameras"
|
||||
cameras.collect{showDevice(it,"image")}
|
||||
}
|
||||
|
||||
def showCamera() {
|
||||
log.debug "entering showCameras"
|
||||
show(cameras, "camera")
|
||||
}
|
||||
|
||||
def updateCamera() {
|
||||
log.debug "entering updateCamera"
|
||||
update(cameras, "camera")
|
||||
}
|
||||
|
||||
def deviceHandler(evt) {}
|
||||
|
||||
private update(devices, type) {
|
||||
def rc = null
|
||||
|
||||
//def command = request.JSON?.command
|
||||
def command = params.command
|
||||
|
||||
log.debug "update, request: params: ${params}, devices: $devices.id type=$type command=$command"
|
||||
|
||||
// Process the command.
|
||||
if (command)
|
||||
{
|
||||
def dev = devices.find { it.id == params.id }
|
||||
if (!dev) {
|
||||
httpError(404, "Device not found: $params.id")
|
||||
} else if (type == "switch") {
|
||||
switch(command) {
|
||||
case "on":
|
||||
rc = dev.on()
|
||||
break
|
||||
case "off":
|
||||
rc = dev.off()
|
||||
break
|
||||
default:
|
||||
httpError(400, "Device command=$command is not a valid for device=$it.id $dev")
|
||||
}
|
||||
} else if (type == "lock") {
|
||||
switch(command) {
|
||||
case "lock":
|
||||
rc = dev.lock()
|
||||
break
|
||||
case "unlock":
|
||||
rc = dev.unlock()
|
||||
break
|
||||
default:
|
||||
httpError(400, "Device command=$command is not a valid for device:=$it.id $dev")
|
||||
}
|
||||
} else if (type == "door") {
|
||||
switch(command) {
|
||||
case "open":
|
||||
rc = dev.open()
|
||||
break
|
||||
case "close":
|
||||
rc = dev.close()
|
||||
break
|
||||
default:
|
||||
httpError(400, "Device command=$command is not a valid for device=$it.id $dev")
|
||||
}
|
||||
} else if (type == "garagedoor") {
|
||||
switch(command) {
|
||||
case "open":
|
||||
rc = dev.open()
|
||||
break
|
||||
case "close":
|
||||
rc = dev.close()
|
||||
break
|
||||
default:
|
||||
httpError(400, "Device command=$command is not a valid for device=$it.id $dev")
|
||||
}
|
||||
} else if (type == "camera") {
|
||||
switch(command) {
|
||||
case "take":
|
||||
rc = dev.take()
|
||||
log.debug "Device command=$command device=$it.id $dev current image=$it.currentImage"
|
||||
break
|
||||
default:
|
||||
httpError(400, "Device command=$command is not a valid for device=$it.id $dev")
|
||||
}
|
||||
}
|
||||
|
||||
log.debug "executed device=$it.id $dev command=$command rc=$rc"
|
||||
|
||||
// Check that the device is a switch that is currently on, supports 'setLevel"
|
||||
// and that a level was specified.
|
||||
int level = params.level ? params.level as int : -1;
|
||||
if ((type == "switch") && (dev.currentValue('switch') == "on") && hasLevel(dev) && (level != -1)) {
|
||||
log.debug "device about to setLevel=$level"
|
||||
dev.setLevel(level);
|
||||
}
|
||||
|
||||
// Show the device info if necessary.
|
||||
if (rc == null) {
|
||||
rc = showDevice(dev, type)
|
||||
}
|
||||
}
|
||||
|
||||
return rc
|
||||
}
|
||||
|
||||
private show(devices, type) {
|
||||
def dev = devices.find { it.id == params.id }
|
||||
if (!dev) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
// Show the device info.
|
||||
showDevice(dev, type)
|
||||
}
|
||||
}
|
||||
|
||||
private showDevice(it, type) {
|
||||
def props = null
|
||||
|
||||
// Get the current state for the device type.
|
||||
def state = [it.currentState(type)]
|
||||
|
||||
// Check that whether the a switch device with level support is located and update the returned device type.
|
||||
def devType = type
|
||||
|
||||
if (type == "switch" && hasLevel(it)) {
|
||||
// Assign "switchWithLevel" to device type.
|
||||
devType = "switchWithLevel"
|
||||
// Add the level state.
|
||||
def levelState = it.currentState("level")
|
||||
if (levelState) {
|
||||
state.add(levelState)
|
||||
}
|
||||
}
|
||||
|
||||
log.debug "device label=$it.label type=$devType"
|
||||
|
||||
// Assign the device item properties if appropriate.
|
||||
if (it) {
|
||||
props = [id: it.id, label: it.label, type: devType, state: state]
|
||||
// Add the hub information to the device properties
|
||||
// if appropriate.
|
||||
if (it.hub) {
|
||||
props.put("location", it.hub.hub.location)
|
||||
}
|
||||
if (it.currentImage) {
|
||||
props.put("currentImage", it.currentImage)
|
||||
}
|
||||
}
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
private hasLevel(device) {
|
||||
// Default return value.
|
||||
def rc = false;
|
||||
|
||||
// Get the device supported commands.
|
||||
def supportedCommands = device.supportedCommands
|
||||
|
||||
// Check to see if the "setLevel" was found and assign
|
||||
// the appropriate return value.
|
||||
if (supportedCommands) {
|
||||
// Find the "setLevel" command.
|
||||
rc = supportedCommands.toString().indexOf("setLevel") != -1
|
||||
}
|
||||
|
||||
log.debug "hasLevel device label=$device.label supportedCommands=$supportedCommands rc=$rc"
|
||||
|
||||
return rc
|
||||
}
|
||||
@@ -30,6 +30,7 @@ definition(
|
||||
preferences {
|
||||
page(name:"mainPage", title:"Hue Device Setup", content:"mainPage", refreshTimeout:5)
|
||||
page(name:"bridgeDiscovery", title:"Hue Bridge Discovery", content:"bridgeDiscovery", refreshTimeout:5)
|
||||
page(name:"bridgeDiscoveryFailed", title:"Bridge Discovery Failed", content:"bridgeDiscoveryFailed", refreshTimeout:0)
|
||||
page(name:"bridgeBtnPush", title:"Linking with your Hue", content:"bridgeLinking", refreshTimeout:5)
|
||||
page(name:"bulbDiscovery", title:"Hue Device Setup", content:"bulbDiscovery", refreshTimeout:5)
|
||||
}
|
||||
@@ -53,12 +54,21 @@ def bridgeDiscovery(params=[:])
|
||||
def options = bridges ?: []
|
||||
def numFound = options.size() ?: 0
|
||||
|
||||
if (numFound == 0 && state.bridgeRefreshCount > 25) {
|
||||
log.trace "Cleaning old bridges memory"
|
||||
state.bridges = [:]
|
||||
state.bridgeRefreshCount = 0
|
||||
app.updateSetting("selectedHue", "")
|
||||
}
|
||||
if (numFound == 0) {
|
||||
if (state.bridgeRefreshCount == 25) {
|
||||
log.trace "Cleaning old bridges memory"
|
||||
state.bridges = [:]
|
||||
app.updateSetting("selectedHue", "")
|
||||
} else if (state.bridgeRefreshCount > 100) {
|
||||
// five minutes have passed, give up
|
||||
// there seems to be a problem going back from discovey failed page in some instances (compared to pressing next)
|
||||
// however it is probably a SmartThings settings issue
|
||||
state.bridges = [:]
|
||||
app.updateSetting("selectedHue", "")
|
||||
state.bridgeRefreshCount = 0
|
||||
return bridgeDiscoveryFailed()
|
||||
}
|
||||
}
|
||||
|
||||
ssdpSubscribe()
|
||||
|
||||
@@ -79,6 +89,13 @@ def bridgeDiscovery(params=[:])
|
||||
}
|
||||
}
|
||||
|
||||
def bridgeDiscoveryFailed() {
|
||||
return dynamicPage(name:"bridgeDiscoveryFailed", title: "Bridge Discovery Failed", nextPage: "bridgeDiscovery") {
|
||||
section("Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.") {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def bridgeLinking()
|
||||
{
|
||||
int linkRefreshcount = !state.linkRefreshcount ? 0 : state.linkRefreshcount as int
|
||||
@@ -88,19 +105,15 @@ def bridgeLinking()
|
||||
def nextPage = ""
|
||||
def title = "Linking with your Hue"
|
||||
def paragraphText
|
||||
def hueimage = null
|
||||
if (selectedHue) {
|
||||
paragraphText = "Press the button on your Hue Bridge to setup a link. "
|
||||
hueimage = "http://huedisco.mediavibe.nl/wp-content/uploads/2013/09/pair-bridge.png"
|
||||
} else {
|
||||
paragraphText = "You haven't selected a Hue Bridge, please Press \"Done\" and select one before clicking next."
|
||||
hueimage = null
|
||||
}
|
||||
if (state.username) { //if discovery worked
|
||||
nextPage = "bulbDiscovery"
|
||||
title = "Success!"
|
||||
paragraphText = "Linking to your hub was a success! Please click 'Next'!"
|
||||
hueimage = null
|
||||
}
|
||||
|
||||
if((linkRefreshcount % 2) == 0 && !state.username) {
|
||||
@@ -110,8 +123,6 @@ def bridgeLinking()
|
||||
return dynamicPage(name:"bridgeBtnPush", title:title, nextPage:nextPage, refreshInterval:refreshInterval) {
|
||||
section("") {
|
||||
paragraph """${paragraphText}"""
|
||||
if (hueimage != null)
|
||||
image "${hueimage}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,13 +146,14 @@ def bulbDiscovery() {
|
||||
if((bulbRefreshCount % 5) == 0) {
|
||||
discoverHueBulbs()
|
||||
}
|
||||
def selectedBridge = state.bridges.find { key, value -> value?.serialNumber?.equalsIgnoreCase(selectedHue) }
|
||||
def title = selectedBridge?.value?.name ?: "Find bridges"
|
||||
|
||||
return dynamicPage(name:"bulbDiscovery", title:"Bulb Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) {
|
||||
section("Please wait while we discover your Hue Bulbs. 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 Bulbs (${numFound} found)", multiple:true, options:bulboptions
|
||||
}
|
||||
section {
|
||||
def title = getBridgeIP() ? "Hue bridge (${getBridgeIP()})" : "Find bridges"
|
||||
href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true]
|
||||
|
||||
}
|
||||
@@ -348,26 +360,29 @@ def addBulbs() {
|
||||
def newHueBulb
|
||||
if (bulbs instanceof java.util.Map) {
|
||||
newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
|
||||
if (newHueBulb != null) {
|
||||
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub)
|
||||
|
||||
if (newHueBulb != null) {
|
||||
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub)
|
||||
if (d) {
|
||||
log.debug "created ${d.displayName} with id $dni"
|
||||
d.completedSetup = true
|
||||
d.refresh()
|
||||
}
|
||||
} else {
|
||||
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
|
||||
}
|
||||
} else {
|
||||
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
|
||||
}
|
||||
} else {
|
||||
//backwards compatable
|
||||
//backwards compatable
|
||||
newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni }
|
||||
d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub)
|
||||
d?.completedSetup = true
|
||||
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 }
|
||||
def newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
|
||||
upgradeDeviceType(d, newHueBulb?.value?.type)
|
||||
}
|
||||
}
|
||||
@@ -399,6 +414,7 @@ def addBridge() {
|
||||
}
|
||||
if (newbridge) {
|
||||
d = addChildDevice("smartthings", "Hue Bridge", selectedHue, vbridge.value.hub)
|
||||
d?.completedSetup = true
|
||||
log.debug "created ${d.displayName} with id ${d.deviceNetworkId}"
|
||||
def childDevice = getChildDevice(d.deviceNetworkId)
|
||||
childDevice.sendEvent(name: "serialNumber", value: vbridge.value.serialNumber)
|
||||
@@ -486,7 +502,21 @@ void bridgeDescriptionHandler(physicalgraph.device.HubResponse hubResponse) {
|
||||
def bridges = getHueBridges()
|
||||
def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())}
|
||||
if (bridge) {
|
||||
bridge.value << [name:body?.device?.friendlyName?.text(), serialNumber:body?.device?.serialNumber?.text(), verified: true]
|
||||
// serialNumber from API is in format of 0017882413ad (mac address), however on the actual bridge only last six
|
||||
// characters are printed on the back so using that to identify bridge
|
||||
def idNumber = body?.device?.serialNumber?.text()
|
||||
if (idNumber?.size() >= 6)
|
||||
idNumber = idNumber[-6..-1].toUpperCase()
|
||||
|
||||
// usually in form of bridge name followed by (ip), i.e. defaults to Philips Hue (192.168.1.2)
|
||||
// replace IP with serial number to make it easier for user to identify
|
||||
def name = body?.device?.friendlyName?.text()
|
||||
def index = name?.indexOf('(')
|
||||
if (index != -1) {
|
||||
name = name.substring(0,index)
|
||||
name += " ($idNumber)"
|
||||
}
|
||||
bridge.value << [name:name, serialNumber:body?.device?.serialNumber?.text(), verified: true]
|
||||
} else {
|
||||
log.error "/description.xml returned a bridge that didn't exist"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user