mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-04-14 22:05:23 +01:00
Merge branch 'master' into staging
This commit is contained in:
@@ -1,12 +1,9 @@
|
|||||||
/**
|
// keen home smart vent
|
||||||
* Keen Home Smart Vent
|
// http://www.keenhome.io
|
||||||
*
|
// SmartThings Device Handler v1.0.0
|
||||||
* Author: Keen Home
|
|
||||||
* Date: 2015-06-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
metadata {
|
metadata {
|
||||||
definition (name: "Keen Home Smart Vent", namespace: "Keen Home", author: "Gregg Altschul") {
|
definition (name: "Keen Home Smart Vent", namespace: "Keen Home", author: "Keen Home") {
|
||||||
capability "Switch Level"
|
capability "Switch Level"
|
||||||
capability "Switch"
|
capability "Switch"
|
||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
@@ -21,6 +18,7 @@ metadata {
|
|||||||
command "getBattery"
|
command "getBattery"
|
||||||
command "getTemperature"
|
command "getTemperature"
|
||||||
command "setZigBeeIdTile"
|
command "setZigBeeIdTile"
|
||||||
|
command "clearObstruction"
|
||||||
|
|
||||||
fingerprint endpoint: "1",
|
fingerprint endpoint: "1",
|
||||||
profileId: "0104",
|
profileId: "0104",
|
||||||
@@ -42,9 +40,10 @@ metadata {
|
|||||||
// UI tile definitions
|
// UI tile definitions
|
||||||
tiles {
|
tiles {
|
||||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||||
state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#53a7c0"
|
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 "off", action: "switch.on", icon: "st.vents.vent-closed", backgroundColor: "#ffffff"
|
||||||
state "obstructed", action: "switch.off", icon:"st.vents.vent-closed", backgroundColor:"#ff0000"
|
state "obstructed", action: "clearObstruction", icon: "st.vents.vent-closed", backgroundColor: "#ff0000"
|
||||||
|
state "clearing", action: "", icon: "st.vents.vent-closed", backgroundColor: "#ffff33"
|
||||||
}
|
}
|
||||||
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) {
|
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) {
|
||||||
state "level", action:"switch level.setLevel"
|
state "level", action:"switch level.setLevel"
|
||||||
@@ -206,12 +205,12 @@ private Map makeOnOffResult(rawValue) {
|
|||||||
|
|
||||||
private Map makeLevelResult(rawValue) {
|
private Map makeLevelResult(rawValue) {
|
||||||
def linkText = getLinkText(device)
|
def linkText = getLinkText(device)
|
||||||
// log.debug "rawValue: ${rawValue}"
|
|
||||||
def value = Integer.parseInt(rawValue, 16)
|
def value = Integer.parseInt(rawValue, 16)
|
||||||
def rangeMax = 254
|
def rangeMax = 254
|
||||||
|
|
||||||
|
// catch obstruction level
|
||||||
if (value == 255) {
|
if (value == 255) {
|
||||||
log.debug "obstructed"
|
log.debug "${linkText} is obstructed"
|
||||||
// Just return here. Once the vent is power cycled
|
// Just return here. Once the vent is power cycled
|
||||||
// it will go back to the previous level before obstruction.
|
// it will go back to the previous level before obstruction.
|
||||||
// Therefore, no need to update level on the display.
|
// Therefore, no need to update level on the display.
|
||||||
@@ -220,24 +219,9 @@ private Map makeLevelResult(rawValue) {
|
|||||||
value: "obstructed",
|
value: "obstructed",
|
||||||
descriptionText: "${linkText} is obstructed. Please power cycle."
|
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)
|
value = Math.floor(value / rangeMax * 100)
|
||||||
// log.debug "post-value: ${value}"
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
name: "level",
|
name: "level",
|
||||||
@@ -327,35 +311,79 @@ private def makeSerialResult(serial) {
|
|||||||
value: serial,
|
value: serial,
|
||||||
descriptionText: "${linkText} has serial ${serial}" ]
|
descriptionText: "${linkText} has serial ${serial}" ]
|
||||||
}
|
}
|
||||||
/**** COMMAND METHODS ****/
|
|
||||||
// def mfgCode() {
|
|
||||||
// ["zcl mfg-code 0x115B", "delay 200"]
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
// takes a level from 0 to 100 and translates it to a ZigBee move to level with on/off command
|
||||||
|
private def makeLevelCommand(level) {
|
||||||
|
def rangeMax = 254
|
||||||
|
def scaledLevel = Math.round(level * rangeMax / 100)
|
||||||
|
log.debug "scaled level for ${level}%: ${scaledLevel}"
|
||||||
|
|
||||||
|
// convert to hex string and pad to two digits
|
||||||
|
def hexLevel = new BigInteger(scaledLevel.toString()).toString(16).padLeft(2, '0')
|
||||||
|
|
||||||
|
"st cmd 0x${device.deviceNetworkId} 1 8 4 {${hexLevel} 0000}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** COMMAND METHODS ****/
|
||||||
def on() {
|
def on() {
|
||||||
log.debug "on()"
|
def linkText = getLinkText(device)
|
||||||
|
log.debug "open ${linkText}"
|
||||||
|
|
||||||
|
// only change the state if the vent is not obstructed
|
||||||
|
if (device.currentValue("switch") == "obstructed") {
|
||||||
|
log.error("cannot open because ${linkText} is obstructed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sendEvent(makeOnOffResult(1))
|
sendEvent(makeOnOffResult(1))
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 6 1 {}"
|
"st cmd 0x${device.deviceNetworkId} 1 6 1 {}"
|
||||||
}
|
}
|
||||||
|
|
||||||
def off() {
|
def off() {
|
||||||
log.debug "off()"
|
def linkText = getLinkText(device)
|
||||||
|
log.debug "close ${linkText}"
|
||||||
|
|
||||||
|
// only change the state if the vent is not obstructed
|
||||||
|
if (device.currentValue("switch") == "obstructed") {
|
||||||
|
log.error("cannot close because ${linkText} is obstructed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sendEvent(makeOnOffResult(0))
|
sendEvent(makeOnOffResult(0))
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 6 0 {}"
|
"st cmd 0x${device.deviceNetworkId} 1 6 0 {}"
|
||||||
}
|
}
|
||||||
|
|
||||||
// does this work?
|
def clearObstruction() {
|
||||||
def toggle() {
|
def linkText = getLinkText(device)
|
||||||
log.debug "toggle()"
|
log.debug "attempting to clear ${linkText} obstruction"
|
||||||
|
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 6 2 {}"
|
sendEvent([
|
||||||
|
name: "switch",
|
||||||
|
value: "clearing",
|
||||||
|
descriptionText: "${linkText} is clearing obstruction"
|
||||||
|
])
|
||||||
|
|
||||||
|
// send a move command to ensure level attribute gets reset for old, buggy firmware
|
||||||
|
// then send a reset to factory defaults
|
||||||
|
// finally re-configure to ensure reports and binding is still properly set after the rtfd
|
||||||
|
[
|
||||||
|
makeLevelCommand(device.currentValue("level")), "delay 500",
|
||||||
|
"st cmd 0x${device.deviceNetworkId} 1 0 0 {}", "delay 5000"
|
||||||
|
] + configure()
|
||||||
}
|
}
|
||||||
|
|
||||||
def setLevel(value) {
|
def setLevel(value) {
|
||||||
log.debug "setting level: ${value}"
|
log.debug "setting level: ${value}"
|
||||||
|
|
||||||
def linkText = getLinkText(device)
|
def linkText = getLinkText(device)
|
||||||
|
|
||||||
|
// only change the level if the vent is not obstructed
|
||||||
|
def currentState = device.currentValue("switch")
|
||||||
|
|
||||||
|
if (currentState == "obstructed") {
|
||||||
|
log.error("cannot set level because ${linkText} is obstructed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sendEvent(name: "level", value: value)
|
sendEvent(name: "level", value: value)
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
sendEvent(name: "switch", value: "on", descriptionText: "${linkText} is on by setting a level")
|
sendEvent(name: "switch", value: "on", descriptionText: "${linkText} is on by setting a level")
|
||||||
@@ -363,29 +391,26 @@ def setLevel(value) {
|
|||||||
else {
|
else {
|
||||||
sendEvent(name: "switch", value: "off", descriptionText: "${linkText} is off by setting level to 0")
|
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)
|
makeLevelCommand(value)
|
||||||
log.debug "level: ${level}"
|
|
||||||
|
|
||||||
if (level.size() < 2){
|
|
||||||
level = '0' + level
|
|
||||||
}
|
|
||||||
|
|
||||||
"st cmd 0x${device.deviceNetworkId} 1 8 4 {${level} 0000}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def getOnOff() {
|
def getOnOff() {
|
||||||
log.debug "getOnOff()"
|
log.debug "getOnOff()"
|
||||||
|
|
||||||
|
// disallow on/off updates while vent is obstructed
|
||||||
|
if (device.currentValue("switch") == "obstructed") {
|
||||||
|
log.error("cannot update open/close status because ${getLinkText(device)} is obstructed")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
["st rattr 0x${device.deviceNetworkId} 1 0x0006 0"]
|
["st rattr 0x${device.deviceNetworkId} 1 0x0006 0"]
|
||||||
}
|
}
|
||||||
|
|
||||||
def getPressure() {
|
def getPressure() {
|
||||||
log.debug "getPressure()"
|
log.debug "getPressure()"
|
||||||
|
|
||||||
|
// using a Keen Home specific attribute in the pressure measurement cluster
|
||||||
[
|
[
|
||||||
"zcl mfg-code 0x115B", "delay 200",
|
"zcl mfg-code 0x115B", "delay 200",
|
||||||
"zcl global read 0x0403 0x20", "delay 200",
|
"zcl global read 0x0403 0x20", "delay 200",
|
||||||
@@ -395,12 +420,13 @@ def getPressure() {
|
|||||||
|
|
||||||
def getLevel() {
|
def getLevel() {
|
||||||
log.debug "getLevel()"
|
log.debug "getLevel()"
|
||||||
// rattr = read attribute
|
|
||||||
// 0x${} = device net id
|
// disallow level updates while vent is obstructed
|
||||||
// 1 = endpoint
|
if (device.currentValue("switch") == "obstructed") {
|
||||||
// 8 = cluster id (level control, in this case)
|
log.error("cannot update level status because ${getLinkText(device)} is obstructed")
|
||||||
// 0 = attribute within cluster
|
return []
|
||||||
// sendEvent(name: "level", value: value)
|
}
|
||||||
|
|
||||||
["st rattr 0x${device.deviceNetworkId} 1 0x0008 0x0000"]
|
["st rattr 0x${device.deviceNetworkId} 1 0x0008 0x0000"]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,78 +451,59 @@ def setZigBeeIdTile() {
|
|||||||
name: "zigbeeId",
|
name: "zigbeeId",
|
||||||
value: device.zigbeeId,
|
value: device.zigbeeId,
|
||||||
descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ])
|
descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ])
|
||||||
return [
|
return [
|
||||||
name: "zigbeeId",
|
name: "zigbeeId",
|
||||||
value: device.zigbeeId,
|
value: device.zigbeeId,
|
||||||
descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ]
|
descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
getOnOff() +
|
getOnOff() +
|
||||||
getLevel() +
|
getLevel() +
|
||||||
getTemperature() +
|
getTemperature() +
|
||||||
getPressure() +
|
getPressure() +
|
||||||
getBattery()
|
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() {
|
def configure() {
|
||||||
log.debug "CONFIGURE"
|
log.debug "CONFIGURE"
|
||||||
log.debug "zigbeeId: ${device.hub.zigbeeId}"
|
|
||||||
|
|
||||||
|
// get ZigBee ID by hidden tile because that's the only way we can do it
|
||||||
setZigBeeIdTile()
|
setZigBeeIdTile()
|
||||||
|
|
||||||
def configCmds = [
|
def configCmds = [
|
||||||
// binding commands
|
// bind reporting clusters to hub
|
||||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0006 {${device.zigbeeId}} {}", "delay 500",
|
"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 0x0008 {${device.zigbeeId}} {}", "delay 500",
|
||||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0402 {${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 0x0403 {${device.zigbeeId}} {}", "delay 500",
|
||||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0001 {${device.zigbeeId}} {}", "delay 500",
|
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0001 {${device.zigbeeId}} {}", "delay 500"
|
||||||
|
|
||||||
// configure report commands
|
// configure report commands
|
||||||
// [cluster] [attr] [type] [min-interval] [max-interval] [min-change]
|
// zcl global send-me-a-report [cluster] [attr] [type] [min-interval] [max-interval] [min-change]
|
||||||
|
|
||||||
// mike 2015/06/22: preconfigured; see tech spec
|
// report with these parameters is preconfigured in firmware, can be overridden here
|
||||||
// vent on/off state - type: boolean, change: 1
|
// vent on/off state - type: boolean, change: 1
|
||||||
// "zcl global send-me-a-report 6 0 0x10 5 60 {01}", "delay 200",
|
// "zcl global send-me-a-report 6 0 0x10 5 60 {01}", "delay 200",
|
||||||
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||||
|
|
||||||
// mike 2015/06/22: preconfigured; see tech spec
|
// report with these parameters is preconfigured in firmware, can be overridden here
|
||||||
// vent level - type: int8u, change: 1
|
// vent level - type: int8u, change: 1
|
||||||
// "zcl global send-me-a-report 8 0 0x20 5 60 {01}", "delay 200",
|
// "zcl global send-me-a-report 8 0 0x20 5 60 {01}", "delay 200",
|
||||||
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||||
|
|
||||||
// mike 2015/06/22: temp and pressure reports are preconfigured, but
|
// report with these parameters is preconfigured in firmware, can be overridden here
|
||||||
// we'd like to override their settings for our own purposes
|
|
||||||
// temperature - type: int16s, change: 0xA = 10 = 0.1C
|
// temperature - type: int16s, change: 0xA = 10 = 0.1C
|
||||||
"zcl global send-me-a-report 0x0402 0 0x29 10 60 {0A00}", "delay 200",
|
// "zcl global send-me-a-report 0x0402 0 0x29 60 60 {0A00}", "delay 200",
|
||||||
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||||
|
|
||||||
// mike 2015/06/22: use new custom pressure attribute
|
// report with these parameters is preconfigured in firmware, can be overridden here
|
||||||
// pressure - type: int32u, change: 1 = 0.1Pa
|
// keen home custom pressure (tenths of Pascals) - type: int32u, change: 1 = 0.1Pa
|
||||||
"zcl mfg-code 0x115B", "delay 200",
|
// "zcl mfg-code 0x115B", "delay 200",
|
||||||
"zcl global send-me-a-report 0x0403 0x20 0x22 10 60 {010000}", "delay 200",
|
// "zcl global send-me-a-report 0x0403 0x20 0x22 60 60 {010000}", "delay 200",
|
||||||
"send 0x${device.deviceNetworkId} 1 1", "delay 1500"
|
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||||
|
|
||||||
// mike 2015/06/22: preconfigured; see tech spec
|
// report with these parameters is preconfigured in firmware, can be overridden here
|
||||||
// battery - type: int8u, change: 1
|
// battery - type: int8u, change: 1
|
||||||
// "zcl global send-me-a-report 1 0x21 0x20 60 3600 {01}", "delay 200",
|
// "zcl global send-me-a-report 1 0x21 0x20 60 3600 {01}", "delay 200",
|
||||||
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ definition(
|
|||||||
description: "Use this free SmartApp in conjunction with the ObyThing Music app for your Mac to control and automate music and more with iTunes and SmartThings.",
|
description: "Use this free SmartApp in conjunction with the ObyThing Music app for your Mac to control and automate music and more with iTunes and SmartThings.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "http://obycode.com/obything/ObyThingSTLogo.png",
|
iconUrl: "http://obycode.com/obything/ObyThingSTLogo.png",
|
||||||
iconX2Url: "http://obycode.com/obything/ObyThingSTLogo@2x.png")
|
iconX2Url: "http://obycode.com/obything/ObyThingSTLogo@2x.png",
|
||||||
|
singleInstance: true)
|
||||||
|
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ definition(
|
|||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/netamo-icon-1.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/netamo-icon-1.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/netamo-icon-1%402x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/netamo-icon-1%402x.png",
|
||||||
oauth: true
|
oauth: true,
|
||||||
|
singleInstance: true
|
||||||
){
|
){
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ definition(
|
|||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/jawbone-up.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/jawbone-up.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/jawbone-up@2x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/jawbone-up@2x.png",
|
||||||
oauth: true,
|
oauth: true,
|
||||||
usePreferencesForAuthorization: false
|
usePreferencesForAuthorization: false,
|
||||||
|
singleInstance: true
|
||||||
) {
|
) {
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ definition(
|
|||||||
iconUrl: "http://i.imgur.com/HU0ANBp.png",
|
iconUrl: "http://i.imgur.com/HU0ANBp.png",
|
||||||
iconX2Url: "http://i.imgur.com/HU0ANBp.png",
|
iconX2Url: "http://i.imgur.com/HU0ANBp.png",
|
||||||
iconX3Url: "http://i.imgur.com/HU0ANBp.png",
|
iconX3Url: "http://i.imgur.com/HU0ANBp.png",
|
||||||
oauth: true)
|
oauth: true,
|
||||||
|
singleInstance: true)
|
||||||
|
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.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"
|
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||||
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ definition(
|
|||||||
description: "Connect your Ecobee thermostat to SmartThings.",
|
description: "Connect your Ecobee thermostat to SmartThings.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee@2x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee@2x.png",
|
||||||
|
singleInstance: true
|
||||||
) {
|
) {
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "serverUrl"
|
appSetting "serverUrl"
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ definition(
|
|||||||
description: "Connect and take pictures using your Foscam camera from inside the Smartthings app.",
|
description: "Connect and take pictures using your Foscam camera from inside the Smartthings app.",
|
||||||
category: "SmartThings Internal",
|
category: "SmartThings Internal",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/foscam.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/foscam.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/foscam@2x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/foscam@2x.png",
|
||||||
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ definition(
|
|||||||
description: "Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Adjust colors by going to the Thing detail screen for your Hue lights (tap the gear on Hue tiles).\n\nPlease update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.",
|
description: "Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Adjust colors by going to the Thing detail screen for your Hue lights (tap the gear on Hue tiles).\n\nPlease update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png",
|
||||||
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ definition(
|
|||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/life360.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/life360.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/life360@2x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/life360@2x.png",
|
||||||
oauth: [displayName: "Life360", displayLink: "Life360"]
|
oauth: [displayName: "Life360", displayLink: "Life360"],
|
||||||
|
singleInstance: true
|
||||||
) {
|
) {
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ definition(
|
|||||||
iconUrl: "https://cloud.lifx.com/images/lifx.png",
|
iconUrl: "https://cloud.lifx.com/images/lifx.png",
|
||||||
iconX2Url: "https://cloud.lifx.com/images/lifx.png",
|
iconX2Url: "https://cloud.lifx.com/images/lifx.png",
|
||||||
iconX3Url: "https://cloud.lifx.com/images/lifx.png",
|
iconX3Url: "https://cloud.lifx.com/images/lifx.png",
|
||||||
oauth: true) {
|
oauth: true,
|
||||||
|
singleInstance: true) {
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ definition(
|
|||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony%402x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony%402x.png",
|
||||||
oauth: [displayName: "Logitech Harmony", displayLink: "http://www.logitech.com/en-us/harmony-remotes"]
|
oauth: [displayName: "Logitech Harmony", displayLink: "http://www.logitech.com/en-us/harmony-remotes"],
|
||||||
|
singleInstance: true
|
||||||
){
|
){
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ definition(
|
|||||||
description: "Allows you to control your Samsung TV from the SmartThings app. Perform basic functions like power Off, source, volume, channels and other remote control functions.",
|
description: "Allows you to control your Samsung TV from the SmartThings app. Perform basic functions like power Off, source, volume, channels and other remote control functions.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Samsung/samsung-remote%402x.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Samsung/samsung-remote%402x.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Samsung/samsung-remote%403x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Samsung/samsung-remote%403x.png",
|
||||||
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ definition(
|
|||||||
description: "Integrate your Tesla car with SmartThings.",
|
description: "Integrate your Tesla car with SmartThings.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/tesla-app%402x.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/tesla-app%402x.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/tesla-app%403x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/tesla-app%403x.png",
|
||||||
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ definition(
|
|||||||
description: "Allows you to integrate your WeMo Switch and Wemo Motion sensor with SmartThings.",
|
description: "Allows you to integrate your WeMo Switch and Wemo Motion sensor with SmartThings.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo@2x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo@2x.png",
|
||||||
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ definition(
|
|||||||
category: "Connections",
|
category: "Connections",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/withings.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/withings.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/withings%402x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/withings%402x.png",
|
||||||
oauth: true
|
oauth: true,
|
||||||
|
singleInstance: true
|
||||||
) {
|
) {
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ definition(
|
|||||||
category: "SmartThings Internal",
|
category: "SmartThings Internal",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png",
|
||||||
oauth: true
|
oauth: true,
|
||||||
|
singleInstance: true
|
||||||
) {
|
) {
|
||||||
appSetting "serverUrl"
|
appSetting "serverUrl"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ definition(
|
|||||||
description: "Connect your Quirky to SmartThings.",
|
description: "Connect your Quirky to SmartThings.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/quirky.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/quirky.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/quirky@2x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/quirky@2x.png",
|
||||||
|
singleInstance: true
|
||||||
) {
|
) {
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ definition(
|
|||||||
description: "Connect your TCP bulbs to SmartThings using Cloud to Cloud integration. You must create a remote login acct on TCP Mobile App.",
|
description: "Connect your TCP bulbs to SmartThings using Cloud to Cloud integration. You must create a remote login acct on TCP Mobile App.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/tcp.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/tcp.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/tcp@2x.png"
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/tcp@2x.png",
|
||||||
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user