Compare commits

..

1 Commits

Author SHA1 Message Date
Raja
f521495569 MSA-2039: Test publication 2017-06-13 22:46:31 -07:00
16 changed files with 126 additions and 157 deletions

View File

@@ -9,7 +9,7 @@ apply plugin: 'smartthings-slack'
buildscript { buildscript {
dependencies { dependencies {
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.12" classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.11"
} }
repositories { repositories {
mavenLocal() mavenLocal()
@@ -19,7 +19,7 @@ buildscript {
username smartThingsArtifactoryUserName username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword password smartThingsArtifactoryPassword
} }
url "https://smartthings.jfrog.io/smartthings/libs-release-local" url "https://artifactory.smartthings.com/libs-release-local"
} }
} }
} }
@@ -32,7 +32,7 @@ repositories {
username smartThingsArtifactoryUserName username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword password smartThingsArtifactoryPassword
} }
url "https://smartthings.jfrog.io/smartthings/libs-release-local" url "https://artifactory.smartthings.com/libs-release-local"
} }
} }
@@ -51,10 +51,10 @@ sourceSets {
dependencies { dependencies {
devicetypesCompile 'org.codehaus.groovy:groovy-all:2.4.7' devicetypesCompile 'org.codehaus.groovy:groovy-all:2.4.7'
devicetypesCompile 'smartthings:appengine-z-wave:0.1.3' devicetypesCompile 'smartthings:appengine-z-wave:0.1.2'
devicetypesCompile 'smartthings:appengine-zigbee:0.1.12' devicetypesCompile 'smartthings:appengine-zigbee:0.1.11'
smartappsCompile 'org.codehaus.groovy:groovy-all:2.4.7' smartappsCompile 'org.codehaus.groovy:groovy-all:2.4.7'
smartappsCompile 'smartthings:appengine-common:0.1.9' smartappsCompile 'smartthings:appengine-common:0.1.8'
smartappsCompile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1' smartappsCompile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
smartappsCompile 'org.grails:grails-web:2.3.11' smartappsCompile 'org.grails:grails-web:2.3.11'
smartappsCompile 'org.json:json:20140107' smartappsCompile 'org.json:json:20140107'
@@ -74,19 +74,19 @@ slackSendMessage {
String username String username
switch (branch) { switch (branch) {
case 'master': case 'master':
username = 'DEV' username = 'Hickory'
iconUrl = wolverine iconUrl = wolverine
color = '#35D0F2' color = '#35D0F2'
messageText = 'Began deployment of _SmartThingsPublic[master]_ branch to the _Dev_ environments.' messageText = 'Began deployment of _SmartThingsPublic[master]_ branch to the _Dev_ environments.'
break break
case 'staging': case 'staging':
username = 'STG' username = 'Dickory'
iconUrl = beach iconUrl = beach
color = '#FFDE20' color = '#FFDE20'
messageText = 'Began deployment of _SmartThingsPublic[staging]_ branch to the _Staging_ environments.' messageText = 'Began deployment of _SmartThingsPublic[staging]_ branch to the _Staging_ environments.'
break break
case 'production': case 'production':
username = 'PRD' username = 'Dock'
iconUrl = drinks iconUrl = drinks
color = '#FF1D23' color = '#FF1D23'
messageText = 'Began deployment of _SmartThingsPublic[production]_ branch to the _Prod_ environments.' messageText = 'Began deployment of _SmartThingsPublic[production]_ branch to the _Prod_ environments.'

View File

@@ -1,2 +0,0 @@
.st-ignore
README.md

View File

@@ -1,34 +0,0 @@
# Aeon Labs Key Fob
Cloud Execution
Works with:
* [Aeon Labs Key Fob](http://aeotec.com/z-wave-key-fob-remote-control)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#troubleshooting)
## Capabilities
* **Actuator** - represents device has commands
* **Button** - represents a device with one or more buttons
* **Holdable Button** - represents a device with one or more holdable buttons
* **Configuration** - allows for configuration of devices
* **Sensor** - detects sensor events
* **Battery** - defines device uses a battery
* **Health Check** - indicates ability to get device health notifications
## Device Health
Aeon Key Fob is a ZWave totally sleepy device and is marked offline only in the case when Hub is offline.
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the sensor is out of range.
Pairing needs to be tried again by placing the sensor closer to the hub.
Instructions related to pairing, resetting and removing the Aeon Labs Key Fob from SmartThings can be found in the following link:
* [Aeotec Key Fob Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202294120-Aeon-Labs-Key-Fob)

View File

@@ -1,4 +1,3 @@
import groovy.json.JsonOutput
/** /**
* Copyright 2015 SmartThings * Copyright 2015 SmartThings
* *
@@ -20,7 +19,6 @@ metadata {
capability "Configuration" capability "Configuration"
capability "Sensor" capability "Sensor"
capability "Battery" capability "Battery"
capability "Health Check"
fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x80,0x84,0x85" fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x80,0x84,0x85"
fingerprint mfr: "0086", prod: "0001", model: "0026", deviceJoinName: "Aeon Panic Button" fingerprint mfr: "0086", prod: "0001", model: "0026", deviceJoinName: "Aeon Panic Button"
@@ -133,9 +131,6 @@ def updated() {
} }
def initialize() { def initialize() {
// Arrival sensors only goes OFFLINE when Hub is off
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zigbee", scheme:"untracked"]), displayed: false)
def zwMap = getZwaveInfo() def zwMap = getZwaveInfo()
def buttons = 4 // Default for Key Fob def buttons = 4 // Default for Key Fob

View File

@@ -251,4 +251,4 @@ def huesatToRGB(float hue, float sat) {
case 4: return [t, p, 255] case 4: return [t, p, 255]
case 5: return [255, p, q] case 5: return [255, p, q]
} }
} }

View File

@@ -1,2 +0,0 @@
.st-ignore
README.md

View File

@@ -1,33 +0,0 @@
# Aeon Minimote
Cloud Execution
Works with:
* [Aeotec Minimote](http://aeotec.com/small-z-wave-remote-control)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#troubleshooting)
## Capabilities
* **Actuator** - represents device has commands
* **Button** - represents a device with one or more buttons
* **Holdable Button** - represents a device with one or more holdable buttons
* **Configuration** - allows for configuration of devices
* **Sensor** - detects sensor events
* **Health Check** - indicates ability to get device health notifications
## Device Health
Aeon Minimote is a ZWave totally sleepy device and is marked offline only in the case when Hub is offline.
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the sensor is out of range.
Pairing needs to be tried again by placing the sensor closer to the hub.
Instructions related to pairing, resetting and removing the Aeotec Minimote from SmartThings can be found in the following link:
* [Aeotec Minimote Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202087904-Aeotec-Minimote)

View File

@@ -1,4 +1,3 @@
import groovy.json.JsonOutput
/** /**
* Copyright 2015 SmartThings * Copyright 2015 SmartThings
* *
@@ -19,7 +18,6 @@ metadata {
capability "Holdable Button" capability "Holdable Button"
capability "Configuration" capability "Configuration"
capability "Sensor" capability "Sensor"
capability "Health Check"
fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x9B", outClusters: "0x26,0x2B" fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x9B", outClusters: "0x26,0x2B"
fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x9B,0x85,0x84", outClusters: "0x26" // old style with numbered buttons fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x9B,0x85,0x84", outClusters: "0x26" // old style with numbered buttons
@@ -121,7 +119,5 @@ def updated() {
} }
def initialize() { def initialize() {
// Arrival sensors only goes OFFLINE when Hub is off
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zigbee", scheme:"untracked"]), displayed: false)
sendEvent(name: "numberOfButtons", value: 4) sendEvent(name: "numberOfButtons", value: 4)
} }

View File

@@ -70,7 +70,7 @@ metadata {
state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat" state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat"
state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool" state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool"
state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto" state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto"
state "auxheatonly", action:"switchMode", icon: "st.thermostat.emergency-heat" state "emergency heat", action:"switchMode", icon: "st.thermostat.emergency-heat" // emergency heat = auxHeatOnly
state "updating", label:"Working", icon: "st.secondary.secondary" state "updating", label:"Working", icon: "st.secondary.secondary"
} }
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") { standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
@@ -156,49 +156,47 @@ void poll() {
def generateEvent(Map results) { def generateEvent(Map results) {
log.debug "parsing data $results" log.debug "parsing data $results"
if(results) { if(results) {
results.each { name, value ->
def linkText = getLinkText(device) def linkText = getLinkText(device)
def supportedThermostatModes = [] def isChange = false
def thermostatMode = null def isDisplayed = true
results.each { name, value ->
def event = [name: name, linkText: linkText, descriptionText: getThermostatDescriptionText(name, value, linkText), def event = [name: name, linkText: linkText, descriptionText: getThermostatDescriptionText(name, value, linkText),
handlerName: name] handlerName: name]
if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint" ) { if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint" ) {
def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger() def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
event << [value: sendValue, unit: temperatureScale] isChange = isTemperatureStateChange(device, name, value.toString())
isDisplayed = isChange
event << [value: sendValue, unit: temperatureScale, isStateChange: isChange, displayed: isDisplayed]
} else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") { } else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") {
def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger() def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
event << [value: sendValue, unit: temperatureScale, displayed: false] event << [value: sendValue, unit: temperatureScale, displayed: false]
} else if (name=="heatMode" || name=="coolMode" || name=="autoMode" || name=="auxHeatMode"){ } else if (name=="heatMode" || name=="coolMode" || name=="autoMode" || name=="auxHeatMode"){
if (value == true) { isChange = isStateChange(device, name, value.toString())
supportedThermostatModes << ((name == "auxHeatMode") ? "auxheatonly" : name - "Mode") event << [value: value.toString(), isStateChange: isChange, displayed: false]
}
return // as we don't want to send this event here, proceed to next name/value pair
} else if (name=="thermostatFanMode"){ } else if (name=="thermostatFanMode"){
sendEvent(name: "supportedThermostatFanModes", value: fanModes(), displayed: false) isChange = isStateChange(device, name, value.toString())
event << [value: value.toString(), data:[supportedThermostatFanModes: fanModes()]] event << [value: value.toString(), isStateChange: isChange, displayed: false]
} else if (name=="humidity") { } else if (name=="humidity") {
event << [value: value.toString(), displayed: false, unit: "%"] isChange = isStateChange(device, name, value.toString())
event << [value: value.toString(), isStateChange: isChange, displayed: false, unit: "%"]
} else if (name == "deviceAlive") { } else if (name == "deviceAlive") {
isChange = isStateChange(device, name, value.toString())
event['isStateChange'] = isChange
event['displayed'] = false event['displayed'] = false
} else if (name == "thermostatMode") { } else if (name == "thermostatMode") {
thermostatMode = value.toLowerCase() def mode = value.toString()
return // as we don't want to send this event here, proceed to next name/value pair mode = (mode == "auxHeatOnly") ? "emergency heat" : mode
isChange = isStateChange(device, name, mode)
event << [value: mode, isStateChange: isChange, displayed: isDisplayed]
} else { } else {
event << [value: value.toString()] isChange = isStateChange(device, name, value.toString())
isDisplayed = isChange
event << [value: value.toString(), isStateChange: isChange, displayed: isDisplayed]
} }
sendEvent(event) sendEvent(event)
} }
if (state.supportedThermostatModes != supportedThermostatModes) {
state.supportedThermostatModes = supportedThermostatModes
sendEvent(name: "supportedThermostatModes", value: supportedThermostatModes, displayed: false)
}
if (thermostatMode) {
sendEvent(name: "thermostatMode", value: thermostatMode, data:[supportedThermostatModes:state.supportedThermostatModes], linkText: linkText,
descriptionText: getThermostatDescriptionText("thermostatMode", thermostatMode, linkText), handlerName: "thermostatMode")
}
generateSetpointEvent () generateSetpointEvent ()
generateStatusEvent () generateStatusEvent ()
} }
@@ -324,7 +322,15 @@ void resumeProgram() {
} }
def modes() { def modes() {
return state.supportedThermostatModes if (state.modes) {
log.debug "Modes = ${state.modes}"
return state.modes
}
else {
state.modes = parent.availableModes(this)
log.debug "Modes = ${state.modes}"
return state.modes
}
} }
def fanModes() { def fanModes() {
@@ -407,13 +413,11 @@ def setThermostatFanMode(String mode) {
} }
def generateModeEvent(mode) { def generateModeEvent(mode) {
sendEvent(name: "thermostatMode", value: mode, data:[supportedThermostatModes: state.supportedThermostatModes], sendEvent(name: "thermostatMode", value: mode, descriptionText: "$device.displayName is in ${mode} mode", displayed: true)
descriptionText: "$device.displayName is in ${mode} mode")
} }
def generateFanModeEvent(fanMode) { def generateFanModeEvent(fanMode) {
sendEvent(name: "thermostatFanMode", value: fanMode, data:[supportedThermostatFanModes: fanModes()], sendEvent(name: "thermostatFanMode", value: fanMode, descriptionText: "$device.displayName fan is in ${fanMode} mode", displayed: true)
descriptionText: "$device.displayName fan is in ${fanMode} mode")
} }
def generateOperatingStateEvent(operatingState) { def generateOperatingStateEvent(operatingState) {
@@ -449,14 +453,14 @@ def heat() {
} }
def emergencyHeat() { def emergencyHeat() {
auxheatonly() auxHeatOnly()
} }
def auxheatonly() { def auxHeatOnly() {
log.debug "auxheatonly()" log.debug "auxHeatOnly = emergency heat"
def deviceId = device.deviceNetworkId.split(/\./).last() def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode ("auxHeatOnly", deviceId)) if (parent.setMode ("auxHeatOnly", deviceId))
generateModeEvent("auxheatonly") generateModeEvent("emergency heat") // emergency heat = auxHeatOnly
else { else {
log.debug "Error setting new mode." log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value def currentMode = device.currentState("thermostatMode")?.value
@@ -589,7 +593,7 @@ def generateSetpointEvent() {
} else if (mode == "off") { } else if (mode == "off") {
sendEvent("name":"thermostatSetpoint", "value":averageSetpoint, "unit":location.temperatureScale) sendEvent("name":"thermostatSetpoint", "value":averageSetpoint, "unit":location.temperatureScale)
sendEvent("name":"displayThermostatSetpoint", "value":"Off", displayed: false) sendEvent("name":"displayThermostatSetpoint", "value":"Off", displayed: false)
} else if (mode == "auxheatonly") { } else if (mode == "emergency heat") { // emergency heat = auxHeatOnly
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale) sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
sendEvent("name":"displayThermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale, displayed: false) sendEvent("name":"displayThermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale, displayed: false)
} }
@@ -628,7 +632,7 @@ void raiseSetpoint() {
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0 targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5 targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5
if ((mode == "heat" || mode == "auxheatonly") && targetvalue > maxHeatingSetpoint) { if ((mode == "heat" || mode == "emergency heat") && targetvalue > maxHeatingSetpoint) { // emergency heat = auxHeatOnly
targetvalue = maxHeatingSetpoint targetvalue = maxHeatingSetpoint
} else if (mode == "cool" && targetvalue > maxCoolingSetpoint) { } else if (mode == "cool" && targetvalue > maxCoolingSetpoint) {
targetvalue = maxCoolingSetpoint targetvalue = maxCoolingSetpoint
@@ -674,7 +678,7 @@ void lowerSetpoint() {
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0 targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5 targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5
if ((mode == "heat" || mode == "auxheatonly") && targetvalue < minHeatingSetpoint) { if ((mode == "heat" || mode == "emergency heat") && targetvalue < minHeatingSetpoint) { // emergency heat = auxHeatOnly
targetvalue = minHeatingSetpoint targetvalue = minHeatingSetpoint
} else if (mode == "cool" && targetvalue < minCoolingSetpoint) { } else if (mode == "cool" && targetvalue < minCoolingSetpoint) {
targetvalue = minCoolingSetpoint targetvalue = minCoolingSetpoint
@@ -715,7 +719,7 @@ void alterSetpoint(temp) {
} }
//step1: check thermostatMode, enforce limits before sending request to cloud //step1: check thermostatMode, enforce limits before sending request to cloud
if (mode == "heat" || mode == "auxheatonly"){ if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly
if (temp.value > coolingSetpoint){ if (temp.value > coolingSetpoint){
targetHeatingSetpoint = temp.value targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value targetCoolingSetpoint = temp.value
@@ -750,7 +754,7 @@ void alterSetpoint(temp) {
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}" log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
} else { } else {
log.error "Error alterSetpoint()" log.error "Error alterSetpoint()"
if (mode == "heat" || mode == "auxheatonly"){ if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false) sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
sendEvent("name": "displayThermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false) sendEvent("name": "displayThermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
} else if (mode == "cool") { } else if (mode == "cool") {
@@ -779,7 +783,7 @@ def generateStatusEvent() {
log.debug "Cooling set point = ${coolingSetpoint}" log.debug "Cooling set point = ${coolingSetpoint}"
log.debug "HVAC Mode = ${mode}" log.debug "HVAC Mode = ${mode}"
if (mode == "heat" || mode == "auxheatonly") { if (mode == "heat") {
if (temperature >= heatingSetpoint) { if (temperature >= heatingSetpoint) {
statusText = "Right Now: Idle" statusText = "Right Now: Idle"
} else { } else {
@@ -802,6 +806,8 @@ def generateStatusEvent() {
} }
} else if (mode == "off") { } else if (mode == "off") {
statusText = "Right Now: Off" statusText = "Right Now: Off"
} else if (mode == "emergency heat") { // emergency heat = auxHeatOnly
statusText = "Emergency Heat"
} else { } else {
statusText = "?" statusText = "?"
} }

View File

@@ -300,21 +300,15 @@ def setColor(value) {
value.hex = "#${hex(value.red)}${hex(value.green)}${hex(value.blue)}" value.hex = "#${hex(value.red)}${hex(value.green)}${hex(value.blue)}"
} }
if(value.hue) { sendEvent(name: "hue", value: value.hue, displayed: false)
sendEvent(name: "hue", value: value.hue, displayed: false) sendEvent(name: "saturation", value: value.saturation, displayed: false)
} sendEvent(name: "color", value: value.hex, displayed: false)
if(value.saturation) { if (value.level) {
sendEvent(name: "saturation", value: value.saturation, displayed: false) sendEvent(name: "level", value: value.level)
} }
if(value.hex?.trim()) { if (value.switch) {
sendEvent(name: "color", value: value.hex, displayed: false) sendEvent(name: "switch", value: value.switch)
} }
if (value.level) {
sendEvent(name: "level", value: value.level)
}
if (value.switch?.trim()) {
sendEvent(name: "switch", value: value.switch)
}
sendRGB(value.rh, value.gh, value.bh) sendRGB(value.rh, value.gh, value.bh)
} }

View File

@@ -35,8 +35,8 @@ metadata {
// tile definitions // tile definitions
tiles(scale: 2) { tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4, canChangeIcon: true){ multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { tileAttribute ("device.valve", key: "PRIMARY_CONTROL") {
attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing" attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing"
attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening" attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening"
attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC" attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
@@ -48,8 +48,8 @@ metadata {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
} }
main "contact" main "valve"
details(["contact","refresh"]) details(["valve","refresh"])
} }
} }

View File

@@ -23,6 +23,7 @@ metadata {
capability "Refresh" capability "Refresh"
capability "Sensor" capability "Sensor"
capability "Health Check" capability "Health Check"
capability "Light"
capability "Outlet" capability "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet" fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet"

View File

@@ -34,6 +34,7 @@ metadata {
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL6HD", deviceJoinName: "Leviton Dimmer Switch" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL6HD", deviceJoinName: "Leviton Dimmer Switch"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL3HL", deviceJoinName: "Leviton Lumina RF Plug-In Dimmer" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL3HL", deviceJoinName: "Leviton Lumina RF Plug-In Dimmer"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL1KD", deviceJoinName: "Leviton Lumina RF Dimmer Switch" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL1KD", deviceJoinName: "Leviton Lumina RF Dimmer Switch"
fingerprint profileId: "0104", deviceId: "0001", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 ON/OFF/DIM", deviceJoinName: "OSRAM LIGHTIFY LED Smart Connected Light"
} }
tiles(scale: 2) { tiles(scale: 2) {
@@ -137,4 +138,4 @@ def configure() {
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
refresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() refresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
} }

View File

@@ -38,8 +38,8 @@ metadata {
} }
tiles(scale: 2) { tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4, canChangeIcon: true){ multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { tileAttribute ("device.valve", key: "PRIMARY_CONTROL") {
attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing" attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing"
attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening" attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening"
attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing" attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing"
@@ -58,8 +58,8 @@ metadata {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
} }
main(["contact"]) main(["valve"])
details(["contact", "battery", "refresh"]) details(["valve", "battery", "refresh"])
} }
} }

View File

@@ -0,0 +1,50 @@
/**
* MMASmarthThingDemo
*
* Copyright 2017 Raja
*
* 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: "MMASmarthThingDemo",
namespace: "MMASmartThing",
author: "Raja",
description: "MMASmartThing demo app is for learning purpose to know how to integrage smarthings with mobile apps",
category: "Fun & Social",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
preferences {
section("Title") {
// TODO: put inputs here
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
// TODO: subscribe to attributes, devices, locations, etc.
}
// TODO: implement event handlers

View File

@@ -195,10 +195,7 @@ def registerDeviceChange() {
state.deviceSubscriptionMap.put(deviceId, [subscriptionEndpt]) state.deviceSubscriptionMap.put(deviceId, [subscriptionEndpt])
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}" log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
} else if (!state.deviceSubscriptionMap[deviceId].contains(subscriptionEndpt)) { } else if (!state.deviceSubscriptionMap[deviceId].contains(subscriptionEndpt)) {
// state.deviceSubscriptionMap[deviceId] << subscriptionEndpt state.deviceSubscriptionMap[deviceId] << subscriptionEndpt
// For now, we will only have one subscription endpoint per device
state.deviceSubscriptionMap.remove(deviceId)
state.deviceSubscriptionMap.put(deviceId, [subscriptionEndpt])
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}" log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
} }