From 8ba5eaf74dbd79ae8b210fed750317133b6429b9 Mon Sep 17 00:00:00 2001 From: Mike Robinet Date: Thu, 24 Sep 2015 15:51:51 -0500 Subject: [PATCH 1/2] CREX-3129 Update parent and service manager apps to be singleton --- .../obything-music-connect.src/obything-music-connect.groovy | 3 ++- smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy | 3 ++- .../juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy | 3 ++- .../weather-underground-pws-connect.groovy | 3 ++- .../bose-soundtouch-connect.src/bose-soundtouch-connect.groovy | 3 ++- smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy | 3 ++- smartapps/smartthings/foscam-connect.src/foscam-connect.groovy | 3 ++- smartapps/smartthings/hue-connect.src/hue-connect.groovy | 3 ++- .../smartthings/life360-connect.src/life360-connect.groovy | 3 ++- smartapps/smartthings/lifx-connect.src/lifx-connect.groovy | 3 ++- .../logitech-harmony-connect.groovy | 3 ++- .../samsung-tv-connect.src/samsung-tv-connect.groovy | 3 ++- smartapps/smartthings/tesla-connect.src/tesla-connect.groovy | 3 ++- smartapps/smartthings/wemo-connect.src/wemo-connect.groovy | 3 ++- smartapps/smartthings/withings.src/withings.groovy | 3 ++- smartapps/smartthings/yoics-connect.src/yoics-connect.groovy | 3 ++- smartapps/wackford/quirky-connect.src/quirky-connect.groovy | 3 ++- .../wackford/tcp-bulbs-connect.src/tcp-bulbs-connect.groovy | 3 ++- 18 files changed, 36 insertions(+), 18 deletions(-) diff --git a/smartapps/com-obycode/obything-music-connect.src/obything-music-connect.groovy b/smartapps/com-obycode/obything-music-connect.src/obything-music-connect.groovy index bad8f99..f6dd374 100644 --- a/smartapps/com-obycode/obything-music-connect.src/obything-music-connect.groovy +++ b/smartapps/com-obycode/obything-music-connect.src/obything-music-connect.groovy @@ -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.", category: "SmartThings Labs", 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 { diff --git a/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy b/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy index 8260360..905cdde 100644 --- a/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy +++ b/smartapps/dianoga/netatmo-connect.src/netatmo-connect.groovy @@ -22,7 +22,8 @@ definition( category: "SmartThings Labs", 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", - oauth: true + oauth: true, + singleInstance: true ){ appSetting "clientId" appSetting "clientSecret" diff --git a/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy b/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy index 7d9e193..afa767d 100644 --- a/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy +++ b/smartapps/juano2310/jawbone-up-connect.src/jawbone-up-connect.groovy @@ -13,7 +13,8 @@ definition( iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/jawbone-up.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/jawbone-up@2x.png", oauth: true, - usePreferencesForAuthorization: false + usePreferencesForAuthorization: false, + singleInstance: true ) { appSetting "clientId" appSetting "clientSecret" diff --git a/smartapps/mager/weather-underground-pws-connect.src/weather-underground-pws-connect.groovy b/smartapps/mager/weather-underground-pws-connect.src/weather-underground-pws-connect.groovy index 620911b..21ecb1d 100644 --- a/smartapps/mager/weather-underground-pws-connect.src/weather-underground-pws-connect.groovy +++ b/smartapps/mager/weather-underground-pws-connect.src/weather-underground-pws-connect.groovy @@ -26,7 +26,8 @@ definition( iconUrl: "http://i.imgur.com/HU0ANBp.png", iconX2Url: "http://i.imgur.com/HU0ANBp.png", iconX3Url: "http://i.imgur.com/HU0ANBp.png", - oauth: true) + oauth: true, + singleInstance: true) preferences { diff --git a/smartapps/smartthings/bose-soundtouch-connect.src/bose-soundtouch-connect.groovy b/smartapps/smartthings/bose-soundtouch-connect.src/bose-soundtouch-connect.groovy index bc7cc82..bcb5d8f 100644 --- a/smartapps/smartthings/bose-soundtouch-connect.src/bose-soundtouch-connect.groovy +++ b/smartapps/smartthings/bose-soundtouch-connect.src/bose-soundtouch-connect.groovy @@ -21,7 +21,8 @@ category: "SmartThings Labs", 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" + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + singleInstance: true ) preferences { diff --git a/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy b/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy index 12b703d..8b7a02e 100644 --- a/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy +++ b/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy @@ -26,7 +26,8 @@ definition( description: "Connect your Ecobee thermostat to SmartThings.", category: "SmartThings Labs", 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 "serverUrl" diff --git a/smartapps/smartthings/foscam-connect.src/foscam-connect.groovy b/smartapps/smartthings/foscam-connect.src/foscam-connect.groovy index acf3ffb..51ec6fa 100644 --- a/smartapps/smartthings/foscam-connect.src/foscam-connect.groovy +++ b/smartapps/smartthings/foscam-connect.src/foscam-connect.groovy @@ -23,7 +23,8 @@ definition( description: "Connect and take pictures using your Foscam camera from inside the Smartthings app.", category: "SmartThings Internal", 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 { diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 9833438..64cafd0 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -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.", category: "SmartThings Labs", 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 { diff --git a/smartapps/smartthings/life360-connect.src/life360-connect.groovy b/smartapps/smartthings/life360-connect.src/life360-connect.groovy index eabf545..ab98fa0 100644 --- a/smartapps/smartthings/life360-connect.src/life360-connect.groovy +++ b/smartapps/smartthings/life360-connect.src/life360-connect.groovy @@ -22,7 +22,8 @@ definition( category: "SmartThings Labs", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/life360.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 "clientSecret" diff --git a/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy b/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy index 645e5ac..dea5939 100644 --- a/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy +++ b/smartapps/smartthings/lifx-connect.src/lifx-connect.groovy @@ -13,7 +13,8 @@ definition( iconUrl: "https://cloud.lifx.com/images/lifx.png", iconX2Url: "https://cloud.lifx.com/images/lifx.png", iconX3Url: "https://cloud.lifx.com/images/lifx.png", - oauth: true) { + oauth: true, + singleInstance: true) { appSetting "clientId" appSetting "clientSecret" } diff --git a/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy b/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy index aefd723..0816d03 100644 --- a/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy +++ b/smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy @@ -43,7 +43,8 @@ definition( category: "SmartThings Labs", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/harmony.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 "clientSecret" diff --git a/smartapps/smartthings/samsung-tv-connect.src/samsung-tv-connect.groovy b/smartapps/smartthings/samsung-tv-connect.src/samsung-tv-connect.groovy index aa6a228..6a15dc9 100644 --- a/smartapps/smartthings/samsung-tv-connect.src/samsung-tv-connect.groovy +++ b/smartapps/smartthings/samsung-tv-connect.src/samsung-tv-connect.groovy @@ -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.", category: "SmartThings Labs", 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 { diff --git a/smartapps/smartthings/tesla-connect.src/tesla-connect.groovy b/smartapps/smartthings/tesla-connect.src/tesla-connect.groovy index 87b9586..5022c42 100644 --- a/smartapps/smartthings/tesla-connect.src/tesla-connect.groovy +++ b/smartapps/smartthings/tesla-connect.src/tesla-connect.groovy @@ -23,7 +23,8 @@ definition( description: "Integrate your Tesla car with SmartThings.", category: "SmartThings Labs", 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 { diff --git a/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy b/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy index 34f20b1..d79ae63 100644 --- a/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy +++ b/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy @@ -22,7 +22,8 @@ definition( description: "Allows you to integrate your WeMo Switch and Wemo Motion sensor with SmartThings.", category: "SmartThings Labs", 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 { diff --git a/smartapps/smartthings/withings.src/withings.groovy b/smartapps/smartthings/withings.src/withings.groovy index 872e653..24cfcd3 100644 --- a/smartapps/smartthings/withings.src/withings.groovy +++ b/smartapps/smartthings/withings.src/withings.groovy @@ -24,7 +24,8 @@ definition( category: "Connections", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/withings.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/withings%402x.png", - oauth: true + oauth: true, + singleInstance: true ) { appSetting "clientId" appSetting "clientSecret" diff --git a/smartapps/smartthings/yoics-connect.src/yoics-connect.groovy b/smartapps/smartthings/yoics-connect.src/yoics-connect.groovy index aebd0b5..cd18e88 100644 --- a/smartapps/smartthings/yoics-connect.src/yoics-connect.groovy +++ b/smartapps/smartthings/yoics-connect.src/yoics-connect.groovy @@ -24,7 +24,8 @@ definition( category: "SmartThings Internal", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png", - oauth: true + oauth: true, + singleInstance: true ) { appSetting "serverUrl" } diff --git a/smartapps/wackford/quirky-connect.src/quirky-connect.groovy b/smartapps/wackford/quirky-connect.src/quirky-connect.groovy index 325f57d..30f5b55 100644 --- a/smartapps/wackford/quirky-connect.src/quirky-connect.groovy +++ b/smartapps/wackford/quirky-connect.src/quirky-connect.groovy @@ -58,7 +58,8 @@ definition( description: "Connect your Quirky to SmartThings.", category: "SmartThings Labs", 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 "clientSecret" diff --git a/smartapps/wackford/tcp-bulbs-connect.src/tcp-bulbs-connect.groovy b/smartapps/wackford/tcp-bulbs-connect.src/tcp-bulbs-connect.groovy index 9f0e5a7..69b6e4c 100644 --- a/smartapps/wackford/tcp-bulbs-connect.src/tcp-bulbs-connect.groovy +++ b/smartapps/wackford/tcp-bulbs-connect.src/tcp-bulbs-connect.groovy @@ -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.", category: "SmartThings Labs", 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 ) From cbd5c91d5224ff388f90443dfda7e21850d80e76 Mon Sep 17 00:00:00 2001 From: Mike Cousins Date: Thu, 22 Oct 2015 13:22:53 -0400 Subject: [PATCH 2/2] update keen home smart vent device handler --- .../keen-home-smart-vent.groovy | 195 +++++++++--------- 1 file changed, 101 insertions(+), 94 deletions(-) diff --git a/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy b/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy index c2e0556..232378a 100644 --- a/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy +++ b/devicetypes/keen-home/keen-home-smart-vent.src/keen-home-smart-vent.groovy @@ -1,12 +1,9 @@ -/** - * Keen Home Smart Vent - * - * Author: Keen Home - * Date: 2015-06-23 - */ +// keen home smart vent +// http://www.keenhome.io +// SmartThings Device Handler v1.0.0 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" capability "Configuration" @@ -21,6 +18,7 @@ metadata { command "getBattery" command "getTemperature" command "setZigBeeIdTile" + command "clearObstruction" fingerprint endpoint: "1", profileId: "0104", @@ -42,9 +40,10 @@ metadata { // 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" + 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: "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) { state "level", action:"switch level.setLevel" @@ -206,12 +205,12 @@ private Map makeOnOffResult(rawValue) { private Map makeLevelResult(rawValue) { def linkText = getLinkText(device) - // log.debug "rawValue: ${rawValue}" def value = Integer.parseInt(rawValue, 16) def rangeMax = 254 + // catch obstruction level if (value == 255) { - log.debug "obstructed" + log.debug "${linkText} is 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. @@ -220,24 +219,9 @@ private Map makeLevelResult(rawValue) { 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", @@ -327,35 +311,79 @@ private def makeSerialResult(serial) { value: 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() { - 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)) "st cmd 0x${device.deviceNetworkId} 1 6 1 {}" } 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)) "st cmd 0x${device.deviceNetworkId} 1 6 0 {}" } -// does this work? -def toggle() { - log.debug "toggle()" +def clearObstruction() { + def linkText = getLinkText(device) + 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) { log.debug "setting level: ${value}" - 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) if (value > 0) { sendEvent(name: "switch", value: "on", descriptionText: "${linkText} is on by setting a level") @@ -363,29 +391,26 @@ def setLevel(value) { 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}" + makeLevelCommand(value) } - def 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"] } def getPressure() { log.debug "getPressure()" + + // using a Keen Home specific attribute in the pressure measurement cluster [ "zcl mfg-code 0x115B", "delay 200", "zcl global read 0x0403 0x20", "delay 200", @@ -395,12 +420,13 @@ def getPressure() { 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) + + // disallow level updates while vent is obstructed + if (device.currentValue("switch") == "obstructed") { + log.error("cannot update level status because ${getLinkText(device)} is obstructed") + return [] + } + ["st rattr 0x${device.deviceNetworkId} 1 0x0008 0x0000"] } @@ -425,78 +451,59 @@ def setZigBeeIdTile() { name: "zigbeeId", value: device.zigbeeId, descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ]) - return [ + return [ name: "zigbeeId", value: device.zigbeeId, descriptionText: "${linkText} has zigbeeId ${device.zigbeeId}" ] } def refresh() { - getOnOff() + + 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}" + // get ZigBee ID by hidden tile because that's the only way we can do it setZigBeeIdTile() 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 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] + "zdo bind 0x${device.deviceNetworkId} 1 1 0x0001 {${device.zigbeeId}} {}", "delay 500" - // mike 2015/06/22: preconfigured; see tech spec + // configure report commands + // zcl global send-me-a-report [cluster] [attr] [type] [min-interval] [max-interval] [min-change] + + // report with these parameters is preconfigured in firmware, can be overridden here // 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 + // report with these parameters is preconfigured in firmware, can be overridden here // 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 + // report with these parameters is preconfigured in firmware, can be overridden here // 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", + // "zcl global send-me-a-report 0x0402 0 0x29 60 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" + // report with these parameters is preconfigured in firmware, can be overridden here + // keen home custom pressure (tenths of Pascals) - type: int32u, change: 1 = 0.1Pa + // "zcl mfg-code 0x115B", "delay 200", + // "zcl global send-me-a-report 0x0403 0x20 0x22 60 60 {010000}", "delay 200", + // "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 // "zcl global send-me-a-report 1 0x21 0x20 60 3600 {01}", "delay 200", // "send 0x${device.deviceNetworkId} 1 1", "delay 1500",