Compare commits

..

1 Commits

12 changed files with 347 additions and 127 deletions

View File

@@ -9,7 +9,7 @@ apply plugin: 'smartthings-slack'
buildscript {
dependencies {
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.12"
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.11"
}
repositories {
mavenLocal()
@@ -19,7 +19,7 @@ buildscript {
username smartThingsArtifactoryUserName
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
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 {
devicetypesCompile 'org.codehaus.groovy:groovy-all:2.4.7'
devicetypesCompile 'smartthings:appengine-z-wave:0.1.3'
devicetypesCompile 'smartthings:appengine-zigbee:0.1.12'
devicetypesCompile 'smartthings:appengine-z-wave:0.1.2'
devicetypesCompile 'smartthings:appengine-zigbee:0.1.11'
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.grails:grails-web:2.3.11'
smartappsCompile 'org.json:json:20140107'
@@ -74,19 +74,19 @@ slackSendMessage {
String username
switch (branch) {
case 'master':
username = 'DEV'
username = 'Hickory'
iconUrl = wolverine
color = '#35D0F2'
messageText = 'Began deployment of _SmartThingsPublic[master]_ branch to the _Dev_ environments.'
break
case 'staging':
username = 'STG'
username = 'Dickory'
iconUrl = beach
color = '#FFDE20'
messageText = 'Began deployment of _SmartThingsPublic[staging]_ branch to the _Staging_ environments.'
break
case 'production':
username = 'PRD'
username = 'Dock'
iconUrl = drinks
color = '#FF1D23'
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
*
@@ -20,7 +19,6 @@ metadata {
capability "Configuration"
capability "Sensor"
capability "Battery"
capability "Health Check"
fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x80,0x84,0x85"
fingerprint mfr: "0086", prod: "0001", model: "0026", deviceJoinName: "Aeon Panic Button"
@@ -133,9 +131,6 @@ def updated() {
}
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 buttons = 4 // Default for Key Fob

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
*
@@ -19,7 +18,6 @@ metadata {
capability "Holdable Button"
capability "Configuration"
capability "Sensor"
capability "Health Check"
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
@@ -121,7 +119,5 @@ def updated() {
}
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)
}

View File

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

View File

@@ -35,8 +35,8 @@ metadata {
// tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.valve", key: "PRIMARY_CONTROL") {
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 "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
@@ -48,16 +48,14 @@ metadata {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "contact"
details(["contact","refresh"])
main "valve"
details(["valve","refresh"])
}
}
def installed(){
// Device-Watch simply pings if no device events received for 32min(checkInterval)
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
response(refresh())
}
def updated(){
@@ -87,17 +85,11 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
}
def open() {
delayBetween([
zwave.switchBinaryV1.switchBinarySet(switchValue: 0x00).format(),
zwave.switchBinaryV1.switchBinaryGet().format()
], 500)
zwave.switchBinaryV1.switchBinarySet(switchValue: 0x00).format()
}
def close() {
delayBetween([
zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF).format(),
zwave.switchBinaryV1.switchBinaryGet().format()
], 500)
zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF).format()
}
/**
@@ -113,6 +105,6 @@ def refresh() {
def createEventWithDebug(eventMap) {
def event = createEvent(eventMap)
log.debug "Event created with ${event?.name}:${event?.value} - ${event?.descriptionText}"
log.debug "Event created with ${event?.descriptionText}"
return event
}

View File

@@ -38,8 +38,8 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.valve", key: "PRIMARY_CONTROL") {
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 "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"
}
main(["contact"])
details(["contact", "battery", "refresh"])
main(["valve"])
details(["valve", "battery", "refresh"])
}
}

View File

@@ -0,0 +1,317 @@
/**
* RealApplication_CA
*
* Copyright 2017 Venkata Kishore Chilakala
*
* 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: "RealApplication_CA",
namespace: "CA",
author: "Venkata Kishore Chilakala",
description: "myApp",
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")
preferences {
section("Allow External Service to Control These Things...")
{
input "motions", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false
input "contacts", "capability.contactSensor",title: "Which Contact Sensor?", multiple: true, required: false
input "presences", "capability.presenceSensor",title: "Which Presence Sensor?", multiple: true, required: false
input "switches", "capability.switchLevel", title: "Which Switches?", multiple: true, required: false
input "levelSwitches","capability.switchLevel",title: "Which Level Switch?",multiple: true, required:false
input "relativeHumidity","capability.relativeHumidityMeasurement",title: "Humidity",multiple:true,required:false
input "temperature","capability.temperatureMeasurement",title: "Temperature Measurement",multiple:true,required:false
input "lock","capability.lock",title: "Door Lock", multiple:true,required:false
input "hubs",title: "Hubs",multiple:false,required:false
}
}
def installed() {
initialize()
}
def updated() {
initialize()
}
mappings {
path("/devices")
{
action:[
GET:"listDevices"
]
}
path("/hubs") {
log.debug "list action"
action: [
GET: "listAll"
]
}
path("/switches") {
action: [
GET:"listSwitches",
PUT:"updateSwitches"
]
}
path("/switches/:id") {
action: [
GET:"showSwitch",
PUT:"updateSwitch"
]
}
path("/levelSwitches") {
action: [
GET:"listLevelSwitches",
PUT:"updateLevelSwitches"
]
}
path("/levelSwitches/:id") {
action: [
GET:"showLevelSwitch",
PUT:"updateLevelSwitch"
]
}
path("/motions") {
action: [
GET:"listMotions",
PUT:"updateMotions"
]
}
path("/motions/:id"){
action:[
GET:"showMotion",
PUT:"updateMotion"
]
}
path("/presences")
{
action:[
GET:"listPresenceSensor",
PUT:"updatePresenceSensor"
]
}
path("/presences/:id")
{
action:[
GET:"showPresence",
PUT:"updatePresence"
]
}
path("/locks") {
action: [
GET:"listLocks",
PUT:"updateLocks"
]
}
path("/locks/:id") {
action: [
GET:"showLock",
PUT:"updateLock"
]
}
path("/contacts")
{
action: [
GET: "listContacts",
PUP: "updateContacts"
]
}
path ("/contacts/:id")
{
action:[
GET:"showContact",
PUT:"updateContact"
]
}
}
def listAll()
{
[location_id :location.id,hub_id:location.hubs*.id,hub_type:location.hubs*.type,hub_name:location.hubs*.name,hub_firm_ver:location.hubs*.firmwareVersionString,hub_ip:location.hubs*.localIP,hub_port:location.hubs*.localSrvPortTCP]
}
def listSwitches() {
switches.collect { device(it,"switch") }
}
void updateSwitches() {
updateAll(switches)
}
def showSwitch() {
show(switches, "switch")
}
void updateSwitch() {
update(switches)
}
def listLevelSwitches() {
levelSwitches.collect { device(it,"level") }
// motions.collect { device(it,"motion") }
}
void updateLevelSwitches() {
updateAll(levelSwitches)
}
def showLevelSwitch() {
show(levelSwitches, "level")
}
void updateLevelSwitch() {
update(levelSwitches)
}
def listLocks() {
lock.collect { device(it,"lock") }
}
void updateLocks() {
updateAll(lock)
}
def showLock() {
show(lock, "lock")
}
void updateLock() {
update(lock)
}
def listMotions() {
motions.collect { device(it,"motion") }
}
void updateMotions()
{
updateAll(motions)
}
def showMotion()
{
show(motions, "motion")
}
void updateMotion()
{
update(motions)
}
def listPresenceSensor()
{
presences.collect{device(it,"presence")}
}
void updatePresenceSensor()
{
updateAll(presences)
}
def showPresence()
{
show(presences,"presence")
}
void updatePresence()
{
update(presences)
}
def listContacts(){
contacts.collect{device(it,"contact")}
}
void updateContacts()
{
updateAll(contacts)
}
def showContact()
{
show(contacts,"contact")
}
void updateContact()
{
update(contacts)
}
private device(it, name) {
if (it) {
def s = it.currentState(name)
[
id: it.id,
name: it.displayName,
label: it.displayName,
hub_name: it.hub.name,
hub_id: it.hub.id,
hub_ip: it.hub.localIP,
hub_port: it.hub.localSrvPortTCP,
state: s
]
}
}
private void updateAll(devices) {
def command = request.JSON?.command
if (command) {
devices."$command"()
}
}
private show(devices, name) {
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
}
else {
log.debug " state s :: ${s}"
log.debug "devices :: ${devices}"
log.debug "name :: ${name}"
def s = device.currentState(name)
[id: device.id, label: device.displayName, name: device.displayName,state:s]
}
}
private void update(devices) {
log.debug "update, request: ${request.JSON}, params: ${params}, devices: $devices.id"
def command = request.JSON?.command
def value = request.JSON?.value
log.debug "$value"
log.debug "$command"
if (command) {
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if("$command"=="on")
{
device."$command"()
}else if("$command"=="off")
{
device."$command"()
}else if("$command"=="lock")
{
device."$command"()
}else if("$command"=="unlock")
{
device."$command"()
}else
{
device.setLevel("$command")
}
}
}
}
def initialize() {
}

View File

@@ -195,10 +195,7 @@ def registerDeviceChange() {
state.deviceSubscriptionMap.put(deviceId, [subscriptionEndpt])
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
} else if (!state.deviceSubscriptionMap[deviceId].contains(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])
state.deviceSubscriptionMap[deviceId] << subscriptionEndpt
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
}