mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-23 13:14:11 +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()
|
|
||||||
}
|
|
||||||
@@ -1,752 +0,0 @@
|
|||||||
/* lgk larry kahn kahn-st@lgk.com custom ct100 .. changes to stock device type
|
|
||||||
|
|
||||||
1. add some icons and colors heat color, cool color,
|
|
||||||
2. add operating mode tile ie idle heating etc
|
|
||||||
3. add color for humididity as well
|
|
||||||
4. get rid of sliders that worked like crap and added up down arrows for both heating and cooling,
|
|
||||||
and color based on temp for both.
|
|
||||||
5. add color for battery status.
|
|
||||||
|
|
||||||
v 2. some returns between indicators to move things down a line as recommended
|
|
||||||
v 3 reintegrate changes smarthigns made in setheatingsetpoint and setcoolingsetpoint functions apparently to get around bugs.
|
|
||||||
these changes were made in the stock ct100 device type.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
metadata {
|
|
||||||
// Automatically generated. Make future change here.
|
|
||||||
definition (name: "My CT100 Thermostat", namespace: "smartthings", author: "LGK Customized") {
|
|
||||||
capability "Actuator"
|
|
||||||
capability "Temperature Measurement"
|
|
||||||
capability "Relative Humidity Measurement"
|
|
||||||
capability "Thermostat"
|
|
||||||
capability "Battery"
|
|
||||||
capability "Configuration"
|
|
||||||
capability "Refresh"
|
|
||||||
capability "Sensor"
|
|
||||||
command "heatLevelUp"
|
|
||||||
command "heatLevelDown"
|
|
||||||
command "coolLevelUp"
|
|
||||||
command "coolLevelDown"
|
|
||||||
attribute "thermostatFanState", "string"
|
|
||||||
|
|
||||||
command "switchMode"
|
|
||||||
command "switchFanMode"
|
|
||||||
command "quickSetCool"
|
|
||||||
command "quickSetHeat"
|
|
||||||
|
|
||||||
fingerprint deviceId: "0x08", inClusters: "0x43,0x40,0x44,0x31,0x80,0x85,0x60"
|
|
||||||
}
|
|
||||||
|
|
||||||
// simulator metadata
|
|
||||||
simulator {
|
|
||||||
status "off" : "command: 4003, payload: 00"
|
|
||||||
status "heat" : "command: 4003, payload: 01"
|
|
||||||
status "cool" : "command: 4003, payload: 02"
|
|
||||||
status "auto" : "command: 4003, payload: 03"
|
|
||||||
status "emergencyHeat" : "command: 4003, payload: 04"
|
|
||||||
|
|
||||||
status "fanAuto" : "command: 4403, payload: 00"
|
|
||||||
status "fanOn" : "command: 4403, payload: 01"
|
|
||||||
status "fanCirculate" : "command: 4403, payload: 06"
|
|
||||||
|
|
||||||
status "heat 60" : "command: 4303, payload: 01 09 3C"
|
|
||||||
status "heat 72" : "command: 4303, payload: 01 09 48"
|
|
||||||
|
|
||||||
status "cool 76" : "command: 4303, payload: 02 09 4C"
|
|
||||||
status "cool 80" : "command: 4303, payload: 02 09 50"
|
|
||||||
|
|
||||||
status "temp 58" : "command: 3105, payload: 01 2A 02 44"
|
|
||||||
status "temp 62" : "command: 3105, payload: 01 2A 02 6C"
|
|
||||||
status "temp 78" : "command: 3105, payload: 01 2A 03 0C"
|
|
||||||
status "temp 86" : "command: 3105, payload: 01 2A 03 34"
|
|
||||||
|
|
||||||
status "idle" : "command: 4203, payload: 00"
|
|
||||||
status "heating" : "command: 4203, payload: 01"
|
|
||||||
status "cooling" : "command: 4203, payload: 02"
|
|
||||||
|
|
||||||
// reply messages
|
|
||||||
reply "2502": "command: 2503, payload: FF"
|
|
||||||
}
|
|
||||||
|
|
||||||
tiles {
|
|
||||||
valueTile("temperature", "device.temperature", width: 2, height: 2) {
|
|
||||||
state("temperature", label:'${currentValue}°',
|
|
||||||
icon: "http://cdn.device-icons.smartthings.com/Weather/weather2-icn@2x.png",
|
|
||||||
backgroundColors:[
|
|
||||||
[value: 32, color: "#153591"],
|
|
||||||
[value: 44, color: "#1e9cbb"],
|
|
||||||
[value: 59, color: "#90d2a7"],
|
|
||||||
[value: 74, color: "#44b621"],
|
|
||||||
[value: 84, color: "#f1d801"],
|
|
||||||
[value: 92, color: "#d04e00"],
|
|
||||||
[value: 98, color: "#bc2323"]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
standardTile("mode", "device.thermostatMode", inactiveLabel: false) {
|
|
||||||
state "off", label:'${name}', action:"switchMode", icon: "st.Outdoor.outdoor19" ,nextState:"to_heat"
|
|
||||||
state "heat", label:'${name}', action:"switchMode", icon: "st.Weather.weather14", backgroundColor: '#E14902', nextState:"to_cool"
|
|
||||||
state "cool", label:'${name}', action:"switchMode", icon: "st.Weather.weather7", backgroundColor: '#1e9cbb', nextState:"..."
|
|
||||||
state "auto", label:'${name}', action:"switchMode", icon: "st.Weather.weather3", backgroundColor: '#44b621', nextState:"..."
|
|
||||||
state "emergency heat", label:'${name}', action:"switchMode", nextState:"..."
|
|
||||||
state "to_heat", label: "heat", action:"switchMode", nextState:"to_cool"
|
|
||||||
state "to_cool", label: "cool", action:"switchMode", nextState:"..."
|
|
||||||
state "...", label: "...", action:"off", nextState:"off"
|
|
||||||
}
|
|
||||||
|
|
||||||
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false) {
|
|
||||||
state "fanAuto", label:'${name}', action:"switchFanMode", icon: "st.Appliances.appliances11", backgroundColor: '#44b621'
|
|
||||||
state "fanOn", label:'${name}', action:"switchFanMode", icon: "st.Appliances.appliances11", backgroundColor: '#44b621'
|
|
||||||
state "fanCirculate", label:'${name}', action:"switchFanMode", icon: "st.Appliances.appliances11", backgroundColor: '#44b621'
|
|
||||||
}
|
|
||||||
|
|
||||||
valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false)
|
|
||||||
{
|
|
||||||
state "default", label:'Cool\n${currentValue}°F', unit:"F",
|
|
||||||
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("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false)
|
|
||||||
{
|
|
||||||
state "default", label:'Heat\n${currentValue}°F', unit:"F",
|
|
||||||
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"]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
standardTile("heatLevelUp", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false) {
|
|
||||||
state "heatLevelUp", label:' ', action:"heatLevelUp", icon:"st.thermostat.thermostat-up"
|
|
||||||
}
|
|
||||||
standardTile("heatLevelDown", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false) {
|
|
||||||
state "heatLevelDown", label:' ', action:"heatLevelDown", icon:"st.thermostat.thermostat-down"
|
|
||||||
}
|
|
||||||
standardTile("coolLevelUp", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false) {
|
|
||||||
state "coolLevelUp", label:' ', action:"coolLevelUp", icon:"st.thermostat.thermostat-up"
|
|
||||||
}
|
|
||||||
standardTile("coolLevelDown", "device.heatingSetpoint", canChangeIcon: false, inactiveLabel: false) {
|
|
||||||
state "coolLevelDown", label:' ', action:"coolLevelDown", icon:"st.thermostat.thermostat-down"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
|
|
||||||
state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#d04e00"
|
|
||||||
}
|
|
||||||
valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") {
|
|
||||||
state "heat", label:'${currentValue}° heat', backgroundColor:"#ffffff"
|
|
||||||
}
|
|
||||||
controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
|
|
||||||
state "setCoolingSetpoint", action:"quickSetCool", backgroundColor: "#1e9cbb"
|
|
||||||
}
|
|
||||||
valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") {
|
|
||||||
state "cool", label:'${currentValue}° cool', backgroundColor:"#ffffff"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
valueTile("humidity", "device.humidity", inactiveLabel: false) {
|
|
||||||
state "humidity", label:'Humidity\n${currentValue}%', unit:"",
|
|
||||||
icon: "http://cdn.device-icons.smartthings.com/Weather/weather12-icn@2x.png",
|
|
||||||
backgroundColors : [
|
|
||||||
[value: 01, color: "#724529"],
|
|
||||||
[value: 11, color: "#724529"],
|
|
||||||
[value: 21, color: "#724529"],
|
|
||||||
[value: 35, color: "#44b621"],
|
|
||||||
[value: 49, color: "#44b621"],
|
|
||||||
[value: 50, color: "#1e9cbb"]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
valueTile("battery", "device.battery", inactiveLabel: false) {
|
|
||||||
state "battery", label:'Battery\n${currentValue}%', unit:"",
|
|
||||||
backgroundColors : [
|
|
||||||
[value: 20, color: "#720000"],
|
|
||||||
[value: 40, color: "#724529"],
|
|
||||||
[value: 60, color: "#00cccc"],
|
|
||||||
[value: 80, color: "#00b621"],
|
|
||||||
[value: 90, color: "#009c00"],
|
|
||||||
[value: 100, color: "#00ff00"]
|
|
||||||
]h
|
|
||||||
}
|
|
||||||
|
|
||||||
valueTile("thermostatOperatingState", "device.thermostatOperatingState", inactiveLabel: false, decoration: "flat") {
|
|
||||||
state "thermostatOperatingState", label:'${currentValue}', unit:""
|
|
||||||
}
|
|
||||||
|
|
||||||
standardTile("refresh", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
|
|
||||||
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "temperature"
|
|
||||||
details(["temperature", "mode", "fanMode",
|
|
||||||
"heatLevelUp", "heatingSetpoint" , "heatLevelDown", "coolLevelUp",
|
|
||||||
"coolingSetpoint", "coolLevelDown",
|
|
||||||
"humidity", "battery","thermostatOperatingState","refresh"])
|
|
||||||
|
|
||||||
/*main "temperature"
|
|
||||||
details(["temperature", "mode", "fanMode",
|
|
||||||
"heatSliderControl", "heatingSetpoint", "coolSliderControl", "coolingSetpoint",
|
|
||||||
"humidity", "battery","thermostatOperatingState","refresh"])*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def parse(String description)
|
|
||||||
{
|
|
||||||
def result = []
|
|
||||||
if (description == "updated") {
|
|
||||||
} else {
|
|
||||||
def zwcmd = zwave.parse(description, [0x42:2, 0x43:2, 0x31: 2, 0x60: 3])
|
|
||||||
if (zwcmd) {
|
|
||||||
result += zwaveEvent(zwcmd)
|
|
||||||
} else {
|
|
||||||
log.debug "$device.displayName couldn't parse $description"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!result) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
if (result.size() == 1 && (!state.lastbatt || now() - state.lastbatt > 48*60*60*1000)) {
|
|
||||||
result << response(zwave.batteryV1.batteryGet().format())
|
|
||||||
}
|
|
||||||
//log.debug "$device.displayName parsed '$description' to $result"
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
|
|
||||||
def result = null
|
|
||||||
def encapsulatedCommand = cmd.encapsulatedCommand([0x42:2, 0x43:2, 0x31: 2])
|
|
||||||
log.debug ("Command from endpoint ${cmd.sourceEndPoint}: ${encapsulatedCommand}")
|
|
||||||
if (encapsulatedCommand) {
|
|
||||||
result = zwaveEvent(encapsulatedCommand)
|
|
||||||
if (cmd.sourceEndPoint == 1) { // indicates a response to refresh() vs an unrequested update
|
|
||||||
def event = ([] + result)[0] // in case zwaveEvent returns a list
|
|
||||||
def resp = nextRefreshQuery(event?.name)
|
|
||||||
if (resp) {
|
|
||||||
log.debug("sending next refresh query: $resp")
|
|
||||||
result = [] + result + response(["delay 200", resp])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatsetpointv2.ThermostatSetpointReport cmd)
|
|
||||||
{
|
|
||||||
def cmdScale = cmd.scale == 1 ? "F" : "C"
|
|
||||||
def temp = convertTemperatureIfNeeded(cmd.scaledValue, cmdScale, cmd.precision)
|
|
||||||
def unit = getTemperatureScale()
|
|
||||||
def map1 = [ value: temp, unit: unit, displayed: false ]
|
|
||||||
switch (cmd.setpointType) {
|
|
||||||
case 1:
|
|
||||||
map1.name = "heatingSetpoint"
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
map1.name = "coolingSetpoint"
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log.debug "unknown setpointType $cmd.setpointType"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// So we can respond with same format
|
|
||||||
state.size = cmd.size
|
|
||||||
state.scale = cmd.scale
|
|
||||||
state.precision = cmd.precision
|
|
||||||
|
|
||||||
def mode = device.latestValue("thermostatMode")
|
|
||||||
if (mode && map1.name.startsWith(mode) || (mode == "emergency heat" && map1.name == "heatingSetpoint")) {
|
|
||||||
def map2 = [ name: "thermostatSetpoint", value: temp, unit: unit ]
|
|
||||||
[ createEvent(map1), createEvent(map2) ]
|
|
||||||
} else {
|
|
||||||
createEvent(map1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
|
|
||||||
{
|
|
||||||
def map = [:]
|
|
||||||
if (cmd.sensorType == 1) {
|
|
||||||
map.name = "temperature"
|
|
||||||
map.unit = getTemperatureScale()
|
|
||||||
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmd.scale == 1 ? "F" : "C", cmd.precision)
|
|
||||||
} else if (cmd.sensorType == 5) {
|
|
||||||
map.name = "humidity"
|
|
||||||
map.unit = "%"
|
|
||||||
map.value = cmd.scaledSensorValue
|
|
||||||
}
|
|
||||||
createEvent(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport cmd)
|
|
||||||
{
|
|
||||||
def map = [name: "thermostatOperatingState" ]
|
|
||||||
switch (cmd.operatingState) {
|
|
||||||
case physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport.OPERATING_STATE_IDLE:
|
|
||||||
map.value = "idle"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport.OPERATING_STATE_HEATING:
|
|
||||||
map.value = "heating"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport.OPERATING_STATE_COOLING:
|
|
||||||
map.value = "cooling"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport.OPERATING_STATE_FAN_ONLY:
|
|
||||||
map.value = "fan only"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_HEAT:
|
|
||||||
map.value = "pending heat"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_COOL:
|
|
||||||
map.value = "pending cool"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatoperatingstatev2.ThermostatOperatingStateReport.OPERATING_STATE_VENT_ECONOMIZER:
|
|
||||||
map.value = "vent economizer"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
def result = createEvent(map)
|
|
||||||
if (result.isStateChange && device.latestValue("thermostatMode") == "auto" && (result.value == "heating" || result.value == "cooling")) {
|
|
||||||
def thermostatSetpoint = device.latestValue("${result.value}Setpoint")
|
|
||||||
result = [result, createEvent(name: "thermostatSetpoint", value: thermostatSetpoint, unit: getTemperatureScale())]
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatfanstatev1.ThermostatFanStateReport cmd) {
|
|
||||||
def map = [name: "thermostatFanState", unit: ""]
|
|
||||||
switch (cmd.fanOperatingState) {
|
|
||||||
case 0:
|
|
||||||
map.value = "idle"
|
|
||||||
break
|
|
||||||
case 1:
|
|
||||||
map.value = "running"
|
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
map.value = "running high"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
createEvent(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport cmd) {
|
|
||||||
def map = [name: "thermostatMode"]
|
|
||||||
def thermostatSetpoint = null
|
|
||||||
switch (cmd.mode) {
|
|
||||||
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_OFF:
|
|
||||||
map.value = "off"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_HEAT:
|
|
||||||
map.value = "heat"
|
|
||||||
thermostatSetpoint = device.latestValue("heatingSetpoint")
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUXILIARY_HEAT:
|
|
||||||
map.value = "emergency heat"
|
|
||||||
thermostatSetpoint = device.latestValue("heatingSetpoint")
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_COOL:
|
|
||||||
map.value = "cool"
|
|
||||||
thermostatSetpoint = device.latestValue("coolingSetpoint")
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUTO:
|
|
||||||
map.value = "auto"
|
|
||||||
def temp = device.latestValue("temperature")
|
|
||||||
def heatingSetpoint = device.latestValue("heatingSetpoint")
|
|
||||||
def coolingSetpoint = device.latestValue("coolingSetpoint")
|
|
||||||
if (temp && heatingSetpoint && coolingSetpoint) {
|
|
||||||
if (temp < (heatingSetpoint + coolingSetpoint) / 2.0) {
|
|
||||||
thermostatSetpoint = heatingSetpoint
|
|
||||||
} else {
|
|
||||||
thermostatSetpoint = coolingSetpoint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
state.lastTriedMode = map.value
|
|
||||||
if (thermostatSetpoint) {
|
|
||||||
[ createEvent(map), createEvent(name: "thermostatSetpoint", value: thermostatSetpoint, unit: getTemperatureScale()) ]
|
|
||||||
} else {
|
|
||||||
createEvent(map)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport cmd) {
|
|
||||||
def map = [name: "thermostatFanMode", displayed: false]
|
|
||||||
switch (cmd.fanMode) {
|
|
||||||
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_AUTO_LOW:
|
|
||||||
map.value = "fanAuto"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_LOW:
|
|
||||||
map.value = "fanOn"
|
|
||||||
break
|
|
||||||
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_CIRCULATION:
|
|
||||||
map.value = "fanCirculate"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
state.lastTriedFanMode = map.value
|
|
||||||
createEvent(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeSupportedReport cmd) {
|
|
||||||
def supportedModes = ""
|
|
||||||
if(cmd.off) { supportedModes += "off " }
|
|
||||||
if(cmd.heat) { supportedModes += "heat " }
|
|
||||||
if(cmd.auxiliaryemergencyHeat) { supportedModes += "emergency heat " }
|
|
||||||
if(cmd.cool) { supportedModes += "cool " }
|
|
||||||
if(cmd.auto) { supportedModes += "auto " }
|
|
||||||
|
|
||||||
state.supportedModes = supportedModes
|
|
||||||
[ createEvent(name:"supportedModes", value: supportedModes, displayed: false),
|
|
||||||
response(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet()) ]
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) {
|
|
||||||
def supportedFanModes = ""
|
|
||||||
if(cmd.auto) { supportedFanModes += "fanAuto " }
|
|
||||||
if(cmd.low) { supportedFanModes += "fanOn " }
|
|
||||||
if(cmd.circulation) { supportedFanModes += "fanCirculate " }
|
|
||||||
|
|
||||||
state.supportedFanModes = supportedFanModes
|
|
||||||
[ createEvent(name:"supportedFanModes", value: supportedModes, displayed: false),
|
|
||||||
response(refresh()) ]
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
|
|
||||||
log.debug "Zwave event received: $cmd"
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
|
||||||
def map = [ name: "battery", unit: "%" ]
|
|
||||||
if (cmd.batteryLevel == 0xFF) {
|
|
||||||
map.value = 1
|
|
||||||
map.descriptionText = "${device.displayName} battery is low"
|
|
||||||
map.isStateChange = true
|
|
||||||
} else {
|
|
||||||
map.value = cmd.batteryLevel
|
|
||||||
}
|
|
||||||
state.lastbatt = now()
|
|
||||||
createEvent(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
|
||||||
log.warn "Unexpected zwave command $cmd"
|
|
||||||
}
|
|
||||||
|
|
||||||
def refresh() {
|
|
||||||
// Use encapsulation to differentiate refresh cmds from what the thermostat sends proactively on change
|
|
||||||
def cmd = zwave.sensorMultilevelV2.sensorMultilevelGet()
|
|
||||||
zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint:1).encapsulate(cmd).format()
|
|
||||||
}
|
|
||||||
|
|
||||||
def nextRefreshQuery(name) {
|
|
||||||
def cmd = null
|
|
||||||
switch (name) {
|
|
||||||
case "temperature":
|
|
||||||
cmd = zwave.thermostatModeV2.thermostatModeGet()
|
|
||||||
break
|
|
||||||
case "thermostatMode":
|
|
||||||
cmd = zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1)
|
|
||||||
break
|
|
||||||
case "heatingSetpoint":
|
|
||||||
cmd = zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2)
|
|
||||||
break
|
|
||||||
case "coolingSetpoint":
|
|
||||||
cmd = zwave.thermostatFanModeV3.thermostatFanModeGet()
|
|
||||||
break
|
|
||||||
case "thermostatFanMode":
|
|
||||||
cmd = zwave.thermostatOperatingStateV2.thermostatOperatingStateGet()
|
|
||||||
break
|
|
||||||
case "thermostatOperatingState":
|
|
||||||
// get humidity, multilevel sensor get to endpoint 2
|
|
||||||
cmd = zwave.sensorMultilevelV2.sensorMultilevelGet()
|
|
||||||
return zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint:2).encapsulate(cmd).format()
|
|
||||||
default: return null
|
|
||||||
}
|
|
||||||
zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint:1).encapsulate(cmd).format()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def quickSetHeat(degrees) {
|
|
||||||
setHeatingSetpoint(degrees, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
def setHeatingSetpoint(degrees, delay = 30000) {
|
|
||||||
setHeatingSetpoint(degrees.toDouble(), delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def setHeatingSetpoint(Double degrees, Integer delay = 30000) {
|
|
||||||
log.trace "setHeatingSetpoint($degrees, $delay)"
|
|
||||||
def deviceScale = state.scale ?: 1
|
|
||||||
def deviceScaleString = deviceScale == 2 ? "C" : "F"
|
|
||||||
def locationScale = getTemperatureScale()
|
|
||||||
def p = (state.precision == null) ? 1 : state.precision
|
|
||||||
|
|
||||||
def convertedDegrees
|
|
||||||
if (locationScale == "C" && deviceScaleString == "F") {
|
|
||||||
convertedDegrees = celsiusToFahrenheit(degrees)
|
|
||||||
} else if (locationScale == "F" && deviceScaleString == "C") {
|
|
||||||
convertedDegrees = fahrenheitToCelsius(degrees)
|
|
||||||
} else {
|
|
||||||
convertedDegrees = degrees
|
|
||||||
}
|
|
||||||
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 1, scale: deviceScale, precision: p, scaledValue: convertedDegrees).format(),
|
|
||||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format()
|
|
||||||
], delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def quickSetCool(degrees) {
|
|
||||||
setCoolingSetpoint(degrees, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
def setCoolingSetpoint(degrees, delay = 30000) {
|
|
||||||
setCoolingSetpoint(degrees.toDouble(), delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def setCoolingSetpoint(Double degrees, Integer delay = 30000) {
|
|
||||||
log.trace "setCoolingSetpoint($degrees, $delay)"
|
|
||||||
def deviceScale = state.scale ?: 1
|
|
||||||
def deviceScaleString = deviceScale == 2 ? "C" : "F"
|
|
||||||
def locationScale = getTemperatureScale()
|
|
||||||
def p = (state.precision == null) ? 1 : state.precision
|
|
||||||
|
|
||||||
def convertedDegrees
|
|
||||||
if (locationScale == "C" && deviceScaleString == "F") {
|
|
||||||
convertedDegrees = celsiusToFahrenheit(degrees)
|
|
||||||
} else if (locationScale == "F" && deviceScaleString == "C") {
|
|
||||||
convertedDegrees = fahrenheitToCelsius(degrees)
|
|
||||||
} else {
|
|
||||||
convertedDegrees = degrees
|
|
||||||
}
|
|
||||||
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 2, scale: deviceScale, precision: p, scaledValue: convertedDegrees).format(),
|
|
||||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format()
|
|
||||||
], delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def configure() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
|
|
||||||
], 2300)
|
|
||||||
}
|
|
||||||
|
|
||||||
def modes() {
|
|
||||||
["off", "heat", "cool", "auto", "emergency heat"]
|
|
||||||
}
|
|
||||||
|
|
||||||
def switchMode() {
|
|
||||||
def currentMode = device.currentState("thermostatMode")?.value
|
|
||||||
def lastTriedMode = state.lastTriedMode ?: currentMode ?: "off"
|
|
||||||
def supportedModes = getDataByName("supportedModes")
|
|
||||||
def modeOrder = modes()
|
|
||||||
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
|
|
||||||
def nextMode = next(lastTriedMode)
|
|
||||||
if (supportedModes?.contains(currentMode)) {
|
|
||||||
while (!supportedModes.contains(nextMode) && nextMode != "off") {
|
|
||||||
nextMode = next(nextMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.lastTriedMode = nextMode
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[nextMode]).format(),
|
|
||||||
zwave.thermostatModeV2.thermostatModeGet().format()
|
|
||||||
], 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
def switchToMode(nextMode) {
|
|
||||||
def supportedModes = getDataByName("supportedModes")
|
|
||||||
if(supportedModes && !supportedModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported"
|
|
||||||
if (nextMode in modes()) {
|
|
||||||
state.lastTriedMode = nextMode
|
|
||||||
"$nextMode"()
|
|
||||||
} else {
|
|
||||||
log.debug("no mode method '$nextMode'")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def switchFanMode() {
|
|
||||||
def currentMode = device.currentState("thermostatFanMode")?.value
|
|
||||||
def lastTriedMode = state.lastTriedFanMode ?: currentMode ?: "off"
|
|
||||||
def supportedModes = getDataByName("supportedFanModes") ?: "fanAuto fanOn"
|
|
||||||
def modeOrder = ["fanAuto", "fanCirculate", "fanOn"]
|
|
||||||
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
|
|
||||||
def nextMode = next(lastTriedMode)
|
|
||||||
while (!supportedModes?.contains(nextMode) && nextMode != "fanAuto") {
|
|
||||||
nextMode = next(nextMode)
|
|
||||||
}
|
|
||||||
switchToFanMode(nextMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
def switchToFanMode(nextMode) {
|
|
||||||
def supportedFanModes = getDataByName("supportedFanModes")
|
|
||||||
if(supportedFanModes && !supportedFanModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported"
|
|
||||||
|
|
||||||
def returnCommand
|
|
||||||
if (nextMode == "fanAuto") {
|
|
||||||
returnCommand = fanAuto()
|
|
||||||
} else if (nextMode == "fanOn") {
|
|
||||||
returnCommand = fanOn()
|
|
||||||
} else if (nextMode == "fanCirculate") {
|
|
||||||
returnCommand = fanCirculate()
|
|
||||||
} else {
|
|
||||||
log.debug("no fan mode '$nextMode'")
|
|
||||||
}
|
|
||||||
if(returnCommand) state.lastTriedFanMode = nextMode
|
|
||||||
returnCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
def getDataByName(String name) {
|
|
||||||
state[name] ?: device.getDataValue(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
def getModeMap() { [
|
|
||||||
"off": 0,
|
|
||||||
"heat": 1,
|
|
||||||
"cool": 2,
|
|
||||||
"auto": 3,
|
|
||||||
"emergency heat": 4
|
|
||||||
]}
|
|
||||||
|
|
||||||
def setThermostatMode(String value) {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[value]).format(),
|
|
||||||
zwave.thermostatModeV2.thermostatModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def getFanModeMap() { [
|
|
||||||
"auto": 0,
|
|
||||||
"on": 1,
|
|
||||||
"circulate": 6
|
|
||||||
]}
|
|
||||||
|
|
||||||
def setThermostatFanMode(String value) {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: fanModeMap[value]).format(),
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def off() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSet(mode: 0).format(),
|
|
||||||
zwave.thermostatModeV2.thermostatModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def heat() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSet(mode: 1).format(),
|
|
||||||
zwave.thermostatModeV2.thermostatModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def emergencyHeat() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSet(mode: 4).format(),
|
|
||||||
zwave.thermostatModeV2.thermostatModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def cool() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSet(mode: 2).format(),
|
|
||||||
zwave.thermostatModeV2.thermostatModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def auto() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatModeV2.thermostatModeSet(mode: 3).format(),
|
|
||||||
zwave.thermostatModeV2.thermostatModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def fanOn() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 1).format(),
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def fanAuto() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 0).format(),
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
def fanCirculate() {
|
|
||||||
delayBetween([
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 6).format(),
|
|
||||||
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
|
|
||||||
], standardDelay)
|
|
||||||
}
|
|
||||||
|
|
||||||
private getStandardDelay() {
|
|
||||||
1000
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def coolLevelUp(){
|
|
||||||
int nextLevel = device.currentValue("coolingSetpoint") + 1
|
|
||||||
|
|
||||||
if( nextLevel > 99){
|
|
||||||
nextLevel = 99
|
|
||||||
}
|
|
||||||
log.debug "Setting cool set point up to: ${nextLevel}"
|
|
||||||
setCoolingSetpoint(nextLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
def coolLevelDown(){
|
|
||||||
int nextLevel = device.currentValue("coolingSetpoint") - 1
|
|
||||||
|
|
||||||
if( nextLevel < 50){
|
|
||||||
nextLevel = 50
|
|
||||||
}
|
|
||||||
log.debug "Setting cool set point down to: ${nextLevel}"
|
|
||||||
setCoolingSetpoint(nextLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
def heatLevelUp(){
|
|
||||||
int nextLevel = device.currentValue("heatingSetpoint") + 1
|
|
||||||
|
|
||||||
if( nextLevel > 90){
|
|
||||||
nextLevel = 90
|
|
||||||
}
|
|
||||||
log.debug "Setting heat set point up to: ${nextLevel}"
|
|
||||||
setHeatingSetpoint(nextLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
def heatLevelDown(){
|
|
||||||
int nextLevel = device.currentValue("heatingSetpoint") - 1
|
|
||||||
|
|
||||||
if( nextLevel < 40){
|
|
||||||
nextLevel = 40
|
|
||||||
}
|
|
||||||
log.debug "Setting heat set point down to: ${nextLevel}"
|
|
||||||
setHeatingSetpoint(nextLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -8,7 +8,6 @@ metadata {
|
|||||||
definition (name: "Zen Thermostat", namespace: "zenwithin", author: "ZenWithin") {
|
definition (name: "Zen Thermostat", namespace: "zenwithin", author: "ZenWithin") {
|
||||||
capability "Actuator"
|
capability "Actuator"
|
||||||
capability "Thermostat"
|
capability "Thermostat"
|
||||||
capability "Temperature Measurement"
|
|
||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
|
|||||||
@@ -341,13 +341,6 @@ def eventHandler(name, value) {
|
|||||||
|
|
||||||
def eventBuffer = atomicState.eventBuffer
|
def eventBuffer = atomicState.eventBuffer
|
||||||
def epoch = now() / 1000
|
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"]
|
eventBuffer << [key: "$name", value: "$value", epoch: "$epoch"]
|
||||||
|
|
||||||
log.debug eventBuffer
|
log.debug eventBuffer
|
||||||
|
|||||||
@@ -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