mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-09 05:11:52 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1241802315 | ||
|
|
0414ae0460 | ||
|
|
67006204da | ||
|
|
32e3916a85 | ||
|
|
dc1071d132 | ||
|
|
94f8b4ecfc |
@@ -1,506 +0,0 @@
|
||||
/**
|
||||
* Keen Home Smart Vent
|
||||
*
|
||||
* Author: Keen Home
|
||||
* Date: 2015-06-23
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Keen Home Smart Vent", namespace: "Keen Home", author: "Gregg Altschul") {
|
||||
capability "Switch Level"
|
||||
capability "Switch"
|
||||
capability "Configuration"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
capability "Temperature Measurement"
|
||||
capability "Battery"
|
||||
|
||||
command "getLevel"
|
||||
command "getOnOff"
|
||||
command "getPressure"
|
||||
command "getBattery"
|
||||
command "getTemperature"
|
||||
command "setZigBeeIdTile"
|
||||
|
||||
fingerprint endpoint: "1",
|
||||
profileId: "0104",
|
||||
inClusters: "0000,0001,0003,0004,0005,0006,0008,0020,0402,0403,0B05,FC01,FC02",
|
||||
outClusters: "0019"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
simulator {
|
||||
// status messages
|
||||
status "on": "on/off: 1"
|
||||
status "off": "on/off: 0"
|
||||
|
||||
// reply messages
|
||||
reply "zcl on-off on": "on/off: 1"
|
||||
reply "zcl on-off off": "on/off: 0"
|
||||
}
|
||||
|
||||
// UI tile definitions
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#53a7c0"
|
||||
state "off", action:"switch.on", icon:"st.vents.vent-closed", backgroundColor:"#ffffff"
|
||||
state "obstructed", action: "switch.off", icon:"st.vents.vent-closed", backgroundColor:"#ff0000"
|
||||
}
|
||||
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) {
|
||||
state "level", action:"switch level.setLevel"
|
||||
}
|
||||
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
|
||||
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
backgroundColors:[
|
||||
[value: 31, color: "#153591"],
|
||||
[value: 44, color: "#1e9cbb"],
|
||||
[value: 59, color: "#90d2a7"],
|
||||
[value: 74, color: "#44b621"],
|
||||
[value: 84, color: "#f1d801"],
|
||||
[value: 95, color: "#d04e00"],
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state "battery", label: 'Battery \n${currentValue}%', backgroundColor:"#ffffff"
|
||||
}
|
||||
valueTile("zigbeeId", "device.zigbeeId", inactiveLabel: true, decoration: "flat") {
|
||||
state "serial", label:'${currentValue}', backgroundColor:"#ffffff"
|
||||
}
|
||||
main "switch"
|
||||
details(["switch","refresh","temperature","levelSliderControl","battery"])
|
||||
}
|
||||
}
|
||||
|
||||
/**** PARSE METHODS ****/
|
||||
def parse(String description) {
|
||||
log.debug "description: $description"
|
||||
|
||||
Map map = [:]
|
||||
if (description?.startsWith('catchall:')) {
|
||||
map = parseCatchAllMessage(description)
|
||||
}
|
||||
else if (description?.startsWith('read attr -')) {
|
||||
map = parseReportAttributeMessage(description)
|
||||
}
|
||||
else if (description?.startsWith('temperature: ') || description?.startsWith('humidity: ')) {
|
||||
map = parseCustomMessage(description)
|
||||
}
|
||||
else if (description?.startsWith('on/off: ')) {
|
||||
map = parseOnOffMessage(description)
|
||||
}
|
||||
|
||||
log.debug "Parse returned $map"
|
||||
return map ? createEvent(map) : null
|
||||
}
|
||||
|
||||
private Map parseCatchAllMessage(String description) {
|
||||
log.debug "parseCatchAllMessage"
|
||||
|
||||
def cluster = zigbee.parse(description)
|
||||
log.debug "cluster: ${cluster}"
|
||||
if (shouldProcessMessage(cluster)) {
|
||||
log.debug "processing message"
|
||||
switch(cluster.clusterId) {
|
||||
case 0x0001:
|
||||
return makeBatteryResult(cluster.data.last())
|
||||
break
|
||||
|
||||
case 0x0402:
|
||||
// temp is last 2 data values. reverse to swap endian
|
||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||
def value = convertTemperatureHex(temp)
|
||||
return makeTemperatureResult(value)
|
||||
break
|
||||
|
||||
case 0x0006:
|
||||
return makeOnOffResult(cluster.data[-1])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return [:]
|
||||
}
|
||||
|
||||
private boolean shouldProcessMessage(cluster) {
|
||||
// 0x0B is default response indicating message got through
|
||||
// 0x07 is bind message
|
||||
if (cluster.profileId != 0x0104 ||
|
||||
cluster.command == 0x0B ||
|
||||
cluster.command == 0x07 ||
|
||||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private Map parseReportAttributeMessage(String description) {
|
||||
log.debug "parseReportAttributeMessage"
|
||||
|
||||
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
|
||||
def nameAndValue = param.split(":")
|
||||
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
|
||||
}
|
||||
log.debug "Desc Map: $descMap"
|
||||
|
||||
if (descMap.cluster == "0006" && descMap.attrId == "0000") {
|
||||
return makeOnOffResult(Int.parseInt(descMap.value));
|
||||
}
|
||||
else if (descMap.cluster == "0008" && descMap.attrId == "0000") {
|
||||
return makeLevelResult(descMap.value)
|
||||
}
|
||||
else if (descMap.cluster == "0402" && descMap.attrId == "0000") {
|
||||
def value = convertTemperatureHex(descMap.value)
|
||||
return makeTemperatureResult(value)
|
||||
}
|
||||
else if (descMap.cluster == "0001" && descMap.attrId == "0021") {
|
||||
return makeBatteryResult(Integer.parseInt(descMap.value, 16))
|
||||
}
|
||||
else if (descMap.cluster == "0403" && descMap.attrId == "0020") {
|
||||
return makePressureResult(Integer.parseInt(descMap.value, 16))
|
||||
}
|
||||
else if (descMap.cluster == "0000" && descMap.attrId == "0006") {
|
||||
return makeSerialResult(new String(descMap.value.decodeHex()))
|
||||
}
|
||||
|
||||
// shouldn't get here
|
||||
return [:]
|
||||
}
|
||||
|
||||
private Map parseCustomMessage(String description) {
|
||||
Map resultMap = [:]
|
||||
if (description?.startsWith('temperature: ')) {
|
||||
// log.debug "${description}"
|
||||
// def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale())
|
||||
// log.debug "split: " + description.split(": ")
|
||||
def value = Double.parseDouble(description.split(": ")[1])
|
||||
// log.debug "${value}"
|
||||
resultMap = makeTemperatureResult(convertTemperature(value))
|
||||
}
|
||||
return resultMap
|
||||
}
|
||||
|
||||
private Map parseOnOffMessage(String description) {
|
||||
Map resultMap = [:]
|
||||
if (description?.startsWith('on/off: ')) {
|
||||
def value = Integer.parseInt(description - "on/off: ")
|
||||
resultMap = makeOnOffResult(value)
|
||||
}
|
||||
return resultMap
|
||||
}
|
||||
|
||||
private Map makeOnOffResult(rawValue) {
|
||||
log.debug "makeOnOffResult: ${rawValue}"
|
||||
def linkText = getLinkText(device)
|
||||
def value = rawValue == 1 ? "on" : "off"
|
||||
return [
|
||||
name: "switch",
|
||||
value: value,
|
||||
descriptionText: "${linkText} is ${value}"
|
||||
]
|
||||
}
|
||||
|
||||
private Map makeLevelResult(rawValue) {
|
||||
def linkText = getLinkText(device)
|
||||
// log.debug "rawValue: ${rawValue}"
|
||||
def value = Integer.parseInt(rawValue, 16)
|
||||
def rangeMax = 254
|
||||
|
||||
if (value == 255) {
|
||||
log.debug "obstructed"
|
||||
// Just return here. Once the vent is power cycled
|
||||
// it will go back to the previous level before obstruction.
|
||||
// Therefore, no need to update level on the display.
|
||||
return [
|
||||
name: "switch",
|
||||
value: "obstructed",
|
||||
descriptionText: "${linkText} is obstructed. Please power cycle."
|
||||
]
|
||||
} else if ( device.currentValue("switch") == "obstructed" &&
|
||||
value == 254) {
|
||||
// When the device is reset after an obstruction, the switch
|
||||
// state will be obstructed and the value coming from the device
|
||||
// will be 254. Since we're not using heating/cooling mode from
|
||||
// the device type handler, we need to bump it down to the lower
|
||||
// (cooling) range
|
||||
sendEvent(makeOnOffResult(1)) // clear the obstructed switch state
|
||||
value = rangeMax
|
||||
}
|
||||
// else if (device.currentValue("switch") == "off") {
|
||||
// sendEvent(makeOnOffResult(1)) // turn back on if in off state
|
||||
// }
|
||||
|
||||
|
||||
// log.debug "pre-value: ${value}"
|
||||
value = Math.floor(value / rangeMax * 100)
|
||||
// log.debug "post-value: ${value}"
|
||||
|
||||
return [
|
||||
name: "level",
|
||||
value: value,
|
||||
descriptionText: "${linkText} level is ${value}%"
|
||||
]
|
||||
}
|
||||
|
||||
private Map makePressureResult(rawValue) {
|
||||
log.debug 'makePressureResut'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
def pascals = rawValue / 10
|
||||
def result = [
|
||||
name: 'pressure',
|
||||
descriptionText: "${linkText} pressure is ${pascals}Pa",
|
||||
value: pascals
|
||||
]
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private Map makeBatteryResult(rawValue) {
|
||||
// log.debug 'makeBatteryResult'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
// log.debug
|
||||
[
|
||||
name: 'battery',
|
||||
value: rawValue,
|
||||
descriptionText: "${linkText} battery is at ${rawValue}%"
|
||||
]
|
||||
}
|
||||
|
||||
private Map makeTemperatureResult(value) {
|
||||
// log.debug 'makeTemperatureResult'
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
// log.debug "tempOffset: ${tempOffset}"
|
||||
if (tempOffset) {
|
||||
def offset = tempOffset as int
|
||||
// log.debug "offset: ${offset}"
|
||||
def v = value as int
|
||||
// log.debug "v: ${v}"
|
||||
value = v + offset
|
||||
// log.debug "value: ${value}"
|
||||
}
|
||||
|
||||
return [
|
||||
name: 'temperature',
|
||||
value: "" + value,
|
||||
descriptionText: "${linkText} is ${value}°${temperatureScale}",
|
||||
]
|
||||
}
|
||||
|
||||
/**** HELPER METHODS ****/
|
||||
private def convertTemperatureHex(value) {
|
||||
// log.debug "convertTemperatureHex(${value})"
|
||||
def celsius = Integer.parseInt(value, 16).shortValue() / 100
|
||||
// log.debug "celsius: ${celsius}"
|
||||
|
||||
return convertTemperature(celsius)
|
||||
}
|
||||
|
||||
private def convertTemperature(celsius) {
|
||||
// log.debug "convertTemperature()"
|
||||
|
||||
if(getTemperatureScale() == "C"){
|
||||
return celsius
|
||||
} else {
|
||||
def fahrenheit = Math.round(celsiusToFahrenheit(celsius) * 100) /100
|
||||
// log.debug "converted to F: ${fahrenheit}"
|
||||
return fahrenheit
|
||||
}
|
||||
}
|
||||
|
||||
private def makeSerialResult(serial) {
|
||||
log.debug "makeSerialResult: " + serial
|
||||
|
||||
def linkText = getLinkText(device)
|
||||
sendEvent([
|
||||
name: "serial",
|
||||
value: serial,
|
||||
descriptionText: "${linkText} has serial ${serial}" ])
|
||||
return [
|
||||
name: "serial",
|
||||
value: serial,
|
||||
descriptionText: "${linkText} has serial ${serial}" ]
|
||||
}
|
||||
/**** COMMAND METHODS ****/
|
||||
// def mfgCode() {
|
||||
// ["zcl mfg-code 0x115B", "delay 200"]
|
||||
// }
|
||||
|
||||
def on() {
|
||||
log.debug "on()"
|
||||
sendEvent(makeOnOffResult(1))
|
||||
"st cmd 0x${device.deviceNetworkId} 1 6 1 {}"
|
||||
}
|
||||
|
||||
def off() {
|
||||
log.debug "off()"
|
||||
sendEvent(makeOnOffResult(0))
|
||||
"st cmd 0x${device.deviceNetworkId} 1 6 0 {}"
|
||||
}
|
||||
|
||||
// does this work?
|
||||
def toggle() {
|
||||
log.debug "toggle()"
|
||||
|
||||
"st cmd 0x${device.deviceNetworkId} 1 6 2 {}"
|
||||
}
|
||||
|
||||
def setLevel(value) {
|
||||
log.debug "setting level: ${value}"
|
||||
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
sendEvent(name: "level", value: value)
|
||||
if (value > 0) {
|
||||
sendEvent(name: "switch", value: "on", descriptionText: "${linkText} is on by setting a level")
|
||||
}
|
||||
else {
|
||||
sendEvent(name: "switch", value: "off", descriptionText: "${linkText} is off by setting level to 0")
|
||||
}
|
||||
def rangeMax = 254
|
||||
def computedLevel = Math.round(value * rangeMax / 100)
|
||||
log.debug "computedLevel: ${computedLevel}"
|
||||
|
||||
def level = new BigInteger(computedLevel.toString()).toString(16)
|
||||
log.debug "level: ${level}"
|
||||
|
||||
if (level.size() < 2){
|
||||
level = '0' + level
|
||||
}
|
||||
|
||||
"st cmd 0x${device.deviceNetworkId} 1 8 4 {${level} 0000}"
|
||||
}
|
||||
|
||||
|
||||
def getOnOff() {
|
||||
log.debug "getOnOff()"
|
||||
|
||||
["st rattr 0x${device.deviceNetworkId} 1 0x0006 0"]
|
||||
}
|
||||
|
||||
def getPressure() {
|
||||
log.debug "getPressure()"
|
||||
[
|
||||
"zcl mfg-code 0x115B", "delay 200",
|
||||
"zcl global read 0x0403 0x20", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
|
||||
]
|
||||
}
|
||||
|
||||
def getLevel() {
|
||||
log.debug "getLevel()"
|
||||
// rattr = read attribute
|
||||
// 0x${} = device net id
|
||||
// 1 = endpoint
|
||||
// 8 = cluster id (level control, in this case)
|
||||
// 0 = attribute within cluster
|
||||
// sendEvent(name: "level", value: value)
|
||||
["st rattr 0x${device.deviceNetworkId} 1 0x0008 0x0000"]
|
||||
}
|
||||
|
||||
def getTemperature() {
|
||||
log.debug "getTemperature()"
|
||||
|
||||
["st rattr 0x${device.deviceNetworkId} 1 0x0402 0"]
|
||||
}
|
||||
|
||||
def getBattery() {
|
||||
log.debug "getBattery()"
|
||||
|
||||
["st rattr 0x${device.deviceNetworkId} 1 0x0001 0x0021"]
|
||||
}
|
||||
|
||||
def setZigBeeIdTile() {
|
||||
log.debug "setZigBeeIdTile() - ${device.zigbeeId}"
|
||||
|
||||
def linkText = getLinkText(device)
|
||||
|
||||
sendEvent([
|
||||
name: "zigbeeId",
|
||||
value: device.zigbeeId,
|
||||
descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ])
|
||||
return [
|
||||
name: "zigbeeId",
|
||||
value: device.zigbeeId,
|
||||
descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ]
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
getOnOff() +
|
||||
getLevel() +
|
||||
getTemperature() +
|
||||
getPressure() +
|
||||
getBattery()
|
||||
}
|
||||
|
||||
private byte[] reverseArray(byte[] array) {
|
||||
int i = 0;
|
||||
int j = array.length - 1;
|
||||
byte tmp;
|
||||
while (j > i) {
|
||||
tmp = array[j];
|
||||
array[j] = array[i];
|
||||
array[i] = tmp;
|
||||
j--;
|
||||
i++;
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
private String swapEndianHex(String hex) {
|
||||
reverseArray(hex.decodeHex()).encodeHex()
|
||||
}
|
||||
|
||||
def configure() {
|
||||
log.debug "CONFIGURE"
|
||||
log.debug "zigbeeId: ${device.hub.zigbeeId}"
|
||||
|
||||
setZigBeeIdTile()
|
||||
|
||||
def configCmds = [
|
||||
// binding commands
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0006 {${device.zigbeeId}} {}", "delay 500",
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0008 {${device.zigbeeId}} {}", "delay 500",
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0402 {${device.zigbeeId}} {}", "delay 500",
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0403 {${device.zigbeeId}} {}", "delay 500",
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0001 {${device.zigbeeId}} {}", "delay 500",
|
||||
|
||||
// configure report commands
|
||||
// [cluster] [attr] [type] [min-interval] [max-interval] [min-change]
|
||||
|
||||
// mike 2015/06/22: preconfigured; see tech spec
|
||||
// vent on/off state - type: boolean, change: 1
|
||||
// "zcl global send-me-a-report 6 0 0x10 5 60 {01}", "delay 200",
|
||||
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||
|
||||
// mike 2015/06/22: preconfigured; see tech spec
|
||||
// vent level - type: int8u, change: 1
|
||||
// "zcl global send-me-a-report 8 0 0x20 5 60 {01}", "delay 200",
|
||||
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||
|
||||
// mike 2015/06/22: temp and pressure reports are preconfigured, but
|
||||
// we'd like to override their settings for our own purposes
|
||||
// temperature - type: int16s, change: 0xA = 10 = 0.1C
|
||||
"zcl global send-me-a-report 0x0402 0 0x29 10 60 {0A00}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||
|
||||
// mike 2015/06/22: use new custom pressure attribute
|
||||
// pressure - type: int32u, change: 1 = 0.1Pa
|
||||
"zcl mfg-code 0x115B", "delay 200",
|
||||
"zcl global send-me-a-report 0x0403 0x20 0x22 10 60 {010000}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 1500"
|
||||
|
||||
// mike 2015/06/22: preconfigured; see tech spec
|
||||
// battery - type: int8u, change: 1
|
||||
// "zcl global send-me-a-report 1 0x21 0x20 60 3600 {01}", "delay 200",
|
||||
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||
]
|
||||
|
||||
return configCmds + refresh()
|
||||
}
|
||||
@@ -341,13 +341,6 @@ def eventHandler(name, value) {
|
||||
|
||||
def eventBuffer = atomicState.eventBuffer
|
||||
def epoch = now() / 1000
|
||||
|
||||
// if for some reason this code block is being run
|
||||
// but the SmartApp wasn't propery setup during install
|
||||
// we need to set initialize the eventBuffer.
|
||||
if (!atomicState.eventBuffer) {
|
||||
atomicState.eventBuffer = []
|
||||
}
|
||||
eventBuffer << [key: "$name", value: "$value", epoch: "$epoch"]
|
||||
|
||||
log.debug eventBuffer
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* Bathroom Lights
|
||||
*
|
||||
* Copyright 2015 Jesse Silverberg
|
||||
*
|
||||
* 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: "Bathroom Lights",
|
||||
namespace: "JLS",
|
||||
author: "Jesse Silverberg",
|
||||
description: "A specialized bathroom lighting automation. Turns lights on with motion, dims after a custom period of time to give the occupant a warning that lights will turn off soon, and then turns off the lights unless motion is detected again. Motion brightens the lights back up. Perfect for showering so you don't get left in the dark, and solves the problem of motion detection during lights-off dimming transitions.",
|
||||
category: "Convenience",
|
||||
iconUrl: "https://www.dropbox.com/s/6kxtd2v5reggonq/lightswitch.gif?raw=1",
|
||||
iconX2Url: "https://www.dropbox.com/s/6kxtd2v5reggonq/lightswitch.gif?raw=1",
|
||||
iconX3Url: "https://www.dropbox.com/s/6kxtd2v5reggonq/lightswitch.gif?raw=1")
|
||||
|
||||
|
||||
preferences {
|
||||
|
||||
section("Select devices") {
|
||||
input "lights", "capability.switchLevel", title:"Bathroom lights", multiple: true , required: true
|
||||
input "motionSensor", "capability.motionSensor", title: "Bathroom motion sensor(s)", multiple: true, required: true
|
||||
}
|
||||
section("Brightness and timing options") {
|
||||
input "dimLevelHi", "number", title: "Brighten lights to this level (0-100)...", required: true
|
||||
input "brightenTimeHi", "number", title: "Hold lights here for this long (minutes)...", required: true
|
||||
input "dimLevelLow", "number", title: "Then dim lights to this level (0-100)...", required: true
|
||||
input "brightenTimeLow", "number", title: "And turn off after this long (minutes)...", required: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
|
||||
unsubscribe()
|
||||
initialize()
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
subscribe(motionSensor, "motion.active", motionDetectedHandler)
|
||||
subscribe(motionSensor, "motion.inactive", motionStoppedHandler)
|
||||
}
|
||||
|
||||
def motionDetectedHandler(evt) {
|
||||
log.debug "motionDetectedHandler called: $evt"
|
||||
unschedule()
|
||||
lights.setLevel(dimLevelHi)
|
||||
}
|
||||
|
||||
def motionStoppedHandler(evt) {
|
||||
log.debug "motionStoppedHandler called: $evt"
|
||||
|
||||
def noMotion = motionSensor.find{it.currentMotion == "active"} == null
|
||||
if (noMotion) {
|
||||
log.debug "motionStoppedHandler found no motion on all sensors"
|
||||
log.debug "Scheduling lights to dim and turn off"
|
||||
runIn(60 * brightenTimeHi, dimLights)
|
||||
runIn(60 * (brightenTimeHi + brightenTimeLow), offLights)
|
||||
}
|
||||
}
|
||||
|
||||
def dimLights() {
|
||||
log.debug "Dimming lights $lights to $dimLeveLow"
|
||||
lights.setLevel(dimLevelLow)
|
||||
}
|
||||
|
||||
def offLights() {
|
||||
log.debug "Turning off lights $lights"
|
||||
lights.off()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,702 @@
|
||||
/**
|
||||
* Home Remote
|
||||
*
|
||||
* Copyright 2015 The Home Remote
|
||||
*
|
||||
* 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: "Home Remote",
|
||||
namespace: "thehomeremote.homeremote",
|
||||
author: "The Home Remote",
|
||||
description: "Web service that enables communication between the Home Remote app and a SmartThings hub.",
|
||||
category: "My Apps",
|
||||
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",
|
||||
oauth: [displayName: "The Home Remote", displayLink: "http://thehomeremote.com/"])
|
||||
|
||||
|
||||
preferences {
|
||||
section() {
|
||||
input "accelerationSensors", "capability.accelerationSensor",title: "Acceleration Sensors", multiple: true, required: false
|
||||
input "alarms", "capability.alarm",title: "Alarms", multiple: true, required: false
|
||||
input "batteries", "capability.battery",title: "Batteries", multiple: true, required: false
|
||||
input "beacons", "capability.beacon",title: "Beacons", multiple: true, required: false
|
||||
input "buttonGroup", "capability.button",title: "Buttons", multiple: true, required: false
|
||||
input "carbonMonoxideDetectors", "capability.carbonMonoxideDetector",title: "CO Detectors", multiple: true, required: false
|
||||
input "colorControls", "capability.colorControl",title: "Color Lights", multiple: true, required: false
|
||||
input "contactSensors", "capability.contactSensor",title: "Contact Sensors", multiple: true, required: false
|
||||
input "doorControls", "capability.doorControl",title: "Door Controllers", multiple: true, required: false
|
||||
input "energyMeters", "capability.energyMeter",title: "Energy Meters", multiple: true, required: false
|
||||
input "illuminanceMeasurements", "capability.illuminanceMeasurement",title: "Illuminance Sensors", multiple: true, required: false
|
||||
input "imageCaptures", "capability.imageCapture",title: "Cameras", multiple: true, required: false
|
||||
input "locks", "capability.lock",title: "Locks", multiple: true, required: false
|
||||
input "mediaControllers", "capability.mediaController",title: "Media Controllers", multiple: true, required: false
|
||||
input "momentaries", "capability.momentary",title: "Momentary Buttons", multiple: true, required: false
|
||||
input "motionSensors", "capability.motionSensor",title: "Motion Sensors", multiple: true, required: false
|
||||
input "musicPlayers", "capability.musicPlayer",title: "Music Players", multiple: true, required: false
|
||||
input "powerMeters", "capability.powerMeter",title: "Power Meters", multiple: true, required: false
|
||||
input "presenceSensors", "capability.presenceSensor",title: "Presence Sensors", multiple: true, required: false
|
||||
input "relativeHumidityMeasurements", "capability.relativeHumidityMeasurement",title: "Humidity Sensors", multiple: true, required: false
|
||||
input "relaySwitches", "capability.relaySwitch",title: "Relays", multiple: true, required: false
|
||||
input "signalStrengths", "capability.signalStrength",title: "Signal Strengths", multiple: true, required: false
|
||||
input "sleepSensors", "capability.sleepSensor",title: "Sleep Sensors", multiple: true, required: false
|
||||
input "smokeDetectors", "capability.smokeDetector",title: "Smoke Detectors", multiple: true, required: false
|
||||
input "speechSyntheses", "capability.speechSynthesis",title: "Speech Syntheses", multiple: true, required: false
|
||||
input "stepSensors", "capability.stepSensor",title: "Step Sensors", multiple: true, required: false
|
||||
input "switches", "capability.switch",title: "Switches", multiple: true, required: false
|
||||
input "switchLevels", "capability.switchLevel",title: "Dimmers", multiple: true, required: false
|
||||
input "temperatureMeasurements", "capability.temperatureMeasurement",title: "Temperature Sensors", multiple: true, required: false
|
||||
input "thermostats", "capability.thermostat",title: "Thermostats", multiple: true, required: false
|
||||
input "threeAxes", "capability.threeAxis",title: "Three axis Sensors", multiple: true, required: false
|
||||
input "tones", "capability.tone",title: "Tones", multiple: true, required: false
|
||||
input "touchSensors", "capability.touchSensor",title: "Touch Sensors", multiple: true, required: false
|
||||
input "valves", "capability.valve",title: "Valves", multiple: true, required: false
|
||||
input "waterSensors", "capability.waterSensor",title: "Water Sensors", multiple: true, required: false
|
||||
}
|
||||
}
|
||||
|
||||
mappings {
|
||||
path("/GetCurrentValues") {
|
||||
action: [
|
||||
GET: "getCurrentValues"
|
||||
]
|
||||
}
|
||||
path("/GetCurrentValuesWithDisplayName") {
|
||||
action: [
|
||||
GET: "getCurrentValuesWithDisplayName"
|
||||
]
|
||||
}
|
||||
path("/ExecuteCommand") {
|
||||
action: [
|
||||
PUT: "executeCommand"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
def getCurrentValues() {
|
||||
def resp = []
|
||||
|
||||
accelerationSensors.each {
|
||||
resp << [id: it.id, capability: "AccelerationSensor", attribute: "acceleration", value: it.currentValue("acceleration")]
|
||||
}
|
||||
|
||||
alarms.each {
|
||||
resp << [id: it.id, capability: "Alarm", attribute: "alarm", value: it.currentValue("alarm")]
|
||||
}
|
||||
|
||||
batteries.each {
|
||||
resp << [id: it.id, capability: "Battery", attribute: "battery", value: it.currentValue("battery")]
|
||||
}
|
||||
|
||||
beacons.each {
|
||||
resp << [id: it.id, capability: "Beacon", attribute: "presence", value: it.currentValue("presence")]
|
||||
}
|
||||
|
||||
buttonGroup.each {
|
||||
resp << [id: it.id, capability: "Button", attribute: "button", value: it.currentValue("button")]
|
||||
}
|
||||
|
||||
carbonMonoxideDetectors.each {
|
||||
resp << [id: it.id, capability: "CarbonMonoxideDetector", attribute: "carbonMonoxide", value: it.currentValue("carbonMonoxide")]
|
||||
}
|
||||
|
||||
colorControls.each {
|
||||
resp << [id: it.id, capability: "ColorControl", attribute: "hue", value: it.currentValue("hue")]
|
||||
}
|
||||
|
||||
colorControls.each {
|
||||
resp << [id: it.id, capability: "ColorControl", attribute: "saturation", value: it.currentValue("saturation")]
|
||||
}
|
||||
|
||||
colorControls.each {
|
||||
resp << [id: it.id, capability: "ColorControl", attribute: "color", value: it.currentValue("color")]
|
||||
}
|
||||
|
||||
contactSensors.each {
|
||||
resp << [id: it.id, capability: "ContactSensor", attribute: "contact", value: it.currentValue("contact")]
|
||||
}
|
||||
|
||||
doorControls.each {
|
||||
resp << [id: it.id, capability: "DoorControl", attribute: "door", value: it.currentValue("door")]
|
||||
}
|
||||
|
||||
energyMeters.each {
|
||||
resp << [id: it.id, capability: "EnergyMeter", attribute: "energy", value: it.currentValue("energy")]
|
||||
}
|
||||
|
||||
illuminanceMeasurements.each {
|
||||
resp << [id: it.id, capability: "IlluminanceMeasurement", attribute: "illuminance", value: it.currentValue("illuminance")]
|
||||
}
|
||||
|
||||
imageCaptures.each {
|
||||
resp << [id: it.id, capability: "ImageCapture", attribute: "image", value: it.currentValue("image")]
|
||||
}
|
||||
|
||||
locks.each {
|
||||
resp << [id: it.id, capability: "Lock", attribute: "lock", value: it.currentValue("lock")]
|
||||
}
|
||||
|
||||
mediaControllers.each {
|
||||
resp << [id: it.id, capability: "MediaController", attribute: "activities", value: it.currentValue("activities")]
|
||||
}
|
||||
|
||||
mediaControllers.each {
|
||||
resp << [id: it.id, capability: "MediaController", attribute: "currentActivity", value: it.currentValue("currentActivity")]
|
||||
}
|
||||
|
||||
motionSensors.each {
|
||||
resp << [id: it.id, capability: "MotionSensor", attribute: "motion", value: it.currentValue("motion")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, capability: "MusicPlayer", attribute: "status", value: it.currentValue("status")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, capability: "MusicPlayer", attribute: "level", value: it.currentValue("level")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, capability: "MusicPlayer", attribute: "trackDescription", value: it.currentValue("trackDescription")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, capability: "MusicPlayer", attribute: "trackData", value: it.currentValue("trackData")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, capability: "MusicPlayer", attribute: "mute", value: it.currentValue("mute")]
|
||||
}
|
||||
|
||||
powerMeters.each {
|
||||
resp << [id: it.id, capability: "PowerMeter", attribute: "power", value: it.currentValue("power")]
|
||||
}
|
||||
|
||||
presenceSensors.each {
|
||||
resp << [id: it.id, capability: "PresenceSensor", attribute: "presence", value: it.currentValue("presence")]
|
||||
}
|
||||
|
||||
relativeHumidityMeasurements.each {
|
||||
resp << [id: it.id, capability: "RelativeHumidityMeasurement", attribute: "humidity", value: it.currentValue("humidity")]
|
||||
}
|
||||
|
||||
relaySwitches.each {
|
||||
resp << [id: it.id, capability: "RelaySwitch", attribute: "switch", value: it.currentValue("switch")]
|
||||
}
|
||||
|
||||
signalStrengths.each {
|
||||
resp << [id: it.id, capability: "SignalStrength", attribute: "lqi", value: it.currentValue("lqi")]
|
||||
}
|
||||
|
||||
signalStrengths.each {
|
||||
resp << [id: it.id, capability: "SignalStrength", attribute: "rssi", value: it.currentValue("rssi")]
|
||||
}
|
||||
|
||||
sleepSensors.each {
|
||||
resp << [id: it.id, capability: "SleepSensor", attribute: "sleeping", value: it.currentValue("sleeping")]
|
||||
}
|
||||
|
||||
smokeDetectors.each {
|
||||
resp << [id: it.id, capability: "SmokeDetector", attribute: "smoke", value: it.currentValue("smoke")]
|
||||
}
|
||||
|
||||
stepSensors.each {
|
||||
resp << [id: it.id, capability: "StepSensor", attribute: "steps", value: it.currentValue("steps")]
|
||||
}
|
||||
|
||||
stepSensors.each {
|
||||
resp << [id: it.id, capability: "StepSensor", attribute: "goal", value: it.currentValue("goal")]
|
||||
}
|
||||
|
||||
switches.each {
|
||||
resp << [id: it.id, capability: "Switch", attribute: "switch", value: it.currentValue("switch")]
|
||||
}
|
||||
|
||||
switchLevels.each {
|
||||
resp << [id: it.id, capability: "SwitchLevel", attribute: "level", value: it.currentValue("level")]
|
||||
}
|
||||
|
||||
temperatureMeasurements.each {
|
||||
resp << [id: it.id, capability: "TemperatureMeasurement", attribute: "temperature", value: it.currentValue("temperature")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, capability: "Thermostat", attribute: "temperature", value: it.currentValue("temperature")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, capability: "Thermostat", attribute: "heatingSetpoint", value: it.currentValue("heatingSetpoint")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, capability: "Thermostat", attribute: "coolingSetpoint", value: it.currentValue("coolingSetpoint")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, capability: "Thermostat", attribute: "thermostatSetpoint", value: it.currentValue("thermostatSetpoint")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, capability: "Thermostat", attribute: "thermostatMode", value: it.currentValue("thermostatMode")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, capability: "Thermostat", attribute: "thermostatFanMode", value: it.currentValue("thermostatFanMode")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, capability: "Thermostat", attribute: "thermostatOperatingState", value: it.currentValue("thermostatOperatingState")]
|
||||
}
|
||||
|
||||
threeAxes.each {
|
||||
resp << [id: it.id, capability: "ThreeAxis", attribute: "threeAxis", value: it.currentValue("threeAxis")]
|
||||
}
|
||||
|
||||
touchSensors.each {
|
||||
resp << [id: it.id, capability: "TouchSensor", attribute: "touch", value: it.currentValue("touch")]
|
||||
}
|
||||
|
||||
valves.each {
|
||||
resp << [id: it.id, capability: "Valve", attribute: "contact", value: it.currentValue("contact")]
|
||||
}
|
||||
|
||||
waterSensors.each {
|
||||
resp << [id: it.id, capability: "WaterSensor", attribute: "water", value: it.currentValue("water")]
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
def getCurrentValuesWithDisplayName() {
|
||||
def resp = []
|
||||
|
||||
accelerationSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "AccelerationSensor", attribute: "acceleration", value: it.currentValue("acceleration")]
|
||||
}
|
||||
|
||||
alarms.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Alarm", attribute: "alarm", value: it.currentValue("alarm")]
|
||||
}
|
||||
|
||||
batteries.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Battery", attribute: "battery", value: it.currentValue("battery")]
|
||||
}
|
||||
|
||||
beacons.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Beacon", attribute: "presence", value: it.currentValue("presence")]
|
||||
}
|
||||
|
||||
buttonGroup.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Button", attribute: "button", value: it.currentValue("button")]
|
||||
}
|
||||
|
||||
carbonMonoxideDetectors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "CarbonMonoxideDetector", attribute: "carbonMonoxide", value: it.currentValue("carbonMonoxide")]
|
||||
}
|
||||
|
||||
colorControls.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "ColorControl", attribute: "hue", value: it.currentValue("hue")]
|
||||
}
|
||||
|
||||
colorControls.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "ColorControl", attribute: "saturation", value: it.currentValue("saturation")]
|
||||
}
|
||||
|
||||
colorControls.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "ColorControl", attribute: "color", value: it.currentValue("color")]
|
||||
}
|
||||
|
||||
contactSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "ContactSensor", attribute: "contact", value: it.currentValue("contact")]
|
||||
}
|
||||
|
||||
doorControls.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "DoorControl", attribute: "door", value: it.currentValue("door")]
|
||||
}
|
||||
|
||||
energyMeters.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "EnergyMeter", attribute: "energy", value: it.currentValue("energy")]
|
||||
}
|
||||
|
||||
illuminanceMeasurements.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "IlluminanceMeasurement", attribute: "illuminance", value: it.currentValue("illuminance")]
|
||||
}
|
||||
|
||||
imageCaptures.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "ImageCapture", attribute: "image", value: it.currentValue("image")]
|
||||
}
|
||||
|
||||
locks.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Lock", attribute: "lock", value: it.currentValue("lock")]
|
||||
}
|
||||
|
||||
mediaControllers.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MediaController", attribute: "activities", value: it.currentValue("activities")]
|
||||
}
|
||||
|
||||
mediaControllers.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MediaController", attribute: "currentActivity", value: it.currentValue("currentActivity")]
|
||||
}
|
||||
|
||||
motionSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MotionSensor", attribute: "motion", value: it.currentValue("motion")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MusicPlayer", attribute: "status", value: it.currentValue("status")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MusicPlayer", attribute: "level", value: it.currentValue("level")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MusicPlayer", attribute: "trackDescription", value: it.currentValue("trackDescription")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MusicPlayer", attribute: "trackData", value: it.currentValue("trackData")]
|
||||
}
|
||||
|
||||
musicPlayers.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "MusicPlayer", attribute: "mute", value: it.currentValue("mute")]
|
||||
}
|
||||
|
||||
powerMeters.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "PowerMeter", attribute: "power", value: it.currentValue("power")]
|
||||
}
|
||||
|
||||
presenceSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "PresenceSensor", attribute: "presence", value: it.currentValue("presence")]
|
||||
}
|
||||
|
||||
relativeHumidityMeasurements.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "RelativeHumidityMeasurement", attribute: "humidity", value: it.currentValue("humidity")]
|
||||
}
|
||||
|
||||
relaySwitches.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "RelaySwitch", attribute: "switch", value: it.currentValue("switch")]
|
||||
}
|
||||
|
||||
signalStrengths.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "SignalStrength", attribute: "lqi", value: it.currentValue("lqi")]
|
||||
}
|
||||
|
||||
signalStrengths.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "SignalStrength", attribute: "rssi", value: it.currentValue("rssi")]
|
||||
}
|
||||
|
||||
sleepSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "SleepSensor", attribute: "sleeping", value: it.currentValue("sleeping")]
|
||||
}
|
||||
|
||||
smokeDetectors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "SmokeDetector", attribute: "smoke", value: it.currentValue("smoke")]
|
||||
}
|
||||
|
||||
stepSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "StepSensor", attribute: "steps", value: it.currentValue("steps")]
|
||||
}
|
||||
|
||||
stepSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "StepSensor", attribute: "goal", value: it.currentValue("goal")]
|
||||
}
|
||||
|
||||
switches.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Switch", attribute: "switch", value: it.currentValue("switch")]
|
||||
}
|
||||
|
||||
switchLevels.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "SwitchLevel", attribute: "level", value: it.currentValue("level")]
|
||||
}
|
||||
|
||||
temperatureMeasurements.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "TemperatureMeasurement", attribute: "temperature", value: it.currentValue("temperature")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Thermostat", attribute: "temperature", value: it.currentValue("temperature")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Thermostat", attribute: "heatingSetpoint", value: it.currentValue("heatingSetpoint")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Thermostat", attribute: "coolingSetpoint", value: it.currentValue("coolingSetpoint")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Thermostat", attribute: "thermostatSetpoint", value: it.currentValue("thermostatSetpoint")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Thermostat", attribute: "thermostatMode", value: it.currentValue("thermostatMode")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Thermostat", attribute: "thermostatFanMode", value: it.currentValue("thermostatFanMode")]
|
||||
}
|
||||
|
||||
thermostats.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Thermostat", attribute: "thermostatOperatingState", value: it.currentValue("thermostatOperatingState")]
|
||||
}
|
||||
|
||||
threeAxes.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "ThreeAxis", attribute: "threeAxis", value: it.currentValue("threeAxis")]
|
||||
}
|
||||
|
||||
touchSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "TouchSensor", attribute: "touch", value: it.currentValue("touch")]
|
||||
}
|
||||
|
||||
valves.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "Valve", attribute: "contact", value: it.currentValue("contact")]
|
||||
}
|
||||
|
||||
waterSensors.each {
|
||||
resp << [id: it.id, displayName: it.displayName, capability: "WaterSensor", attribute: "water", value: it.currentValue("water")]
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
def getDevices(capability){
|
||||
|
||||
def result
|
||||
|
||||
switch (capability) {
|
||||
case "Alarm":
|
||||
result = alarms
|
||||
break
|
||||
case "ColorControl":
|
||||
result = colorControls
|
||||
break
|
||||
case "DoorControl":
|
||||
result = doorControls
|
||||
break
|
||||
case "ImageCapture":
|
||||
result = imageCaptures
|
||||
break
|
||||
case "Lock":
|
||||
result = locks
|
||||
break
|
||||
case "MediaController":
|
||||
result = mediaControllers
|
||||
break
|
||||
case "Momentary":
|
||||
result = momentaries
|
||||
break
|
||||
case "MusicPlayer":
|
||||
result = musicPlayers
|
||||
break
|
||||
case "RelaySwitch":
|
||||
result = relaySwitches
|
||||
break
|
||||
case "SpeechSynthesis":
|
||||
result = speechSyntheses
|
||||
break
|
||||
case "Switch":
|
||||
result = switches
|
||||
break
|
||||
case "SwitchLevel":
|
||||
result = switchLevels
|
||||
break
|
||||
case "Thermostat":
|
||||
result = thermostats
|
||||
break
|
||||
case "ThermostatCoolingSetpoint":
|
||||
result = thermostatCoolingSetpoints
|
||||
break
|
||||
case "ThermostatFanMode":
|
||||
result = thermostatFanModes
|
||||
break
|
||||
case "ThermostatHeatingSetpoint":
|
||||
result = thermostatHeatingSetpoints
|
||||
break
|
||||
case "ThermostatMode":
|
||||
result = thermostatModes
|
||||
break
|
||||
case "Tone":
|
||||
result = tones
|
||||
break
|
||||
case "Valve":
|
||||
result = valves
|
||||
break
|
||||
default:
|
||||
result = valves
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def getDoorControlCommand(value){
|
||||
def result
|
||||
switch (value) {
|
||||
case "closed":
|
||||
result = "close"
|
||||
break
|
||||
case "open":
|
||||
result = "open"
|
||||
break
|
||||
default:
|
||||
result = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def getLockCommand(value){
|
||||
def result
|
||||
switch (value) {
|
||||
case "locked":
|
||||
result = "lock"
|
||||
break
|
||||
case "unlocked":
|
||||
result = "unlock"
|
||||
break
|
||||
default:
|
||||
result = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def getMuteCommand(value){
|
||||
def result
|
||||
switch (value) {
|
||||
case "muted":
|
||||
result = "mute"
|
||||
break
|
||||
case "unmuted":
|
||||
result = "unmute"
|
||||
break
|
||||
default:
|
||||
result = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def getContactCommand(value){
|
||||
def result
|
||||
switch (value) {
|
||||
case "closed":
|
||||
result = "close"
|
||||
break
|
||||
case "open":
|
||||
result = "open"
|
||||
break
|
||||
default:
|
||||
result = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def getThermostatFanModeCommand(value){
|
||||
def result
|
||||
switch (value) {
|
||||
case "on":
|
||||
result = "fanOn"
|
||||
break
|
||||
case "auto":
|
||||
result = "fanAuto"
|
||||
break
|
||||
case "circulate":
|
||||
result = "fanCirculate"
|
||||
break
|
||||
default:
|
||||
result = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
void executeCommand() {
|
||||
// use the built-in request object to get the command parameter
|
||||
def deviceId = request.JSON?.deviceId
|
||||
def capability = request.JSON?.capability
|
||||
def attribute = request.JSON?.attribute
|
||||
def value = request.JSON?.value
|
||||
if (deviceId) {
|
||||
def devices = getDevices(capability)
|
||||
def command
|
||||
def valueIsParameter = false
|
||||
switch (attribute) {
|
||||
case "hue":
|
||||
command = "setHue"
|
||||
valueIsParameter = true
|
||||
break
|
||||
case "saturation":
|
||||
command = "setSaturation"
|
||||
valueIsParameter = true
|
||||
break
|
||||
case "color":
|
||||
command = "setColor"
|
||||
valueIsParameter = true
|
||||
break
|
||||
case "level":
|
||||
command = "setLevel"
|
||||
valueIsParameter = true
|
||||
break
|
||||
case "heatingSetpoint":
|
||||
command = "setHeatingSetpoint"
|
||||
valueIsParameter = true
|
||||
break
|
||||
case "coolingSetpoint":
|
||||
command = "setCoolingSetpoint"
|
||||
valueIsParameter = true
|
||||
break
|
||||
case "currentActivity":
|
||||
command = "startActivity"
|
||||
valueIsParameter = true
|
||||
break
|
||||
case "door":
|
||||
command = getDoorControlCommand(value)
|
||||
break
|
||||
case "lock":
|
||||
command = getLockCommand(value)
|
||||
break
|
||||
case "mute":
|
||||
command = getMuteCommand(value)
|
||||
break
|
||||
case "thermostatFanMode":
|
||||
command = getThermostatFanModeCommand(value)
|
||||
break
|
||||
case "thermostatMode":
|
||||
if (value == "emergency heat") {
|
||||
command = "emergencyHeat"
|
||||
}
|
||||
break
|
||||
case "contact":
|
||||
command = getContactCommand(value)
|
||||
break
|
||||
default:
|
||||
command = value
|
||||
}
|
||||
// check that the switch supports the specified command
|
||||
// If not, return an error using httpError, providing a HTTP status code.
|
||||
devices.each {
|
||||
if (it.id == deviceId) {
|
||||
if (!it.hasCommand(command)) {
|
||||
httpError(501, "$command is not a valid command for all devices specified")
|
||||
}
|
||||
if(valueIsParameter){
|
||||
it."$command"(value)
|
||||
}
|
||||
else{
|
||||
it."$command"()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {}
|
||||
|
||||
def updated() {}
|
||||
Reference in New Issue
Block a user