Compare commits

...

1 Commits

Author SHA1 Message Date
Eugen Valeriu
d18774081a MSA-1839: SmartThings in any respect whatsoever. 2017-03-14 13:13:02 -07:00
2 changed files with 527 additions and 0 deletions

View File

@@ -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
}

View File

@@ -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
}