mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-09 05:11:52 +00:00
Compare commits
21 Commits
MSA-1822-1
...
MSA-1839-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d18774081a | ||
|
|
2ae163b10b | ||
|
|
e3168793bd | ||
|
|
0baa986c61 | ||
|
|
8484f18a0e | ||
|
|
cb6377886d | ||
|
|
90fb9251a6 | ||
|
|
195e0babb2 | ||
|
|
065715f296 | ||
|
|
10acb76b34 | ||
|
|
4fc046f57f | ||
|
|
ff2e70b011 | ||
|
|
79e2789f68 | ||
|
|
94a87e5c7f | ||
|
|
22be8ef2e8 | ||
|
|
2f20a339c3 | ||
|
|
ab79ceb857 | ||
|
|
2151e2dd3e | ||
|
|
bfd2b6c0fa | ||
|
|
fc312286a2 | ||
|
|
0846b6f34c |
@@ -9,7 +9,7 @@ apply plugin: 'smartthings-slack'
|
||||
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.8"
|
||||
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.11"
|
||||
}
|
||||
repositories {
|
||||
mavenLocal()
|
||||
|
||||
@@ -21,6 +21,7 @@ metadata {
|
||||
capability "Tamper Alert"
|
||||
capability "Temperature Measurement"
|
||||
capability "Water Sensor"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x9C, 0x31, 0x86", outClusters: ""
|
||||
}
|
||||
@@ -228,7 +229,9 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca
|
||||
|
||||
def configure() {
|
||||
log.debug "Executing 'configure'"
|
||||
|
||||
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds = []
|
||||
|
||||
cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds:21600, nodeid: zwaveHubNodeId)//FGFS' default wake up interval
|
||||
|
||||
@@ -22,6 +22,7 @@ metadata {
|
||||
capability "Sensor"
|
||||
capability "Tamper Alert"
|
||||
capability "Temperature Measurement"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x20, 0x86, 0x72, 0x5A, 0x59, 0x85, 0x73, 0x84, 0x80, 0x71, 0x56, 0x70, 0x31, 0x8E, 0x22, 0x30, 0x9C, 0x98, 0x7A", outClusters: ""
|
||||
}
|
||||
@@ -240,7 +241,9 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca
|
||||
|
||||
def configure() {
|
||||
log.debug "Executing 'configure'"
|
||||
|
||||
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds = []
|
||||
|
||||
cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds: 7200, nodeid: zwaveHubNodeId)//FGMS' default wake up interval
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* Raspberry Pi
|
||||
*
|
||||
* Copyright 2014 Nicholas Wilde
|
||||
*
|
||||
* Monitor your Raspberry Pi using SmartThings and WebIOPi <https://code.google.com/p/webiopi/>
|
||||
*
|
||||
* Companion WebIOPi python script can be found here:
|
||||
* <https://github.com/nicholaswilde/smartthings/blob/master/device-types/raspberry-pi/raspberrypi.py>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
preferences {
|
||||
input("ip", "string", title:"IP Address", description: "192.168.1.150", required: true, displayDuringSetup: true)
|
||||
input("port", "string", title:"Port", description: "8000", defaultValue: 8000 , required: true, displayDuringSetup: true)
|
||||
input("username", "string", title:"Username", description: "webiopi", required: true, displayDuringSetup: true)
|
||||
input("password", "password", title:"Password", description: "Password", required: true, displayDuringSetup: true)
|
||||
}
|
||||
|
||||
metadata {
|
||||
definition (name: "Raspberry Pi", namespace: "nicholaswilde/smartthings", author: "Nicholas Wilde") {
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Temperature Measurement"
|
||||
capability "Switch"
|
||||
capability "Sensor"
|
||||
capability "Actuator"
|
||||
|
||||
attribute "cpuPercentage", "string"
|
||||
attribute "memory", "string"
|
||||
attribute "diskUsage", "string"
|
||||
|
||||
command "restart"
|
||||
}
|
||||
|
||||
simulator {
|
||||
// TODO: define status and reply messages here
|
||||
}
|
||||
|
||||
tiles {
|
||||
valueTile("temperature", "device.temperature", width: 1, height: 1) {
|
||||
state "temperature", label:'${currentValue}° CPU', unit: "F",
|
||||
backgroundColors:[
|
||||
[value: 25, color: "#153591"],
|
||||
[value: 35, color: "#1e9cbb"],
|
||||
[value: 47, color: "#90d2a7"],
|
||||
[value: 59, color: "#44b621"],
|
||||
[value: 67, color: "#f1d801"],
|
||||
[value: 76, color: "#d04e00"],
|
||||
[value: 77, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
standardTile("button", "device.switch", width: 1, height: 1, canChangeIcon: true) {
|
||||
state "off", label: 'Off', icon: "st.Electronics.electronics18", backgroundColor: "#ffffff", nextState: "on"
|
||||
state "on", label: 'On', icon: "st.Electronics.electronics18", backgroundColor: "#79b821", nextState: "off"
|
||||
}
|
||||
valueTile("cpuPercentage", "device.cpuPercentage", inactiveLabel: false) {
|
||||
state "default", label:'${currentValue}% CPU', unit:"Percentage",
|
||||
backgroundColors:[
|
||||
[value: 31, color: "#153591"],
|
||||
[value: 44, color: "#1e9cbb"],
|
||||
[value: 59, color: "#90d2a7"],
|
||||
[value: 74, color: "#44b621"],
|
||||
[value: 84, color: "#f1d801"],
|
||||
[value: 95, color: "#d04e00"],
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
valueTile("memory", "device.memory", width: 1, height: 1) {
|
||||
state "default", label:'${currentValue} MB', unit:"MB",
|
||||
backgroundColors:[
|
||||
[value: 353, color: "#153591"],
|
||||
[value: 287, color: "#1e9cbb"],
|
||||
[value: 210, color: "#90d2a7"],
|
||||
[value: 133, color: "#44b621"],
|
||||
[value: 82, color: "#f1d801"],
|
||||
[value: 26, color: "#d04e00"],
|
||||
[value: 20, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
valueTile("diskUsage", "device.diskUsage", width: 1, height: 1) {
|
||||
state "default", label:'${currentValue}% Disk', unit:"Percent",
|
||||
backgroundColors:[
|
||||
[value: 31, color: "#153591"],
|
||||
[value: 44, color: "#1e9cbb"],
|
||||
[value: 59, color: "#90d2a7"],
|
||||
[value: 74, color: "#44b621"],
|
||||
[value: 84, color: "#f1d801"],
|
||||
[value: 95, color: "#d04e00"],
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
standardTile("restart", "device.restart", inactiveLabel: false, decoration: "flat") {
|
||||
state "default", action:"restart", label: "Restart", displayName: "Restart"
|
||||
}
|
||||
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
|
||||
state "default", action:"refresh.refresh", icon: "st.secondary.refresh"
|
||||
}
|
||||
main "button"
|
||||
details(["button", "temperature", "cpuPercentage", "memory" , "diskUsage", "restart", "refresh"])
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
def map = [:]
|
||||
def descMap = parseDescriptionAsMap(description)
|
||||
//log.debug descMap
|
||||
def body = new String(descMap["body"].decodeBase64())
|
||||
//log.debug "body: ${body}"
|
||||
def slurper = new JsonSlurper()
|
||||
def result = slurper.parseText(body)
|
||||
log.debug "result: ${result}"
|
||||
if (result){
|
||||
log.debug "Computer is up"
|
||||
sendEvent(name: "switch", value: "on")
|
||||
}
|
||||
|
||||
|
||||
if (result.containsKey("cpu_temp")) {
|
||||
sendEvent(name: "temperature", value: result.cpu_temp)
|
||||
}
|
||||
|
||||
if (result.containsKey("cpu_perc")) {
|
||||
sendEvent(name: "cpuPercentage", value: result.cpu_perc)
|
||||
}
|
||||
|
||||
if (result.containsKey("mem_avail")) {
|
||||
log.debug "mem_avail: ${result.mem_avail}"
|
||||
sendEvent(name: "memory", value: result.mem_avail)
|
||||
}
|
||||
if (result.containsKey("disk_usage")) {
|
||||
log.debug "disk_usage: ${result.disk_usage}"
|
||||
sendEvent(name: "diskUsage", value: result.disk_usage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// handle commands
|
||||
def poll() {
|
||||
log.debug "Executing 'poll'"
|
||||
sendEvent(name: "switch", value: "off")
|
||||
getRPiData()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
sendEvent(name: "switch", value: "off")
|
||||
log.debug "Executing 'refresh'"
|
||||
getRPiData()
|
||||
}
|
||||
|
||||
def restart(){
|
||||
log.debug "Restart was pressed"
|
||||
sendEvent(name: "switch", value: "off")
|
||||
def uri = "/macros/reboot"
|
||||
postAction(uri)
|
||||
}
|
||||
|
||||
// Get CPU percentage reading
|
||||
private getRPiData() {
|
||||
def uri = "/macros/getData"
|
||||
postAction(uri)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
private postAction(uri){
|
||||
setDeviceNetworkId(ip,port)
|
||||
|
||||
def userpass = encodeCredentials(username, password)
|
||||
|
||||
def headers = getHeader(userpass)
|
||||
|
||||
def hubAction = new physicalgraph.device.HubAction(
|
||||
method: "POST",
|
||||
path: uri,
|
||||
headers: headers
|
||||
)//,delayAction(1000), refresh()]
|
||||
log.debug("Executing hubAction on " + getHostAddress())
|
||||
//log.debug hubAction
|
||||
hubAction
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Helper methods
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
def parseDescriptionAsMap(description) {
|
||||
description.split(",").inject([:]) { map, param ->
|
||||
def nameAndValue = param.split(":")
|
||||
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
|
||||
}
|
||||
}
|
||||
|
||||
private encodeCredentials(username, password){
|
||||
log.debug "Encoding credentials"
|
||||
def userpassascii = "${username}:${password}"
|
||||
def userpass = "Basic " + userpassascii.encodeAsBase64().toString()
|
||||
//log.debug "ASCII credentials are ${userpassascii}"
|
||||
//log.debug "Credentials are ${userpass}"
|
||||
return userpass
|
||||
}
|
||||
|
||||
private getHeader(userpass){
|
||||
log.debug "Getting headers"
|
||||
def headers = [:]
|
||||
headers.put("HOST", getHostAddress())
|
||||
headers.put("Authorization", userpass)
|
||||
//log.debug "Headers are ${headers}"
|
||||
return headers
|
||||
}
|
||||
|
||||
private delayAction(long time) {
|
||||
new physicalgraph.device.HubAction("delay $time")
|
||||
}
|
||||
|
||||
private setDeviceNetworkId(ip,port){
|
||||
def iphex = convertIPtoHex(ip)
|
||||
def porthex = convertPortToHex(port)
|
||||
device.deviceNetworkId = "$iphex:$porthex"
|
||||
log.debug "Device Network Id set to ${iphex}:${porthex}"
|
||||
}
|
||||
|
||||
private getHostAddress() {
|
||||
return "${ip}:${port}"
|
||||
}
|
||||
|
||||
private String convertIPtoHex(ipAddress) {
|
||||
String hex = ipAddress.tokenize( '.' ).collect { String.format( '%02x', it.toInteger() ) }.join()
|
||||
return hex
|
||||
|
||||
}
|
||||
|
||||
private String convertPortToHex(port) {
|
||||
String hexport = port.toString().format( '%04x', port.toInteger() )
|
||||
return hexport
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* Live Code Friday Virtual Device Manager
|
||||
*
|
||||
* Copyright 2015 Patrick Stuart
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Tasks
|
||||
Create a dynamic pages interface
|
||||
Pick a device type
|
||||
add/delete that child
|
||||
|
||||
*/
|
||||
definition(
|
||||
name: "Live Code Friday Virtual Device Manager",
|
||||
namespace: "pstuart",
|
||||
author: "Patrick Stuart",
|
||||
description: "Live Code Friday Virtual Device Manager",
|
||||
category: "My Apps",
|
||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||
singleInstance: true)
|
||||
|
||||
|
||||
preferences {
|
||||
page(name: "firstPage")
|
||||
page(name: "inputPage")
|
||||
page(name: "devicePage")
|
||||
page(name: "addDevicePage")
|
||||
page(name: "viewDevicePage")
|
||||
page(name: "deletePage")
|
||||
}
|
||||
|
||||
def firstPage() {
|
||||
dynamicPage(name: "firstPage", title: "Where to first?", install: true, uninstall: true) {
|
||||
section("Main Menu") {
|
||||
paragraph "Version 1.2"
|
||||
href(page: "inputPage", title: "Let's Add Devices!")
|
||||
|
||||
}
|
||||
/*
|
||||
section("Later") {
|
||||
paragraph "More to come..."
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
def inputPage() {
|
||||
dynamicPage(name: "inputPage", title: "Choose What Device Type You Want To Add", nextPage:"firstPage") {
|
||||
section("Device Types") {
|
||||
href(page: "devicePage", title: "Switches", params: [device: "Generic Switch"])
|
||||
href(page: "devicePage", title: "Dimmers", params: [device: "Generic Dimmer"])
|
||||
href(page: "devicePage", title: "Contact Sensor", params: [device: "Generic Contact"])
|
||||
|
||||
}
|
||||
section("Later") {
|
||||
paragraph "more devices coming soon"
|
||||
}
|
||||
section("Navigation") {
|
||||
href(page: "firstPage", title: "Main Menu")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def devicePage(params) {
|
||||
dynamicPage(name: "devicePage", title: "Devices", nextPage:"inputPage") {
|
||||
// Loop childDevices based on type
|
||||
// match up types
|
||||
def device = params.device
|
||||
log.debug "Hit Device Page with the selector device type $device"
|
||||
def deviceTitle = device + "s"
|
||||
if (device?.endsWith('ch') || device?.endsWith('s') || device?.endsWith('x')) {
|
||||
deviceTitle = device + "es"
|
||||
}
|
||||
log.debug "Device Title is $deviceTitle"
|
||||
|
||||
section("Installed ${deviceTitle}") {
|
||||
def childDevices = getChildDevices()
|
||||
|
||||
log.debug "The Child Devices are $childDevices"
|
||||
if (childDevices) {
|
||||
def devices = "Switches Installed:\r\nThis is a second line\r\n"
|
||||
log.debug "Inside childDevices if statement"
|
||||
|
||||
childDevices.findAll { it.typeName == device }
|
||||
.each {
|
||||
log.debug "The child device id is $it.deviceNetworkId and the type is $it"
|
||||
def test = it.typeName
|
||||
log.debug "Testing $test"
|
||||
//def tempDevice = getChildDevice(it)
|
||||
//log.debug tempDevice
|
||||
//devices = devices + "test\r\n"
|
||||
|
||||
|
||||
|
||||
switch(it.typeName) {
|
||||
case "Generic Switch" :
|
||||
href(page: "viewDevicePage", title: it.name, params: [dni: it.deviceNetworkId])
|
||||
break
|
||||
case "Generic Dimmer" :
|
||||
href(page: "viewDevicePage", title: it.name, params: [dni: it.deviceNetworkId])
|
||||
break
|
||||
case "Generic Contact" :
|
||||
href(page: "viewDevicePage", title: it.name, params: [dni: it.deviceNetworkId])
|
||||
break
|
||||
default : break
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
paragraph "No Virtual Generic Devices are Installed"
|
||||
}
|
||||
}
|
||||
|
||||
section("Add A ${params.device}") { //${params.device}
|
||||
// List Switches getChildDevices()
|
||||
|
||||
// Add A Switch addChildDevice()
|
||||
// View A Switch / Delete that switch go to switch view
|
||||
input("DeviceName", "text")
|
||||
href(page: "addDevicePage", title: "New $device", params: [type: device])
|
||||
}
|
||||
|
||||
section("Navigation") {
|
||||
href(page: "firstPage", title: "Main Menu")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def addDevicePage(params) {
|
||||
dynamicPage(name: "addDevicePage", title: "New $params.type", nextPage:"devicePage") {
|
||||
section("New $params.type Add Result") {
|
||||
//add new virtual switch
|
||||
log.debug "Add Device Page hit with params $params and $settings.DeviceName"
|
||||
def newDeviceName = params.type
|
||||
if (settings.DeviceName) {
|
||||
newDeviceName = settings.DeviceName
|
||||
}
|
||||
def result = addChildDevice(params.type, newDeviceName)
|
||||
paragraph "$params.type Added ${result}"
|
||||
|
||||
href(page: "devicePage", title: "Devices")
|
||||
}
|
||||
|
||||
section("Navigation") {
|
||||
href(page: "firstPage", title: "Main Menu")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def viewDevicePage(params) {
|
||||
dynamicPage(name: "viewDevicePage", title: "Switch", nextPage:"devicePage") {
|
||||
def viewSwitch = getChildDevice(params.dni)
|
||||
section("$viewSwitch.name") {
|
||||
paragraph "Switch Details \r\nName: $viewSwitch.name\r\nType: $viewSwitch.typeName\r\nNetwork ID: $viewSwitch.deviceNetworkId\r\nStates\r\nSwitch: ${viewSwitch.currentState('switch').value}\r\n" // Create info about switch / child device
|
||||
log.debug viewSwitch.currentState('switch').value
|
||||
href(page: "deletePage", title: "Delete", params: [dni: params.dni])
|
||||
}
|
||||
|
||||
section("Navigation") {
|
||||
href(page: "firstPage", title: "Main Menu")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def deletePage(params) {
|
||||
dynamicPage(name: "deletePage", title: "Delete", nextPage:"devicePage") {
|
||||
section("switch") {
|
||||
paragraph "Deleted Switch with DNI of $params.dni"
|
||||
log.debug "Deleting $params.dni"
|
||||
//def delete = getChildDevices().findAll { it?.contains(params.dni) }
|
||||
//log.debug delete
|
||||
def delete = getChildDevice(params.dni)
|
||||
//removeChildDevices(delete)
|
||||
deleteChildDevice(delete.deviceNetworkId)
|
||||
|
||||
href(page: "switchPage", title: "Switches")
|
||||
}
|
||||
|
||||
section("Navigation") {
|
||||
href(page: "firstPage", title: "Main Menu")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
def switches = getChildDevices()
|
||||
switches.each {
|
||||
if (!it.currentValue('switch') ) {
|
||||
it.off()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def addChildDevice(params, deviceName) {
|
||||
//Get all devices installed as children
|
||||
def childDevices = getChildDevices() //.findAll{ it -> it.type == params } //Find device of type params.type
|
||||
//def collectDevices = childDevices.collect{ getChildDevice(it).type ?: 0}
|
||||
//log.debug "The result of collectDevices is $collectDevices"
|
||||
|
||||
def gTypes = genericTypes()
|
||||
log.debug gTypes
|
||||
def subChildDevices = childDevices?.findAll { it -> it.typeName == params }
|
||||
log.debug "The subset of child devices is $subChildDevices based on type $params"
|
||||
def counter = subChildDevices?.size() + 1
|
||||
log.debug "$subChildDevices and counter is $counter"
|
||||
|
||||
/*
|
||||
def counters = [:]
|
||||
childDevices.each {
|
||||
def childDevice = getChildDevice(it)
|
||||
log.debug "Child Device type is $childDevice.type"
|
||||
gTypes.each {
|
||||
if (it == childDevice.type) {
|
||||
def counter = ["name" : params.type, "counter" : counter++ ]
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//def counter = childDevices.size() + 1 //TODO Fix counter for each type
|
||||
def dni = "pstuartDevice_$counter" // TODO create random string /guid
|
||||
def newDeviceName = "$params $counter"
|
||||
if (deviceName != params) {
|
||||
newDeviceName = deviceName
|
||||
}
|
||||
log.debug newDeviceName
|
||||
log.debug dni
|
||||
log.debug params
|
||||
log.trace "just about to add childe device"
|
||||
def childDevice = addChildDevice("pstuart", params, dni, null, [name:newDeviceName])
|
||||
log.debug childDevice
|
||||
childDevice.off()
|
||||
return childDevice
|
||||
//return dni
|
||||
|
||||
|
||||
}
|
||||
|
||||
def genericTypes() {
|
||||
def gTypes = [
|
||||
"Generic Switch",
|
||||
"Generic Contact",
|
||||
"Generic Dimmer",
|
||||
]
|
||||
return gTypes
|
||||
}
|
||||
@@ -39,6 +39,8 @@ metadata {
|
||||
capability "Temperature Measurement"
|
||||
capability "Configuration"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
capability "Sensor"
|
||||
|
||||
command "resetParams2StDefaults"
|
||||
command "listCurrentParams"
|
||||
@@ -304,6 +306,9 @@ def lateConfigure(setConf = False) {
|
||||
*/
|
||||
def configure() {
|
||||
log.debug "Configuring Device..."
|
||||
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds = []
|
||||
|
||||
// send associate to group 2 to get alarm data
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
capability "Illuminance Measurement"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
|
||||
command "resetParams2StDefaults"
|
||||
command "listCurrentParams"
|
||||
@@ -125,6 +126,9 @@
|
||||
*/
|
||||
def configure() {
|
||||
log.debug "Configuring Device For SmartThings Use"
|
||||
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds = []
|
||||
|
||||
// send associate to group 3 to get sensor data reported only to hub
|
||||
|
||||
@@ -21,6 +21,7 @@ metadata {
|
||||
capability "Configuration"
|
||||
capability "Battery"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
|
||||
command "enrollResponse"
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ metadata {
|
||||
capability "Contact Sensor"
|
||||
capability "Refresh"
|
||||
capability "Health Check"
|
||||
capability "Sensor"
|
||||
|
||||
command "enrollResponse"
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ definition(
|
||||
* garageDoors | door | open, close | unknown, closed, open, closing, opening
|
||||
* cameras | image | take | <String>
|
||||
* thermostats | thermostat | setHeatingSetpoint, | temperature, heatingSetpoint, coolingSetpoint,
|
||||
* | | setCoolingSetpoint, | thermostatSetpoint, thermostatMode,
|
||||
* | | setCoolingSetpoint, | thermostatSetpoint, thermostatMode,
|
||||
* | | off, heat, cool, auto,| thermostatFanMode, thermostatOperatingState
|
||||
* | | emergencyHeat, |
|
||||
* | | setThermostatMode, |
|
||||
@@ -55,7 +55,7 @@ preferences {
|
||||
input "contactSensors", "capability.contactSensor", title: "Which Contact Sensors", multiple: true, required: false
|
||||
input "garageDoors", "capability.garageDoorControl", title: "Which Garage Doors?", multiple: true, required: false
|
||||
input "locks", "capability.lock", title: "Which Locks?", multiple: true, required: false
|
||||
input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false
|
||||
input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false
|
||||
input "motionSensors", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false
|
||||
input "presenceSensors", "capability.presenceSensor", title: "Which Presence Sensors", multiple: true, required: false
|
||||
input "switches", "capability.switch", title: "Which Switches and Lights?", multiple: true, required: false
|
||||
@@ -66,54 +66,48 @@ preferences {
|
||||
|
||||
def getInputs() {
|
||||
def inputList = []
|
||||
inputList += contactSensors ?: []
|
||||
inputList += garageDoors ?: []
|
||||
inputList += locks ?: []
|
||||
inputList += cameras ?: []
|
||||
inputList += motionSensors ?: []
|
||||
inputList += presenceSensors ?: []
|
||||
inputList += switches ?: []
|
||||
inputList += thermostats ?: []
|
||||
inputList += waterSensors ?: []
|
||||
inputList += contactSensors?: []
|
||||
inputList += garageDoors?: []
|
||||
inputList += locks?: []
|
||||
inputList += cameras?: []
|
||||
inputList += motionSensors?: []
|
||||
inputList += presenceSensors?: []
|
||||
inputList += switches?: []
|
||||
inputList += thermostats?: []
|
||||
inputList += waterSensors?: []
|
||||
return inputList
|
||||
}
|
||||
|
||||
//API external Endpoints
|
||||
mappings {
|
||||
path("/subscriptionURL/:url") {
|
||||
action:
|
||||
[
|
||||
action: [
|
||||
PUT: "updateEndpointURL"
|
||||
]
|
||||
}
|
||||
path("/connectionId/:connId") {
|
||||
action:
|
||||
[
|
||||
action: [
|
||||
PUT: "updateConnectionId"
|
||||
]
|
||||
}
|
||||
path("/devices") {
|
||||
action:
|
||||
[
|
||||
action: [
|
||||
GET: "getDevices"
|
||||
]
|
||||
}
|
||||
path("/devices/:id") {
|
||||
action:
|
||||
[
|
||||
action: [
|
||||
GET: "getDevice"
|
||||
]
|
||||
}
|
||||
path("/update/:id") {
|
||||
action:
|
||||
[
|
||||
action: [
|
||||
PUT: "updateDevice"
|
||||
]
|
||||
}
|
||||
path("/subscription/:id") {
|
||||
action:
|
||||
[
|
||||
POST : "registerDeviceChange",
|
||||
action: [
|
||||
POST: "registerDeviceChange",
|
||||
DELETE: "unregisterDeviceChange"
|
||||
]
|
||||
}
|
||||
@@ -145,7 +139,7 @@ def registerSubscriptions() {
|
||||
def registerChangeHandler(myList) {
|
||||
myList.each { myDevice ->
|
||||
def theAtts = myDevice.supportedAttributes
|
||||
theAtts.each { att ->
|
||||
theAtts.each {att ->
|
||||
subscribe(myDevice, att.name, eventHandler)
|
||||
log.info "Registering ${myDevice.displayName}.${att.name}"
|
||||
}
|
||||
@@ -157,7 +151,7 @@ def registerDeviceChange() {
|
||||
def myDevice = findDevice(params.id)
|
||||
def theAtts = myDevice.supportedAttributes
|
||||
try {
|
||||
theAtts.each { att ->
|
||||
theAtts.each {att ->
|
||||
subscribe(myDevice, att.name, eventHandler)
|
||||
log.info "Registering ${myDevice.displayName}.${att.name}"
|
||||
}
|
||||
@@ -186,16 +180,20 @@ def eventHandler(evt) {
|
||||
def evt_name = evt.name
|
||||
def evt_device = evt.device
|
||||
def evt_deviceType = getDeviceType(evt_device);
|
||||
def deviceInfo
|
||||
|
||||
if(evt_deviceType == "thermostat")
|
||||
{
|
||||
deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device), locationMode: getLocationModeInfo()]
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device)]
|
||||
}
|
||||
|
||||
def params = [
|
||||
uri : "${state.endpointURL}/${state.connectionId}",
|
||||
body: [
|
||||
name : evt_device.displayName,
|
||||
id : evt_device.id,
|
||||
deviceType : evt_deviceType,
|
||||
manufacturer: evt_device.getManufacturerName(),
|
||||
model : evt_device.getModelName(),
|
||||
attributes : deviceAttributeList(evt_device)
|
||||
]
|
||||
uri: "${state.endpointURL}/${state.connectionId}",
|
||||
body: [ deviceInfo ]
|
||||
]
|
||||
try {
|
||||
log.trace "POST URI: ${params.uri}"
|
||||
@@ -230,10 +228,13 @@ def getDevices() {
|
||||
def deviceData = []
|
||||
inputs?.each {
|
||||
def deviceType = getDeviceType(it)
|
||||
if (deviceType == "thermostat") {
|
||||
deviceData << [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
|
||||
} else {
|
||||
deviceData << [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it)]
|
||||
if(deviceType == "thermostat")
|
||||
{
|
||||
deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,10 +247,13 @@ def getDevice() {
|
||||
def it = findDevice(params.id)
|
||||
def deviceType = getDeviceType(it)
|
||||
def device
|
||||
if (deviceType == "thermostat") {
|
||||
device = [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
|
||||
} else {
|
||||
device = [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it)]
|
||||
if(deviceType == "thermostat")
|
||||
{
|
||||
device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
|
||||
}
|
||||
else
|
||||
{
|
||||
device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)]
|
||||
}
|
||||
log.debug "getDevice, return: ${device}"
|
||||
return device
|
||||
@@ -261,18 +265,18 @@ void updateDevice() {
|
||||
request.JSON.each {
|
||||
def command = it.key
|
||||
def value = it.value
|
||||
if (command) {
|
||||
if (command){
|
||||
def commandList = mapDeviceCommands(command, value)
|
||||
command = commandList[0]
|
||||
value = commandList[1]
|
||||
|
||||
if (command == "setAwayMode") {
|
||||
log.info "Setting away mode to ${value}"
|
||||
if (location.modes?.find { it.name == value }) {
|
||||
if (location.modes?.find {it.name == value}) {
|
||||
location.setMode(value)
|
||||
}
|
||||
} else if (command == "thermostatSetpoint") {
|
||||
switch (device.currentThermostatMode) {
|
||||
}else if (command == "thermostatSetpoint"){
|
||||
switch(device.currentThermostatMode){
|
||||
case "cool":
|
||||
log.info "Update: ${device.displayName}, [${command}, ${value}]"
|
||||
device.setCoolingSetpoint(value)
|
||||
@@ -286,7 +290,7 @@ void updateDevice() {
|
||||
httpError(501, "this mode: ${device.currentThermostatMode} does not allow changing thermostat setpoint.")
|
||||
break
|
||||
}
|
||||
} else if (!device) {
|
||||
}else if (!device) {
|
||||
log.error "updateDevice, Device not found"
|
||||
httpError(404, "Device not found")
|
||||
} else if (!device.hasCommand(command)) {
|
||||
@@ -296,11 +300,11 @@ void updateDevice() {
|
||||
if (command == "setColor") {
|
||||
log.info "Update: ${device.displayName}, [${command}, ${value}]"
|
||||
device."$command"(hex: value)
|
||||
} else if (value.isNumber()) {
|
||||
} else if(value.isNumber()) {
|
||||
def intValue = value as Integer
|
||||
log.info "Update: ${device.displayName}, [${command}, ${intValue}(int)]"
|
||||
device."$command"(intValue)
|
||||
} else if (value) {
|
||||
} else if (value){
|
||||
log.info "Update: ${device.displayName}, [${command}, ${value}]"
|
||||
device."$command"(value)
|
||||
} else {
|
||||
@@ -322,19 +326,28 @@ private getLocationModeInfo() {
|
||||
//Map each device to a type given it's capabilities
|
||||
private getDeviceType(device) {
|
||||
def deviceType
|
||||
def caps = device.capabilities
|
||||
log.debug "capabilities: [${device}, ${caps}]"
|
||||
def capabilities = device.capabilities
|
||||
log.debug "capabilities: [${device}, ${capabilities}]"
|
||||
log.debug "supported commands: [${device}, ${device.supportedCommands}]"
|
||||
caps.each {
|
||||
switch (it.name.toLowerCase()) {
|
||||
|
||||
//Loop through the device capability list to determine the device type.
|
||||
capabilities.each {capability ->
|
||||
switch(capability.name.toLowerCase())
|
||||
{
|
||||
case "switch":
|
||||
deviceType = "switch"
|
||||
if (caps.any { it.name.toLowerCase() == "power meter" }) {
|
||||
return deviceType
|
||||
}
|
||||
if (caps.any { it.name.toLowerCase() == "switch level" }) {
|
||||
deviceType = "light"
|
||||
return deviceType
|
||||
|
||||
//If the device also contains "Switch Level" capability, identify it as a "light" device.
|
||||
if (capabilities.any{it.name.toLowerCase() == "switch level"}){
|
||||
|
||||
//If the device also contains "Power Meter" capability, identify it as a "dimmerSwitch" device.
|
||||
if (capabilities.any{it.name.toLowerCase() == "power meter"}){
|
||||
deviceType = "dimmerSwitch"
|
||||
return deviceType
|
||||
} else {
|
||||
deviceType = "light"
|
||||
return deviceType
|
||||
}
|
||||
}
|
||||
break
|
||||
case "contact sensor":
|
||||
@@ -375,16 +388,16 @@ private findDevice(deviceId) {
|
||||
|
||||
//Return a list of device attributes
|
||||
private deviceAttributeList(device) {
|
||||
device.supportedAttributes.collectEntries { attribute ->
|
||||
device.supportedAttributes.collectEntries { attribute->
|
||||
try {
|
||||
[(attribute.name): device.currentValue(attribute.name)]
|
||||
} catch (e) {
|
||||
[(attribute.name): null]
|
||||
[ (attribute.name): device.currentValue(attribute.name) ]
|
||||
} catch(e) {
|
||||
[ (attribute.name): null ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Map device command and value.
|
||||
//Map device command and value.
|
||||
//input command and value are from UWP,
|
||||
//returns resultCommand and resultValue that corresponds with function and value in SmartApps
|
||||
private mapDeviceCommands(command, value) {
|
||||
@@ -414,7 +427,7 @@ private mapDeviceCommands(command, value) {
|
||||
resultCommand = "setSaturation"
|
||||
resultValue = value
|
||||
break
|
||||
case "ct":
|
||||
case "colorTemperature":
|
||||
resultCommand = "setColorTemperature"
|
||||
resultValue = value
|
||||
break
|
||||
@@ -451,7 +464,8 @@ private mapDeviceCommands(command, value) {
|
||||
if (value == 1 || value == "1" || value == "lock") {
|
||||
resultCommand = "lock"
|
||||
resultValue = ""
|
||||
} else if (value == 0 || value == "0" || value == "unlock") {
|
||||
}
|
||||
else if (value == 0 || value == "0" || value == "unlock") {
|
||||
resultCommand = "unlock"
|
||||
resultValue = ""
|
||||
}
|
||||
@@ -460,6 +474,5 @@ private mapDeviceCommands(command, value) {
|
||||
break
|
||||
}
|
||||
|
||||
return [resultCommand, resultValue]
|
||||
return [resultCommand,resultValue]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user