I’ve managed to go through the api on my own and get a handler working with a raspberry pi.
Now I’m stuck on one problem. In the parse I update the state of the tile. The problem is even if I turn off the raspberry to test, when I click the tile button it still updates to the “On” state in the app.
What should happen is that the button does not turn to “On” since the raspberry is offline.
What am I missing here? I’m trying to track something down in other handlers or the api but have not come across the needle in the haystack.
/**
* 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)
}
metadata {
definition (name: "Pool Controller", namespace: "jaswalters", author: "Jason Walters") {
capability "Polling"
capability "Refresh"
capability "Temperature Measurement"
capability "Switch"
capability "Sensor"
capability "Actuator"
attribute "SuctionValvePos", "enum", ["SpaPos", "PoolPos"]
attribute "ReturnValvePos", "enum", ["FountainPos", "WaterFallPos"]
attribute "cpuPercentage", "string"
attribute "memory", "string"
attribute "diskUsage", "string"
attribute "Fountain", "string"
command "restart"
command "FountainModeOn"
command "FountainModeOff"
command "WaterFallMode"
command "SpaMode"
}
simulator {
// TODO: define status and reply messages here
}
tiles {
valueTile("temperature", "device.temperature", width: 1, height: 1) {
state "temperature", label:'${currentValue}°F CPU', unit: "F",
backgroundColors:[
[value: 26, color: "#153591"],
[value: 52, color: "#1e9cbb"],
[value: 78, color: "#90d2a7"],
[value: 104, color: "#44b621"],
[value: 130, color: "#f1d801"],
[value: 156, color: "#d04e00"],
[value: 185, 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"]
]
}
standardTile("Fountain", "device.Fountain", width: 1, height: 1) {
state "off", action:"FountainModeOn", label: '${name}', icon: "st.Outdoor.outdoor13", backgroundColor: "#ffffff", nextState: "on"
state "turningOn", action:"FountainModeOff", label: '${name}', icon: "st.Outdoor.outdoor13", backgroundColor: "#ffffff", nextState: "turningOff"
state "turningOff", action:"FountainModeOff", label: '${name}', icon: "st.Outdoor.outdoor13", backgroundColor: "#ffffff", nextState: "turningOn"
state "on", action:"FountainModeOff", label: '${name}', icon: "st.Outdoor.outdoor13", backgroundColor: "#79b821", nextState: "off"
}
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", "Fountain", "diskUsage", "restart", "refresh"])
}
}
// ------------------------------------------------------------------
// parse events into attributes
def parse(String description) {
def map = [:]
def descMap = parseDescriptionAsMap(description)
log.debug "Parsed"
def body = new String(descMap["body"].decodeBase64())
log.debug "body: ${body}"
def slurper = new JsonSlurper()
def result = slurper.parseText(body)
if (result){
log.debug "Computer is up"
sendEvent(name: "switch", value: "on", isStateChange: true)
}
if (result.containsKey("cpu_temp")) {
log.debug "cpu_temp: ${result.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)
}
if (result.containsKey("FountainMode")) {
log.debug "Parse result Fountain ${result.FountainMode}"
sendEvent(name: "Fountain", value: result.FountainMode)
if (result.FountainMode == "On") {
log.debug "Return Valve has been set"
state.ReturnValvePos = "FountainPos"
} else{
state.ReturnValvePos = "WaterFallPos"
}
}
}
//commands
def FountainModeOn() {
log.debug "FountainMethodCalled"
def uri = "/macros/FountainOn"
postAction(uri)
}
def FountainModeOff() {
def uri = "/macros/FountainOff"
postAction(uri)
}
def WaterFallMode() {
}
def SpaMode() {
}
def poll() {
log.debug "Executing 'poll'"
sendEvent(name: "switch", value: "off")
getRPiData()
}
def refresh()
{
log.debug "Executing 'refresh'"
sendEvent(name: "switch", value: "off")
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/getRPiData"
postAction(uri)
}
// ------------------------------------------------------------------
private postAction(uri){
setDeviceNetworkId(ip,port)
def hubAction = new physicalgraph.device.HubAction(
method: "POST",
path: uri
)//,delayAction(1000), refresh()]
log.debug("Executing hubAction on " + getHostAddress())
log.debug hubAction
return hubAction
}
// ------------------------------------------------------------------
// Helper methods
// ------------------------------------------------------------------
def parseDescriptionAsMap(description) {
description.split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
}
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
}