This isn’t rocket science I don’t think, so you should be able to understand my code at this point…
/ *
* Author: Khile T. Klock (klockksr@gmail.com) - Leveraged from Andrew Dumaresq (dumaresq@gmail.com)
*/
definition(
name: "Sprinkler Konntroler",
namespace: "klockk",
author: "Khile T. Klock",
description: "This will turn on your sprinkler schedule at a specified time, depending on moister from a spruce sensor and the weather forecast",
category: "Green Living",
iconUrl: "http://cdn.device-icons.smartthings.com/Outdoor/outdoor12-icn.png",
iconX2Url: "http://cdn.device-icons.smartthings.com/Outdoor/outdoor12-icn@2x.png"
//http://cdn.device-icons.smartthings.com/Outdoor/outdoor12-icn@2x.png
)
preferences {
section("Schedule") {
input name: "startTime", title: "Start Time?", type: "time"
}
section("Relays to turn on?") {
input "Relay1", "capability.switch", title: "Phisical Relay 1", required: false
input "Timer1", title: "Minutes to water", type: "number", required: false, defaultValue: 0
input "Relay2", "capability.switch", title: "Phisical Relay 2", required: false
input "Timer2", title: "Minutes to water", type: "number", required: false, defaultValue: 0
input "Relay3", "capability.switch", title: "Phisical Relay 3", required: false
input "Timer3", title: "Minutes to water", type: "number", required: false, defaultValue: 0
input "Relay4", "capability.switch", title: "Phisical Relay 4", required: false
input "Timer4", title: "Minutes to water", type: "number", required: false, defaultValue: 0
input "Relay5", "capability.switch", title: "Phisical Relay 5", required: false
input "Timer5", title: "Minutes to water", type: "number", required: false, defaultValue: 0
input "Relay6", "capability.switch", title: "Phisical Relay 6", required: false
input "Timer6", title: "Minutes to water", type: "number", required: false, defaultValue: 0
}
section("Moisture Sensor") {
input "sensor1", "capability.sensor", required: false
input name: "highHumidity", title: "How Wet is too Wet (in %)?", type: "number", required: false
}
section("Zip code..."){
input "zipcode", "text", title: "Zipcode?", required: false
}
section( "Notifications" ) {
input("recipients", "contact", title: "Send notifications to") {
input "sendPushMessage", "enum", title: "Send a push notification?", options: ["Yes", "No"], required: false
input "phone1", "phone", title: "Send a Text Message?", required: false
}
}
}
def installed() {
log.debug "Installed with settings: ${settings}" // Docs indicate this should work, but it results in null
log.debug "Installed with settings: "
log.debug " Relay1: ${Relay1} for ${Timer1} min" // Docs indicate should be able to reference $settings.Relay1 but that doesn't work....
log.debug " Relay2: ${Relay2} for ${Timer2} min"
log.debug " Relay3: ${Relay3} for ${Timer3} min"
log.debug " Relay4: ${Relay4} for ${Timer4} min"
log.debug " Relay5: ${Relay5} for ${Timer5} min"
log.debug " Relay6: ${Relay6} for ${Timer6} min"
log.debug " Run at: $startTime"
schedule(startTime, "startTimerCallback")
}
def updated() {
log.debug "Updated with settings: ${settings}" // Docs indicate this should work, but it results in null
log.debug "Updated settings: "
log.debug " Relay1: ${Relay1} for ${Timer1} min"
log.debug " Relay2: ${Relay2} for ${Timer2} min"
log.debug " Relay3: ${Relay3} for ${Timer3} min"
log.debug " Relay4: ${Relay4} for ${Timer4} min"
log.debug " Relay5: ${Relay5} for ${Timer5} min"
log.debug " Relay6: ${Relay6} for ${Timer6} min"
log.debug " Run at: $startTime"
unschedule()
schedule(startTime, "startTimerCallback")
}
def initialize() {
data.Zone = null
data.runTimeMin = 0
}
private isStormy(json) {
def STORMY = ['rain', 'snow', 'showers', 'sprinkles', 'precipitation']
def forecast = json?.forecast?.txt_forecast?.forecastday?.first()
log.debug "Checking Response"
if (forecast) {
def text = forecast?.fcttext?.toLowerCase()
if (text) {
log.debug "reponse is: ${text}"
def result = false
for (int i = 0; i < STORMY.size() && !result; i++) {
result = text.contains(STORMY[i])
}
return result
} else {
return false
}
} else {
log.warn "Did not get a forecast: $json"
return false
}
}
def startTimerCallback() {
log.debug "startTimerCallback: Begin"
sendNotificationEvent("${app.label}: Checking to see if we should Water the lawn")
if ((sensor1 && highHumidity) && sensor1.currentHumidity > highHumidity) {
int hours = 48
def yesterday = new Date(now() - (/* 1000 * 60 * 60 */ 3600000 * hours).toLong())
def lastHumDate = sensor1.latestState('humidity').date
if (lastHumDate < yesterday) {
log.warning "${app.label}: Please check sensor ${sensor1}, no humidity reports for ${hours}+ hours"
sendNotificationEvent("${app.label}: Please check sensor ${sensor1}, no humidity reports for ${hours}+ hours")
}
sendNotificationEvent("${app.label}: Not Watering, because ${sensor1} is at ${sensor1.currentHumidity}")
log.debug "Not Watering, because ${sensor1} is at ${sensor1.currentHumidity} the cut off is ${highHumidity}"
return
}
if (zipcode) {
def response = getWeatherFeature("forecast", zipcode)
if (isStormy(response)) {
log.debug "Got Rain not Wattering"
sendNotificationEvent("${app.label}: Not Watering, the forcast calls for rain.")
return
}
}
if (sensor1 && highHumidity) {
log.debug "The Humidity is: ${sensor1.currentHumidity} and our cut off is ${highHumidity} so we are watering."
}
sendNotificationEvent("${app.label}: All Checks passed, initiating Sprinkler Konntrol for ${app.label}.")
log.debug "All Checks passed, initiating Sprinkler Konntrol for ${app.label}."
if (Relay1) {
runIn(0,turnOnSwitch, [data: [Zone: Relay1, runTimeMin: Timer1]] ) // Passing this data map works beautifully...
}
//if (Relay2) {
// runIn(##,turnOnSwitch, [data: [Zone: Relay2, runTimeMin: Timer2]])
//}
log.debug "startTimerCallback: End"
}
def StopTimerCallback(data) {
log.debug "StopTimerCallback: Begin"
log.debug "Relay is $data.Zone" // This is no longer a reference to the device object...??
// 11:39:00 AM: debug Relay is [id:4ce19db3-a62b-4929-8720-b3055705fb9b, name:Konnected Switch, label:Sprinklers - Front Yard]
//def devices = settings.inputDevices
//log.debug
// Thought I might try to re-establish a pointer to the device by enumerating through them, but that didnt work either...
// Find Devices with a specific ID:
//devices.findAll( { it.getDeviceNetworkId() == "${data.Zone}" } ).each {
//for (device in devices) {
// log.debug "Device ID: ${device.getDeviceNetworkId()}"
// if ( "${device.getDeviceNetworkId()}" == "${data.Zone}") {
// log.debug "Found device: ID: ${it.id}, Label: ${it.label}, Name: ${it.name}"
// Relay = it
// log.debug "Relay is $Relay"
// turnOffSwitch(it)
turnOffSwitch(data.Zone) // THis doesnt work...
// }
//}
log.debug "StopTimerCallback: End"
}
def turnOnSwitch(data) {
log.debug "turnOnSwitch: Begin"
log.debug "Relay is $data.Zone"
log.debug "runTime is $data.runTimeMin"
log.debug "Relay is ${data.Zone.currentSwitch}"
if (data.Zone) {
sendNotificationEvent("${app.label}: Watering for $data.runTimeMin minutes.")
log.debug "Watering ($Relay1.label) for $data.runTimeMin minutes."
data.Zone.on()
// Turn the Relay Back off After specified period of Minutes
// We'll pass in the target relay as part of the data map in the runIn() function, but when the Callback occurs, it seems it's no longer a reference to the object...??
//runIn(60 * data.runTimeMin.toInteger(), StopTimerCallback, [data: [Zone: data.Zone.getDeviceNetworkId()]])
runIn(60 * data.runTimeMin.toInteger(), StopTimerCallback, [data: [Zone: data.Zone]])
}
log.debug "turnOnSwitch: End"
}
def turnOffSwitch(Relay) {
log.debug "turnOffSwitch: Begin"
log.debug "Relay is $Relay" // 11:39:00 AM: debug Relay is null
log.debug "Relay is ${Relay.currentSwitch}"
if (Relay.currentSwitch == "on") {
Relay.off()
}
log.debug "turnOffSwitch: End"
}