The foundation is based on the Sample Rules - Irrigation Controller.. However, I would like to improve upon this design by using an actual rain gauge and simplifying the rules on how often & how much to run the sprinklers. My goal is to conservatively water my yard every other day with a weekly total of 1 inch of water.
Many of the values are changed by setpiont for testing purposes.
Let’s start with the ITEMS. I’ve changed them to more generic names. Check groups on items as they are not included.
//---------------Irrigation----------------
Number Weather_Rain_Trigger "Manual Trip for Rainfall [%.2f in]" <rain> (All)
// Weather_Rain_Trigger is intended to simulate the reed switch rain guage
Number Weather_Rain "Manual Rainfall Today (future tipping bucket)[%.2f in]" <rain> (All)
// Weather_Rain is intended to be the current days rainfall
Number Weather_Rain_Cumulative "Manual Rainfall Last 2 Days (future tipping bucket)[%.2f in]" <rain> (All)
// Weather_Rain is intended to be the rainfall from the last two days
Number Precip_Probability_0 "Precip Probability Today [%d %%]" <rain> (Irrigation,Test) {weather="locationId=home, type=precipitation, property=probability"}
Number Precip_Probability_1 "Precip Probability Tomorrow[%d %%]" <rain> (Irrigation,Test) {weather="locationId=home, forecast=1, type=precipitation, property=probability"}
Switch Irrigation_Master "irrigation Master" <sprinkler> (All,Sate,Masters,Irrigation)
// On|Off switch for whole irrigation system
String Irrigation_Start_Time "Start Time [%s]" <calendar> (Irrigation)
// Time the system would normally turn on
Number Irrigation_Scale_Factor "Scale Factor Master [%d %%]" <water> (Irrigation)
// Percentage of Runtime to conserve water
//---------------Runtime for each relay----------------
Number Irrigation_Relay_1_Mins "Relay 1 Runtime[%d mins]" <water> (Irrigation)
Number Irrigation_Relay_2_Mins "Relay 2 Runtime[%d mins]" <water> (Irrigation)
Number Irrigation_Relay_3_Mins "Relay 3 Runtime[%d mins]" <water> (Irrigation)
Number Irrigation_Relay_4_Mins "Relay 4 Runtime[%d mins]" <water> (Irrigation)
Number Irrigation_Relay_5_Mins "Relay 5 Runtime[%d mins]" <water> (Irrigation)
Number Irrigation_Relay_6_Mins "Relay 6 Runtime[%d mins]" <water> (Irrigation)
//---------------Last time each relay was actuated----------------
DateTime Irrigation_Relay_1_Time "Relay 1 Last Run [%1$tm/%1$td, %1$tI:%1$tM %1$tp]" <DateTimeIcon> (All,Updates,Irrigation)
DateTime Irrigation_Relay_2_Time "Relay 2 Last Run [%1$tm/%1$td, %1$tI:%1$tM %1$tp]" <DateTimeIcon> (All,Updates,Irrigation)
DateTime Irrigation_Relay_3_Time "Relay 3 Last Run [%1$tm/%1$td, %1$tI:%1$tM %1$tp]" <DateTimeIcon> (All,Updates,Irrigation)
DateTime Irrigation_Relay_4_Time "Relay 4 Last Run [%1$tm/%1$td, %1$tI:%1$tM %1$tp]" <DateTimeIcon> (All,Updates,Irrigation)
DateTime Irrigation_Relay_5_Time "Relay 5 Last Run [%1$tm/%1$td, %1$tI:%1$tM %1$tp]" <DateTimeIcon> (All,Updates,Irrigation)
DateTime Irrigation_Relay_6_Time "Relay 6 Last Run [%1$tm/%1$td, %1$tI:%1$tM %1$tp]" <DateTimeIcon> (All,Updates,Irrigation)
//---------------Relays that trigger the irrigation zones (can also bind with OpenSprkinker----------------
Switch Irrigation_Relay_1 "Relay 1 Switch" <water> (Irrigation_Relay,Irrigation)
Switch Irrigation_Relay_2 "Relay 2 Switch" <water> (Irrigation_Relay,Irrigation)
Switch Irrigation_Relay_3 "Relay 3 Switch" <water> (Irrigation_Relay,Irrigation)
Switch Irrigation_Relay_4 "Relay 4 Switch" <water> (Irrigation_Relay,Irrigation)
Switch Irrigation_Relay_5 "Relay 5 Switch" <water> (Irrigation_Relay,Irrigation)
Switch Irrigation_Relay_6 "Relay 6 Switch" <water> (Irrigation_Relay,Irrigation)
DateTime Weather_Last_Update "Weather Binding Last Update [%1$tm/%1$td, %1$tI:%1$tM %1$tp]" <DateTimeIcon> (Irrigation,Updates)
Now onto the RULES… I think it is best to break them up as some may not need to be changed.
Variables
val String MailTo1 = "someone@yourdomain.comt"
var Number RainIncr = 0
rule "Irrigation startup"
when
System started
then
postUpdate(Irrigation_Start_Time, "05:00")
Irrigation_Relay?.members.forEach(Switch | {
Switch.sendCommand(OFF)
})
end
rule "Irrigation run"
when
Time cron "0 0 5 1/1 * ? *"
then
if (Irrigation_Master.state == ON) {
// get the scale factor - used to reduce the run times across the board
var Number scaleFactor = Irrigation_Scale_Factor.state as DecimalType
// convert our start time to a joda.time.DateTime for today
var DateTime startTime = parse(now.getYear() + "-" + now.getMonthOfYear() + "-" + now.getDayOfMonth() + "T" + Irrigation_Start_Time.state + ":00")
var DateTime endTime
// get the raw run times for each zone (in mins)
var Number R1Mins = Irrigation_Relay_1_Mins.state as DecimalType
var Number R2Mins = Irrigation_Relay_2_Mins.state as DecimalType
var Number R3Mins = Irrigation_Relay_3_Mins.state as DecimalType
var Number R4Mins = Irrigation_Relay_4_Mins.state as DecimalType
var Number R5Mins = Irrigation_Relay_5_Mins.state as DecimalType
var Number R6Mins = Irrigation_Relay_6_Mins.state as DecimalType
// convert to the actual run times (by applying the scale factor)
var int R1Time = ((R1Mins * scaleFactor) / 100).intValue
var int R2Time = ((R2Mins * scaleFactor) / 100).intValue
var int R3Time = ((R3Mins * scaleFactor) / 100).intValue
var int R4Time = ((R4Mins * scaleFactor) / 100).intValue
var int R5Time = ((R5Mins * scaleFactor) / 100).intValue
var int R6Time = ((R6Mins * scaleFactor) / 100).intValue
// turn on each zone in turn (with a minute gap between each zone activation)
if (R1Time > 0) {
endTime = startTime.plusMinutes(R1Time)
createTimer(startTime) [| sendCommand(Irrigation_Relay_1, ON) ]
createTimer(endTime) [| sendCommand(Irrigation_Relay_1, OFF) ]
startTime = endTime.plusMinutes(1)
}
if (R2Time > 0) {
endTime = startTime.plusMinutes(R2Time)
createTimer(startTime) [| sendCommand(Irrigation_Relay_2, ON) ]
createTimer(endTime) [| sendCommand(Irrigation_Relay_2, OFF) ]
startTime = endTime.plusMinutes(1)
}
if (R3Time > 0) {
endTime = startTime.plusMinutes(R3Time)
createTimer(startTime) [| sendCommand(Irrigation_Relay_3, ON) ]
createTimer(endTime) [| sendCommand(Irrigation_Relay_3, OFF) ]
startTime = endTime.plusMinutes(1)
}
if (R4Time > 0) {
endTime = startTime.plusMinutes(R4Time)
createTimer(startTime) [| sendCommand(Irrigation_Relay_4, ON) ]
createTimer(endTime) [| sendCommand(Irrigation_Relay_4, OFF) ]
startTime = endTime.plusMinutes(1)
}
if (R4Time > 0) {
endTime = startTime.plusMinutes(R5Time)
createTimer(startTime) [| sendCommand(Irrigation_Relay_5, ON) ]
createTimer(endTime) [| sendCommand(Irrigation_Relay_5, OFF) ]
startTime = endTime.plusMinutes(1)
}
if (R4Time > 0) {
endTime = startTime.plusMinutes(R6Time)
createTimer(startTime) [| sendCommand(Irrigation_Relay_6, ON) ]
createTimer(endTime) [| sendCommand(Irrigation_Relay_6, OFF) ]
startTime = endTime.plusMinutes(1)
}
}
end
This is the rule that I believe we can simplify.
rule "Disable irrigation if any rain"
when
Item Weather_Rain changed or
Item Weather_Today_Icon changed or
Item Weather_Tomorrow_Icon changed
or
Time cron "0 0 10 1/1 * ? *"
then
// the rainfall threshold where we shutdown off irrigation
var rainThreshold = 1
// check for any rain in the last 24 hours
var rainInLast24Hours = Weather_Rain.maximumSince(now.minusHours(24), "rrd4j")
// default to the current rain value in case there is nothing in our history
var rain = Weather_Rain.state
if (rainInLast24Hours != null)
rain = rainInLast24Hours.state
// check if any rain is forecast
var rainToday = Weather_Today_Icon.state == "chanceflurries" ||
Weather_Today_Icon.state == "chancerain" ||
Weather_Today_Icon.state == "chancesleet" ||
Weather_Today_Icon.state == "chancesnow" ||
Weather_Today_Icon.state == "chancetstorms" ||
Weather_Today_Icon.state == "flurries" ||
Weather_Today_Icon.state == "rain" ||
Weather_Today_Icon.state == "sleet" ||
Weather_Today_Icon.state == "snow" ||
Weather_Today_Icon.state == "tstorms"
var rainTomorrow = Weather_Tomorrow_Icon.state == "chanceflurries" ||
Weather_Tomorrow_Icon.state == "chancerain" ||
Weather_Tomorrow_Icon.state == "chancesleet" ||
Weather_Tomorrow_Icon.state == "chancesnow" ||
Weather_Tomorrow_Icon.state == "chancetstorms" ||
Weather_Tomorrow_Icon.state == "flurries" ||
Weather_Tomorrow_Icon.state == "rain" ||
Weather_Tomorrow_Icon.state == "sleet" ||
Weather_Tomorrow_Icon.state == "snow" ||
Weather_Tomorrow_Icon.state == "tstorms"
// shutoff irrigation if there has been rain or rain is forecast
var logMessage = ""
if (rain > rainThreshold) {
logMessage = "Rain in the last 24 hours (" + rain + " mm) is above our threshold (" + rainThreshold + " mm) - irrigation disabled!"
} else if (rainToday) {
logMessage = "Rain is forecast for today - irrigation disabled!"
} else if (rainTomorrow) {
logMessage = "Rain is forecast for tomorrow - irrigation disabled!"
}
if (logMessage != "") {
if (Irrigation_Master.state == ON) {
logInfo("Irrigation", logMessage)
sendMail(MailTo1 , "Irrigation Notice", logMessage)
postUpdate(Irrigation_Master, OFF)
}
} else {
if (Irrigation_Master.state == OFF) {
logInfo("Irrigation", "No rain in the last 24 hours or any rain forecast - irrigation enabled!")
sendMail(MailTo1 , "Irrigation Notice", "No rain in the last 24 hours or any rain forecast - irrigation enabled!")
postUpdate(Irrigation_Master, ON)
}
}
end