Wauw, this was exactly what I needed to kick-start my irrigation program. Have been doubting a while to just buy an irrigation computer or program something myself. Stumbled upon YAWS and loved it.
I’ve extended it to 7 zones which are grouped in 3 groups. Created 3 individual times and incorporated a weather dependent option copied from the Zimmerman principle in OpenSprikler. Oh and I’ve made a link with Apple HomeKit so I can set the irrigation times using HomeKit on my iPhone/iPad etc.
Not completely satisfied with how the groups are related to the individual zones as the remaining time for the zones isn’t updated if a group is used for irrigation. Need to figure something out at some point, but for now it’s working.
Also I created a “every other day” function where the minimum time between 2 starts can be set (for each program separatey).
And last, I translated the user labels to Dutch as I’m from The Netherlands, but left all internals to English so should be readable for most.
Let me know if you have questions or find better ways to accomplish things.
ps. not all zones are linked yet to a KNX actuator as I don’t have more outputs available currently. Work in Progress…
// items for YAWS - Yet Another Watering Solution https://community.openhab.org/t/yaws-yet-another-watering-solution/101945
// settings group
Group Group_Irrigation_Settings
// program 1 group
Group Group_Program1_Settings
// program 2 group
Group Group_Program2_Settings
// program 3 group
Group Group_Program3_Settings
// active program
Number ActiveProgram "Actieve programma [%d]" (everyChange_Startup)
// irrigation lock
Switch IrrigationLock "Programma" (Group_Irrigation_Settings, everyChange_Startup)
// protection against too long watering, 2h default
Switch IrrigationTimerMax "Max irrigation time [%s]" (everyChange_Startup) { expire = "6h,command=OFF" }
// all valves group
Group:Switch:OR(ON,OFF) GroupIrrigationValves "Irrigation valves [%s]"
Group:Number:SUM GroupIrrigationTimes "Total irrigation time [%d s]"
Group:Number:SUM GroupRemainingTime "Total remaining irrigation time [%d s]"
// groups of valves to have multiple valves open simultaniously
//Group:Switch:AND(ON,OFF) IrrigationValveZone8 "Sproeiers achtertuin"
//Group:Switch:AND(ON,OFF) IrrigationValveZone9 "Sproeiers voortuin"
//Group:Switch:AND(ON,OFF) IrrigationValveZone10 "Alle druppelzones"
// cascading valves - current zone
String IrrigationCurrentValve "Current irrigation zone [%s]"
// integration HomeKit items//
// Group 1, dripline border backyard
Group gValve1 "Druppel border" {homekit="Valve" [homekitValveType="Irrigation"]}
Switch IrrigationValveZone1 "Zone 1 active" (gValve1, GroupIrrigationValves, IrrigationValveZone10) {homekit = "Valve.ActiveStatus, Valve.InUseStatus"}
Number IrrigationValveZone1Time "Zone 1: Druppel border achtertuin [%d s]" (gValve1, GroupIrrigationTimes, Group_Irrigation_Settings) {homekit = "Valve.Duration"}
Number RemainingTimeZone1 "Valve 1 remaining duration" (gValve1, GroupRemainingTime) {homekit = "Valve.RemainingDuration"}
// Group 2, sprinklers backside backyard
Group gValve2 "Sproeier 1 AT" {homekit="Valve" [homekitValveType="Irrigation"]}
Switch IrrigationValveZone2 "Zone 2 active" (gValve2, GroupIrrigationValves, IrrigationValveZone8) {homekit = "Valve.ActiveStatus, Valve.InUseStatus", channel="knx:device:bridge:generic:Valve2"}
Number IrrigationValveZone2Time "Zone 2: Sproeier 1 achtertuin [%d s]" (gValve2, GroupIrrigationTimes, Group_Irrigation_Settings) {homekit = "Valve.Duration"}
Number RemainingTimeZone2 "Valve 2 remaining duration" (gValve2, GroupRemainingTime) {homekit = "Valve.RemainingDuration"}
// Group 3, dripline trees backyard
Group gValve3 "Druppel bomen AT" {homekit="Valve" [homekitValveType="Irrigation"]}
Switch IrrigationValveZone3 "Zone 3 active" (gValve3, GroupIrrigationValves, IrrigationValveZone10) {homekit = "Valve.ActiveStatus, Valve.InUseStatus"}
Number IrrigationValveZone3Time "Zone 3: Druppel bomen achtertuin [%d s]" (gValve3, GroupIrrigationTimes, Group_Irrigation_Settings) {homekit = "Valve.Duration"}
Number RemainingTimeZone3 "Valve 3 remaining duration" (gValve3, GroupRemainingTime) {homekit = "Valve.RemainingDuration"}
// Group 4, sprinklers frontside backyard
Group gValve4 "Sproeier 2 AT" {homekit="Valve" [homekitValveType="Irrigation"]}
Switch IrrigationValveZone4 "Zone 4 active" (gValve4, GroupIrrigationValves, IrrigationValveZone8) {homekit = "Valve.ActiveStatus, Valve.InUseStatus", channel="knx:device:bridge:generic:Valve4"}
Number IrrigationValveZone4Time "Zone 4: Sproeier 2 achtertuin [%d s]" (gValve4, GroupIrrigationTimes, Group_Irrigation_Settings) {homekit = "Valve.Duration"}
Number RemainingTimeZone4 "Valve 4 remaining duration" (gValve4, GroupRemainingTime) {homekit = "Valve.RemainingDuration"}
// Group 5, sprinkler house side frontyard
Group gValve5 "Sproeier 1 VT" {homekit="Valve" [homekitValveType="Irrigation"]}
Switch IrrigationValveZone5 "Zone 5 active" (gValve5, GroupIrrigationValves, IrrigationValveZone9) {homekit = "Valve.ActiveStatus, Valve.InUseStatus", channel="knx:device:bridge:generic:Valve5"}
Number IrrigationValveZone5Time "Zone 5: Sproeier 1 voortuin [%d s]" (gValve5, GroupIrrigationTimes, Group_Irrigation_Settings) {homekit = "Valve.Duration"}
Number RemainingTimeZone5 "Valve 5 remaining duration" (gValve5, GroupRemainingTime) {homekit = "Valve.RemainingDuration"}
// Group 6, dripline trees frontyard
Group gValve6 "Druppel bomen VT" {homekit="Valve" [homekitValveType="Irrigation"]}
Switch IrrigationValveZone6 "Zone 6 active" (gValve6, GroupIrrigationValves, IrrigationValveZone10) {homekit = "Valve.ActiveStatus, Valve.InUseStatus"}
Number IrrigationValveZone6Time "Zone 6: Druppel bomen voortuin [%d s]" (gValve6, GroupIrrigationTimes, Group_Irrigation_Settings) {homekit = "Valve.Duration"}
Number RemainingTimeZone6 "Valve 6 remaining duration" (gValve6, GroupRemainingTime) {homekit = "Valve.RemainingDuration"}
// Group 7, sprinkler road side frontyard
Group gValve7 "Sproeier 2 VT" {homekit="Valve" [homekitValveType="Irrigation"]}
Switch IrrigationValveZone7 "Zone 7 active" (gValve7, GroupIrrigationValves, IrrigationValveZone9) {homekit = "Valve.ActiveStatus, Valve.InUseStatus", channel="knx:device:bridge:generic:Valve7"}
Number IrrigationValveZone7Time "Zone 7: Sproeier 2 voortuin [%d s]" (gValve7, GroupIrrigationTimes, Group_Irrigation_Settings) {homekit = "Valve.Duration"}
Number RemainingTimeZone7 "Valve 7 remaining duration" (gValve7, GroupRemainingTime) {homekit = "Valve.RemainingDuration"}
// Group 8, all sprinkler valves backyard
Group:Switch:AND(ON,OFF) IrrigationValveZone8 "Sproeiers achtertuin" (GroupIrrigationValves)
Number IrrigationValveZone8Time "Sproeiers achtertuin [%d s]" (GroupIrrigationTimes, Group_Irrigation_Settings)
Number RemainingTimeZone8 "Valve 8 remaining duration" (GroupRemainingTime)
/////
// Group 9, all sprinkler valves frontyard
Group:Switch:AND(ON,OFF) IrrigationValveZone9 "Sproeiers voortuin" (GroupIrrigationValves)
Number IrrigationValveZone9Time "Sproeiers voortuin [%d s]" (GroupIrrigationTimes, Group_Irrigation_Settings)
Number RemainingTimeZone9 "Valve 9 remaining duration" (GroupRemainingTime)
/////
// Group 10, all sprinkler valves backyard
Group:Switch:AND(ON,OFF) IrrigationValveZone10 "Druppelslangen" (GroupIrrigationValves)
Number IrrigationValveZone10Time "Druppelslangen [%d s]" (GroupIrrigationTimes, Group_Irrigation_Settings)
Number RemainingTimeZone10 "Valve 10 remaining duration" (GroupRemainingTime)
/////
// irrigation variables
Number IrrigationDurationCoefficientFactor "Correction factor"
Number:Time IrrigationSectionRemainingTime "Resterende tijd huidige zone [%d s]"
// switch - whether to start at a particular hour or before the sunrise
Switch Program1IrrigationStartAtSpecificHour "Start op vast tijdstip" (Group_Program1_Settings, everyChange_Startup)
Number Program1IrrigationStartTime "Starttijd beregening" (Group_Program1_Settings, everyChange_Startup)
Number Program1IrrigationHoursBeforeSunrise "Start beregening voor zonsopkomst [%d u]" (Group_Program1_Settings, everyChange_Startup)
Switch Program1WeatherAdjust "Weersafhankelijke aanpassing" (Group_Program1_Settings, everyChange_Startup)
Switch Program2IrrigationStartAtSpecificHour "Start op vast tijdstip" (Group_Program2_Settings)
Number Program2IrrigationStartTime "Starttijd beregening" (Group_Program2_Settings)
Number Program2IrrigationHoursBeforeSunrise "Start beregening voor zonsopkomst [%d u]" (Group_Program2_Settings)
Switch Program2WeatherAdjust "Weersafhankelijke aanpassing" (Group_Program2_Settings)
Switch Program3IrrigationStartAtSpecificHour "Start op vast tijdstip" (Group_Program3_Settings)
Number Program3IrrigationStartTime "Starttijd beregening" (Group_Program3_Settings)
Number Program3IrrigationHoursBeforeSunrise "Start beregening voor zonsopkomst [%d u]" (Group_Program3_Settings)
Switch Program3WeatherAdjust "Weersafhankelijke aanpassing" (Group_Program3_Settings)
// irrigation week days
Group:Switch:OR(ON,OFF) Group_Program1Days "Programma 1 [%s]"
Switch Program1SpecificDays "Specifieke dagen" (Group_Program1Days, everyChange_Startup)
Switch Program1IrrigationDay1 "Maandag" (Group_Program1Days, everyChange_Startup)
Switch Program1IrrigationDay2 "Dinsdag" (Group_Program1Days, everyChange_Startup)
Switch Program1IrrigationDay3 "Woensdag" (Group_Program1Days, everyChange_Startup)
Switch Program1IrrigationDay4 "Donderdag" (Group_Program1Days, everyChange_Startup)
Switch Program1IrrigationDay5 "Vrijdag" (Group_Program1Days, everyChange_Startup)
Switch Program1IrrigationDay6 "Zaterdag" (Group_Program1Days, everyChange_Startup)
Switch Program1IrrigationDay7 "Zondag" (Group_Program1Days, everyChange_Startup)
DateTime Program1LastRun "Programma 1 laatste start [%1$td-%1$tm-%1$tY %1$tH:%1$tM:%1$tS]" (everyChange_Startup)
Switch Program1EOD "Programma 1 laatste 24u actief" (everyChange_Startup)
Number Program1HoursSinceLastRun "Aantal uur sinds laatste start [%d u]" (everyChange_Startup)
Number Program1MinHoursBetween "Minimaal aantal uur tussen 2 starts [%d u]" (everyChange_Startup)
Group:Switch:OR(ON,OFF) Group_Program2Days "Programma 2 [%s]"
Switch Program2SpecificDays "Specifieke dagen" (Group_Program2Days, everyChange_Startup)
Switch Program2IrrigationDay1 "Maandag" (Group_Program2Days, everyChange_Startup)
Switch Program2IrrigationDay2 "Dinsdag" (Group_Program2Days, everyChange_Startup)
Switch Program2IrrigationDay3 "Woensdag" (Group_Program2Days, everyChange_Startup)
Switch Program2IrrigationDay4 "Donderdag" (Group_Program2Days, everyChange_Startup)
Switch Program2IrrigationDay5 "Vrijdag" (Group_Program2Days, everyChange_Startup)
Switch Program2IrrigationDay6 "Zaterdag" (Group_Program2Days, everyChange_Startup)
Switch Program2IrrigationDay7 "Zondag" (Group_Program2Days, everyChange_Startup)
DateTime Program2LastRun "Programma 2 laatste start [%1$td-%1$tm-%1$tY %1$tH:%1$tM:%1$tS]" (everyChange_Startup)
Switch Program2EOD "Programma 2 laatste 24u actief" (everyChange_Startup)
Number Program2HoursSinceLastRun "Aantal uur sinds laatste start [%d u]" (everyChange_Startup)
Number Program2MinHoursBetween "Minimaal aantal uur tussen 2 starts [%d u]" (everyChange_Startup)
Group:Switch:OR(ON,OFF) Group_Program3Days "Programma 3 [%s]"
Switch Program3SpecificDays "Specifieke dagen" (Group_Program3Days, everyChange_Startup)
Switch Program3IrrigationDay1 "Maandag" (Group_Program3Days, everyChange_Startup)
Switch Program3IrrigationDay2 "Dinsdag" (Group_Program3Days, everyChange_Startup)
Switch Program3IrrigationDay3 "Woensdag" (Group_Program3Days, everyChange_Startup)
Switch Program3IrrigationDay4 "Donderdag" (Group_Program3Days, everyChange_Startup)
Switch Program3IrrigationDay5 "Vrijdag" (Group_Program3Days, everyChange_Startup)
Switch Program3IrrigationDay6 "Zaterdag" (Group_Program3Days, everyChange_Startup)
Switch Program3IrrigationDay7 "Zondag" (Group_Program3Days, everyChange_Startup)
DateTime Program3LastRun "Programma 3 laatste start [%1$td-%1$tm-%1$tY %1$tH:%1$tM:%1$tS]" (everyChange_Startup)
Switch Program3EOD "Programma 3 laatste 24u actief" (everyChange_Startup)
Number Program3HoursSinceLastRun "Aantal uur sinds laatste start [%d u]" (everyChange_Startup)
Number Program3MinHoursBetween "Minimaal aantal uur tussen 2 starts [%d u]" (everyChange_Startup)
Group:Switch:OR(ON,OFF) Group_Program_Zones "Programma zones [%s]"
Switch Program1Zone1 "Zone 1: Druppel border achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone2 "Zone 2: Sproeier 1 achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone3 "Zone 3: Druppel bomen achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone4 "Zone 4: Sproeier 2 achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone5 "Zone 5: Sproeier 1 voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone6 "Zone 6: Druppel bomen voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone7 "Zone 7: Sproeier 2 voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone8 "Sproeiers achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone9 "Sproeiers voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program1Zone10 "Druppelslangen" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone1 "Zone 1: Druppel border achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone2 "Zone 2: Sproeier 1 achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone3 "Zone 3: Druppel bomen achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone4 "Zone 4: Sproeier 2 achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone5 "Zone 5: Sproeier 1 voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone6 "Zone 6: Druppel bomen voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone7 "Zone 7: Sproeier 2 voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone8 "Sproeiers achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone9 "Sproeiers voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program2Zone10 "Druppelslangen" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone1 "Zone 1: Druppel border achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone2 "Zone 2: Sproeier 1 achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone3 "Zone 3: Druppel bomen achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone4 "Zone 4: Sproeier 2 achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone5 "Zone 5: Sproeier 1 voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone6 "Zone 6: Druppel bomen voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone7 "Zone 7: Sproeier 2 voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone8 "Sproeiers achtertuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone9 "Sproeiers voortuin" (Group_Program_Zones, everyChange_Startup)
Switch Program3Zone10 "Druppelslangen" (Group_Program_Zones, everyChange_Startup)
Number:Length SumRainLast24h "Neerslag, laatste 24u [%.2f mm]"
Number:Length SumRainNext24h "Neerslag, voorspelling 24u [%.2f mm]"
//Number:Speed avgWindLast2h "Windsnelheid afgelopen 2u [%d km/h]"
//Number:Speed avgWindNext3h "Windsnelheid voorspelling 3u [%d km/h]"
Number:Speed MaxAllowedWindSpeed "Max allowed windspeed [%d km/h]" (Group_Irrigation_Settings, everyChange_Startup)
Number:Length MaxAllowedRain "Max allowed rainfall sum [%.1f mm]" (Group_Irrigation_Settings, everyChange_Startup)
Number TempBaseLine "Temperature base line" (Group_Irrigation_Settings, everyChange_Startup)
Number TempAdjustment "Percentage change / 1 deg change" (Group_Irrigation_Settings, everyChange_Startup)
Number HumidityBaseLine "Humidity base line" (Group_Irrigation_Settings, everyChange_Startup)
Number RainAdjustment "Percentage change / 1mm rain" (Group_Irrigation_Settings, everyChange_Startup)
Number CoefficientPercentage "Weersafhankelijke optimalisatie 0-200% [%.1f %%]"
Number:Temperature AverageTemperature24h "Gemiddelde temperatuur afgelopen 24u [%.1f %unit%]"
Number AverageHumidity24h "Gemiddelde luchtvochtigheid afgelopen 24u [%.0f %%]"
DateTime LastStart "Laatste cyclus start [%1$td-%1$tm-%1$tY %1$tH:%1$tM:%1$tS]"
DateTime LastEnd "Laatste cyclus einde [%1$td-%1$tm-%1$tY %1$tH:%1$tM:%1$tS]"
// rules for YAWS - Yet Another Watering Solution https://community.openhab.org/t/yaws-yet-another-watering-solution/101945
/*
* Irrigation rules
*/
//import org.eclipse.smarthome.model.script.ScriptServiceUtil
import org.openhab.core.model.script.ScriptServiceUtil
import java.time.temporal.ChronoUnit
val logName = "Irrigation"
var Timer irrigationTimer = null
// Total rain fall over past 24h and forecasted 24h
var Number RainTotal = 0
// Wind speed averages to limit spray of lawn sprinklers
var Number avgWindLast2h = 0
var Number avgWindNext3h = 0
// Average temperature and humidity over past 24h
var Number avgTemperatureLast24h = 20
var Number avgHumidity24h = 60
// watering time correction factor - based on the average temperature, humidity and rain
var Number coefficientFactor = 1
rule "Irrigation - system start"
when
System started
then
// initiall default settings
if (SumRainLast24h.state == NULL)
SumRainLast24h.sendCommand(0)
if (SumRainNext24h.state == NULL)
SumRainNext24h.sendCommand(0)
if (MaxAllowedWindSpeed.state == NULL)
MaxAllowedWindSpeed.sendCommand(35)
if (MaxAllowedRain.state == NULL)
MaxAllowedRain.sendCommand(3)
if (TempBaseLine.state == NULL)
TempBaseLine.sendCommand(20)
if (TempAdjustment.state == NULL)
TempAdjustment.sendCommand(5)
if (HumidityBaseLine.state == NULL)
HumidityBaseLine.sendCommand(60)
if (RainAdjustment.state == NULL)
RainAdjustment.sendCommand(8)
if (ActiveProgram.state == NULL)
ActiveProgram.sendCommand(0)
// Init program 1 settings
if (Program1IrrigationHoursBeforeSunrise.state == NULL)
Program1IrrigationHoursBeforeSunrise.sendCommand(1)
if (Program1IrrigationStartAtSpecificHour.state == NULL)
Program1IrrigationStartAtSpecificHour.sendCommand(OFF)
if (Program1SpecificDays.state == NULL)
Program1SpecificDays.sendCommand(OFF)
if (Program1IrrigationStartTime.state == NULL)
Program1IrrigationStartTime.sendCommand(5)
if (Program1WeatherAdjust.state == NULL)
Program1WeatherAdjust.sendCommand(OFF)
if (Program1EOD.state == NULL)
Program1EOD.sendCommand(OFF)
if (Program1HoursSinceLastRun.state == NULL)
Program1HoursSinceLastRun.postUpdate(0)
if (Program1MinHoursBetween.state == NULL)
Program1MinHoursBetween.postUpdate(36)
// Init all irrigation days to OFF if not set (null)
Group_Program1Days.members.filter[day | day.state == NULL].forEach[day | day.sendCommand(OFF)]
// Init program 2 settings
if (Program2IrrigationHoursBeforeSunrise.state == NULL)
Program2IrrigationHoursBeforeSunrise.sendCommand(1)
if (Program2IrrigationStartAtSpecificHour.state == NULL)
Program2IrrigationStartAtSpecificHour.sendCommand(OFF)
if (Program2SpecificDays.state == NULL)
Program2SpecificDays.sendCommand(OFF)
if (Program2IrrigationStartTime.state == NULL)
Program2IrrigationStartTime.sendCommand(5)
if (Program2WeatherAdjust.state == NULL)
Program2WeatherAdjust.sendCommand(OFF)
if (Program2EOD.state == NULL)
Program2EOD.sendCommand(OFF)
if (Program2HoursSinceLastRun.state == NULL)
Program2HoursSinceLastRun.postUpdate(0)
if (Program2MinHoursBetween.state == NULL)
Program2MinHoursBetween.postUpdate(36)
// Init all irrigation days to OFF if not set (null)
Group_Program2Days.members.filter[day | day.state == NULL].forEach[day | day.sendCommand(OFF)]
// Init program 3 settings
if (Program3IrrigationHoursBeforeSunrise.state == NULL)
Program3IrrigationHoursBeforeSunrise.sendCommand(1)
if (Program3IrrigationStartAtSpecificHour.state == NULL)
Program3IrrigationStartAtSpecificHour.sendCommand(OFF)
if (Program3SpecificDays.state == NULL)
Program3SpecificDays.sendCommand(OFF)
if (Program3IrrigationStartTime.state == NULL)
Program3IrrigationStartTime.sendCommand(5)
if (Program3WeatherAdjust.state == NULL)
Program3WeatherAdjust.sendCommand(OFF)
if (Program3EOD.state == NULL)
Program3EOD.sendCommand(OFF)
if (Program3HoursSinceLastRun.state == NULL)
Program3HoursSinceLastRun.postUpdate(0)
if (Program3MinHoursBetween.state == NULL)
Program3MinHoursBetween.postUpdate(36)
// Init all irrigation days to OFF if not set (null)
Group_Program3Days.members.filter[day | day.state == NULL].forEach[day | day.sendCommand(OFF)]
// Init all zones to OFF if not set (null)
Group_Program_Zones.members.filter[zone | zone.state == NULL].forEach[zone | zone.sendCommand(OFF)]
// Init default zone irrigation times
GroupIrrigationTimes.members.filter[time | time.state == NULL].forEach[time | time.sendCommand(60)]
// Init irrigation remaining times to 0
GroupRemainingTime.members.filter[time | time.state == NULL].forEach[time | time.sendCommand(0)]
// close all valves
GroupIrrigationValves.members.filter[valve | valve.state != OFF].forEach[valve | valve.sendCommand(OFF)]
IrrigationCurrentValve.postUpdate(OFF)
logInfo(logName, "init all default settings")
end
rule "Irrigation - Generic calculations"
when
Time cron "0 * * ? * *" // every minute
then
try {
logDebug(logName, "Calculating generic irrigation parameters")
// calculate hours after last run
Program1HoursSinceLastRun.postUpdate(ChronoUnit.HOURS.between((Program1LastRun.state as DateTimeType).zonedDateTime, (new DateTimeType()).zonedDateTime))
Program2HoursSinceLastRun.postUpdate(ChronoUnit.HOURS.between((Program2LastRun.state as DateTimeType).zonedDateTime, (new DateTimeType()).zonedDateTime))
Program3HoursSinceLastRun.postUpdate(ChronoUnit.HOURS.between((Program3LastRun.state as DateTimeType).zonedDateTime, (new DateTimeType()).zonedDateTime))
// calculate wind speed
avgWindLast2h = (WindSpeed.averageSince(now.minusHours(2), "influxdb") as Number).doubleValue * 3.6
avgWindNext3h = GroupForecastedWind3Sum.state as Number
logDebug(logName, "Windspeed last 2h: {}km/h, next 3h: {}km/h", avgWindLast2h, avgWindNext3h)
// calculate rain fall history
SumRainLast24h.sendCommand((localCurrentRainVolume.sumSince(now.minusHours(24), "influxdb") as Number).doubleValue)
SumRainNext24h.sendCommand(GroupForecastedRain24Sum.state as Number)
RainTotal = (SumRainLast24h.state as Number).doubleValue + (SumRainNext24h.state as Number).doubleValue
logDebug(logName, "Rain last 24h: {}mm, next 24h: {}mm, total: {}mm", SumRainLast24h.state, SumRainNext24h.state, RainTotal)
// if the temperature is to low, don't start watering
avgTemperatureLast24h = (localCurrentTemperature.averageSince(now.minusHours(24), "influxdb") as Number).doubleValue
AverageTemperature24h.sendCommand(avgTemperatureLast24h)
logDebug(logName, "Average temperature last 24h: {}", avgTemperatureLast24h)
avgHumidity24h = (localCurrentHumidity.averageSince(now.minusHours(24), "influxdb") as Number).doubleValue
AverageHumidity24h.sendCommand(avgHumidity24h)
logDebug(logName, "Average humidity last 24h: {}%", avgHumidity24h)
// let's wait for propagating item values
Thread::sleep(100)
if (avgTemperatureLast24h <= 10) {
CoefficientPercentage.postUpdate(0)
logDebug(logName, "Temperature too low. Setting irrigation coefficient percentage to {}%", CoefficientPercentage)
return
}
else if (avgTemperatureLast24h > 30) {
CoefficientPercentage.postUpdate(200)
logDebug(logName, "Temperature very high. Setting irrigation coefficient percentage to {}%", CoefficientPercentage)
}
else {
// The software can be configured to use weather data to make adjustments to the irrigation duration automatically. The data is retrieved from openweathermap and uses the following parameters to adjust the duration:
// Original by https://github.com/rszimm/sprinklers_pi/wiki/Weather-adjustments
// Average humidity for the previous day.
// Average temperature for the previous day.
// Total precipitation for the previous day.
// Total precipitation for the current day.
// The weather adjustment formula uses a (configurable) baseline of 20deg C, 60% Humidity and no precipitation.
// Humidity: Average humidity for the previous day above 60% is subtracted from the weather adjustment, below 60% is added to it. Example: 60% - 51% Avg Humidity = 9% Humidity Adjustment
val HumidityPercentage = (((HumidityBaseLine.state as Number) - avgHumidity24h) * 1000).intValue
// Temperature: +5% for each degree Celcius above 20, and -5% for each degree Celcius below 20.
val TemperaturePercentage = (((avgTemperatureLast24h - (TempBaseLine.state as Number)) * (TempAdjustment.state as Number)) * 1000).intValue
// Precipitation: -8% for each 1mm of precipitation from today and yesterday. Example: 3mm rain today + 1.27mm rain yesterday = 4.27 mm of rain * -8 = -34.16% Precipitation Adjustment
val PrecipitationPercentage = ((RainTotal * (RainAdjustment.state as Number) * -1) * 1000).intValue // multiply with -1 to get to negative value as precipitation needs to be substracted
val CoeffPct = (100 + (((HumidityPercentage as Number) + (TemperaturePercentage as Number) + (PrecipitationPercentage as Number))/1000)).intValue
if (CoeffPct < 0) {
CoefficientPercentage.postUpdate(0)
}
else {
CoefficientPercentage.postUpdate(CoeffPct)
}
logDebug(logName, "Calculated coefficient percentage {}%", CoeffPct)
}
}
catch (Exception e) {
logError(logName, "Error calculating generic parameters: " + e)
}
end
rule "Irrigation - calculate whether to start watering program 1"
when
Time cron "1 * * ? * *" // every minute, 1 second after generic calculations
then
try {
logDebug(logName, "Calculating whether to start irrigation program 1")
///////////////////
// start calculations, whether to start and for how long
///////////////////
// check for the manual lock
if (IrrigationLock.state == OFF) {
logInfo(logName, "Irrigation lock is on")
return
}
// check if other program is active
if (ActiveProgram.state != 0) {
logInfo(logName, "Program {} already running", ActiveProgram.state)
return
}
// check if schedule is set to every other day and if program ran yesterday
if ((Program1HoursSinceLastRun.state as Number) < (Program1MinHoursBetween.state as Number) && Program1SpecificDays.state == OFF) {
logInfo(logName, "Program 1 ran less than {}hrs ago, skip.", Program1MinHoursBetween.state)
// Program1EOD.postUpdate(OFF)
return
}
// set the default irrigation hour to X hours before the sunrise
val localSunRise = new DateTimeType(Sunrise_Time.state.toString).getZonedDateTime.minusHours((Program1IrrigationHoursBeforeSunrise.state as Number).intValue)
var Number wateringHour = localSunRise.getHour.intValue
var Number wateringMinute = localSunRise.getMinute.intValue
// if there is a specific hour in settings, then use it
if (Program1IrrigationStartAtSpecificHour.state == ON) {
wateringHour = Program1IrrigationStartTime.state as Number
wateringMinute = 0
}
logDebug(logName, "Watering at: {}:{}", wateringHour, wateringMinute)
// check if the current time is the watering time (full hour)
if (now.getHour.intValue != wateringHour || now.getMinute.intValue != wateringMinute) {
// nope - good bye
logInfo(logName, "Inappropriate time to start irrigation. Program 1 watering at: {}:{}", wateringHour, wateringMinute)
return
}
logInfo(logName, "It is watering hour: {}:{}", wateringHour, wateringMinute)
// check the week day
if (Program1SpecificDays.state == ON) {
val Number day = now.getDayOfWeek.getValue
val dayItem = ScriptServiceUtil.getItemRegistry.getItem("Program1IrrigationDay" + day)
if (dayItem === null || dayItem.state == OFF || dayItem.state == NULL) {
logInfo(logName, "Inappropriate day to start irrigation", dayItem)
return
}
}
// check if the current wind speed is higher then the max allowed
logDebug(logName, "Current wind speed: {} km/h", String::format("%.2f", (localCurrentWindSpeed.state as Number).doubleValue))
if (localCurrentWindSpeed.state > MaxAllowedWindSpeed.state as Number) {
logInfo(logName, "Wind speed too high to irrigate")
return
}
// if the rainfall sum for the last 24h and the forecast for 24h is higher then set, then we are not going to irrigate
if (RainTotal > (MaxAllowedRain.state as Number).doubleValue) {
logInfo(logName, "To heavy rain to irrigate (past and forcasted)")
return
}
// check the weather, and based on that set the watering time coefficient factor
// Rainbird R-VAN ~ 15mm/h (square precip)
// Rainbird 3500 ~ 11mm/h (square precip)
// Target lawn 10-15mm irrigation each time
if (Program1WeatherAdjust.state == ON){
if ((CoefficientPercentage.state as Number) <= 0) {
logInfo(logName, "Weather conditions don't require irrigation")
return
}
else {
coefficientFactor = (CoefficientPercentage.state as Number) / 100
}
}
else {
coefficientFactor = 1
}
logInfo(logName, "Setting irrigation coefficient factor to {}", coefficientFactor)
///////////////////
// ok, let's start watering, cascading all of the valves from the GroupIrrigationValves
///////////////////
// Only if no other program is running (double check), start with the Zone 1, other zones will be turned on in sequence by the separate rule
if (ActiveProgram.state == 0) {
// if EveryOtherDay flag is off, turn it on. Warn and skip if flag is on and EOD is set. Shouldn't get to this point but skip irrigation.
//if (Program1EOD.state == OFF) {
// Program1EOD.postUpdate(ON)
//}
//else if (Program1SpecificDays == OFF) {
// logWarn(logName, "About to start irrigation program 1, but only every other day required on and irrigation ran yesterday so skip")
// return
//}
logInfo(logName, "Starting the irrigation sequence from program 1")
ActiveProgram.postUpdate(1)
Program1LastRun.postUpdate(new DateTimeType())
IrrigationCurrentValve.sendCommand(IrrigationValveZone1.name)
}
else {
logWarn(logName, "About to start irrigation program 1, but program {} already running so skip", ActiveProgram.state) // shouldn't get to this point, but if so log warning.
}
}
catch (Exception e) {
logError(logName, "Error calculating whether to start irrigation: " + e)
}
end
rule "Irrigation - calculate whether to start watering program 2"
when
Time cron "2 * * ? * *" // every minute, 1s after program 1
then
try {
logDebug(logName, "Calculating whether to start irrigation program 2")
///////////////////
// start calculations, whether to start and for how long
///////////////////
// check for the manual lock
if (IrrigationLock.state == OFF) {
logInfo(logName, "Irrigation lock is on")
return
}
// check if other program is active
if (ActiveProgram.state != 0) {
logInfo(logName, "Program {} already running", ActiveProgram.state)
return
}
// check if schedule is set to every other day and if program ran yesterday
if ((Program2HoursSinceLastRun.state as Number) < (Program2MinHoursBetween.state as Number) && Program2SpecificDays.state == OFF) {
logInfo(logName, "Program 2 ran less than {}hrs ago, skip.", Program2MinHoursBetween.state)
return
}
// check if program 2 is set
if (Program2IrrigationStartAtSpecificHour.state == OFF) {
logInfo(logName, "Program 2 not active")
return
}
var Number wateringHour = Program2IrrigationStartTime.state as Number
var Number wateringMinute = 0
// check if the current time is the watering time (full hour)
if (now.getHour.intValue != wateringHour || now.getMinute.intValue != wateringMinute) {
// nope - good bye
logInfo(logName, "Inappropriate time to start irrigation. Program 2 watering at: {}:{}", wateringHour, wateringMinute)
return
}
logInfo(logName, "It is watering hour: {}:{}", wateringHour, wateringMinute)
// check the week day
if (Program2SpecificDays.state == ON) {
val Number day = now.getDayOfWeek.getValue
val dayItem = ScriptServiceUtil.getItemRegistry.getItem("Program2IrrigationDay" + day)
if (dayItem === null || dayItem.state == OFF || dayItem.state == NULL) {
logInfo(logName, "Inappropriate day to start irrigation", dayItem)
return
}
}
// check if the current wind speed is higher then the max allowed
logDebug(logName, "Current wind speed: {} km/h", String::format("%.2f", (localCurrentWindSpeed.state as Number).doubleValue))
if (localCurrentWindSpeed.state > MaxAllowedWindSpeed.state as Number) {
logInfo(logName, "Wind speed too high to irrigate")
return
}
// if the rainfall sum for the last 24h and the forecast for 24h is higher then set, then we are not going to irrigate
if (RainTotal > (MaxAllowedRain.state as Number).doubleValue) {
logInfo(logName, "To heavy rain to irrigate (past and forcasted)")
return
}
// check the weather, and based on that set the watering time coefficient factor
// Rainbird R-VAN ~ 15mm/h (square precip)
// Rainbird 3500 ~ 11mm/h (square precip)
// Target lawn 10-15mm irrigation each time
if (Program2WeatherAdjust.state == ON){
if ((CoefficientPercentage.state as Number) <= 0) {
logInfo(logName, "Weather conditions don't require irrigation")
return
}
else {
coefficientFactor = (CoefficientPercentage.state as Number) / 100
}
}
else {
coefficientFactor = 1
}
logInfo(logName, "Setting irrigation coefficient factor to {}", coefficientFactor)
///////////////////
// ok, let's start watering, cascading all of the valves from the GroupIrrigationValves
///////////////////
// Only if no other program is running (double check), start with the Zone 1, other zones will be turned on in sequence by the separate rule
if (ActiveProgram.state == 0) {
logInfo(logName, "Starting the irrigation sequence from program 2")
ActiveProgram.postUpdate(2)
Program2LastRun.postUpdate(new DateTimeType())
IrrigationCurrentValve.sendCommand(IrrigationValveZone1.name)
}
else {
logWarn(logName, "About to start irrigation program 2, but program {} already running so skip", ActiveProgram.state) // shouldn't get to this point, but if so log warning.
}
}
catch (Exception e) {
logError(logName, "Error calculating whether to start irrigation: " + e)
}
end
rule "Irrigation - calculate whether to start watering program 3"
when
Time cron "3 * * ? * *" // every minute, 2s after program 1, 1s after program 2
then
try {
logDebug(logName, "Calculating whether to start irrigation program 3")
///////////////////
// start calculations, whether to start and for how long
///////////////////
// check for the manual lock
if (IrrigationLock.state == OFF) {
logInfo(logName, "Irrigation lock is on")
return
}
// check if other program is active
if (ActiveProgram.state != 0) {
logInfo(logName, "Program {} already running", ActiveProgram.state)
return
}
// check if schedule is set to every other day and if program ran yesterday
if ((Program3HoursSinceLastRun.state as Number) < (Program3MinHoursBetween.state as Number) && Program3SpecificDays.state == OFF) {
logInfo(logName, "Program 3 ran less than {}hrs ago, skip.", Program3MinHoursBetween.state)
return
}
// check if program 3 is set
if (Program3IrrigationStartAtSpecificHour.state == OFF) {
logInfo(logName, "Program 3 not active")
return
}
var Number wateringHour = Program3IrrigationStartTime.state as Number
var Number wateringMinute = 0
// check if the current time is the watering time (full hour)
if (now.getHour.intValue != wateringHour || now.getMinute.intValue != wateringMinute) {
// nope - good bye
logInfo(logName, "Inappropriate time to start irrigation. Program 3 watering at: {}:{}", wateringHour, wateringMinute)
return
}
logInfo(logName, "It is watering hour: {}:{}", wateringHour, wateringMinute)
// check the week day
if (Program3SpecificDays.state == ON) {
val Number day = now.getDayOfWeek.getValue
val dayItem = ScriptServiceUtil.getItemRegistry.getItem("Program3IrrigationDay" + day)
if (dayItem === null || dayItem.state == OFF || dayItem.state == NULL) {
logInfo(logName, "Inappropriate day to start irrigation", dayItem)
return
}
}
// check if the current wind speed is higher then the max allowed
logDebug(logName, "Current wind speed: {} km/h", String::format("%.2f", (localCurrentWindSpeed.state as Number).doubleValue))
if (localCurrentWindSpeed.state > MaxAllowedWindSpeed.state as Number) {
logInfo(logName, "Wind speed too high to irrigate")
return
}
// if the rainfall sum for the last 24h and the forecast for 24h is higher then set, then we are not going to irrigate
if (RainTotal > (MaxAllowedRain.state as Number).doubleValue) {
logInfo(logName, "To heavy rain to irrigate (past and forcasted)")
return
}
// check the weather, and based on that set the watering time coefficient factor
// Rainbird R-VAN ~ 15mm/h (square precip)
// Rainbird 3500 ~ 11mm/h (square precip)
// Target lawn 10-15mm irrigation each time
if (Program3WeatherAdjust.state == ON){
if ((CoefficientPercentage.state as Number) <= 0) {
logInfo(logName, "Weather conditions don't require irrigation")
return
}
else {
coefficientFactor = (CoefficientPercentage.state as Number) / 100
}
}
else {
coefficientFactor = 1
}
logInfo(logName, "Setting irrigation coefficient factor to {}", coefficientFactor)
///////////////////
// ok, let's start watering, cascading all of the valves from the GroupIrrigationValves
///////////////////
// Only if no other program is running (double check), start with the Zone 1, other zones will be turned on in sequence by the separate rule
if (ActiveProgram.state == 0) {
logInfo(logName, "Starting the irrigation sequence from program 3")
ActiveProgram.postUpdate(3)
Program3LastRun.postUpdate(new DateTimeType())
IrrigationCurrentValve.sendCommand(IrrigationValveZone1.name)
}
else {
logWarn(logName, "About to start irrigation program 3, but program {} already running so skip", ActiveProgram.state) // shouldn't get to this point, but if so log warning.
}
}
catch (Exception e) {
logError(logName, "Error calculating whether to start irrigation: " + e)
}
end
rule "Irrigation - cascading"
when
Item IrrigationCurrentValve received command
then
try {
// get the currently open valve
var currValve = GroupIrrigationValves.members.findFirst[valve | valve.name == receivedCommand.toString]
var currValveNum = Integer::parseInt(currValve.name.split("Zone").get(1))
var currValveSecs = (GroupIrrigationTimes.members.findFirst[t | t.name == currValve.name+"Time" ].state as Number)
var ProgZoneName = "Program" + ActiveProgram.state + "Zone" + currValveNum // name for item of current zone within current program for evaluation
var ProgZoneItem = Group_Program_Zones.members.findFirst[zone | zone.name == ProgZoneName]
//logInfo(logName, "Before while loop: Current valve {}, duration {}", currValve.name, currValveSecs) // changed to logInfo for debug
// while loop to check if set time > 0. In case of 0, skip zone and select next one.
var boolean exitFlag = false
while (!exitFlag && (currValveSecs < 1 || ProgZoneItem.state == OFF)){
currValveNum = currValveNum + 1
var currValveName = "IrrigationValveZone" + currValveNum
currValve = GroupIrrigationValves.members.findFirst[valve | valve.name == currValveName]
ProgZoneName = "Program" + ActiveProgram.state + "Zone" + currValveNum // name for item of current zone within current program for evaluation
ProgZoneItem = Group_Program_Zones.members.findFirst[zone | zone.name == ProgZoneName]
if (currValve === null || ProgZoneItem === null){
exitFlag = true
logInfo(logName, "In while loop: No more valves")
}
else {
currValveSecs = (GroupIrrigationTimes.members.findFirst[t | t.name == currValve.name+"Time" ].state as Number)
logInfo(logName, "In while loop: currValve {}, currValveSecs {}", currValve.name, currValveSecs) // added for debug
}
}
logInfo(logName, "After while loop: Current valve {}, duration {}", currValve, currValveSecs) // changed to logInfo for debug
// get the next valve in the sequence
val nextValveNum = currValveNum + 1
val nextValveName = "IrrigationValveZone" + nextValveNum
val nextValve = GroupIrrigationValves.members.findFirst[valve | valve.name == nextValveName]
// if there is no next valve in the sequence, then nextValve is null
if (nextValve === null) {
logDebug(logName, "This is the last valve in the sequence")
}
else {
logDebug(logName, "Next valve {}", nextValve.name)
}
if (currValve !== null){
// open the current valve
val valveOpenTime = (currValveSecs * coefficientFactor).intValue
logInfo(logName, "Opening {} for {} seconds", currValve.name, valveOpenTime)
currValve.sendCommand(ON)
IrrigationSectionRemainingTime.postUpdate(valveOpenTime)
// let's wait for propagating item values
Thread::sleep(100)
// update HomeKit remaining time
val RemainingTimeCurrentZoneName = "RemainingTimeZone" + currValveNum
val RemainingTimeCurrentZone = GroupRemainingTime.members.findFirst[valve | valve.name == RemainingTimeCurrentZoneName]
RemainingTimeCurrentZone.postUpdate(IrrigationSectionRemainingTime.state)
// set the timer, after expiring turn off the current valve and turn on the next one
irrigationTimer = createTimer(now.plusSeconds(valveOpenTime), [ |
if (nextValve !== null) {
// this will invoke cascading valves, "Irrigation - cascading" rule
IrrigationCurrentValve.sendCommand(nextValve.name)
}
else {
logInfo(logName, "Irrigation is complete")
}
// let's wait for propagating item values
Thread::sleep(500)
// turn off current valve
logInfo(logName, "Closing " + currValve.name)
currValve.sendCommand(OFF)
irrigationTimer = null
])
}
else {
logInfo(logName, "Irrigation is complete")
}
}
catch (Exception e) {
logError(logName, "Error controlling cascading valves: " + e)
}
end
// for displaying remaining irrigation time purpose only
rule "Irrigation - update timer"
when
Time cron "0 * * ? * *" // every minute
then
if (IrrigationSectionRemainingTime.state as Number > 60) {
IrrigationSectionRemainingTime.postUpdate((IrrigationSectionRemainingTime.state as Number) - 60)
}
end
rule "Irrigation - update timer for HomeKit items"
when
Time cron "/10 * * ? * *" // every 10s
then
GroupRemainingTime.members.filter[valve | valve.state > 9].forEach[valve |
valve.postUpdate((valve.state as Number) - 10)
]
end
rule "Irrigation - all valves closed"
when
Item GroupIrrigationValves changed to OFF
then
// set the current valve to OFF
logInfo(logName, "All irrigation valves closed")
IrrigationCurrentValve.postUpdate(OFF)
// reset the remaining time
IrrigationSectionRemainingTime.postUpdate(0)
GroupRemainingTime.members.filter[valve | valve.state != 0].forEach[valve | valve.postUpdate(0)]
// reset active program
ActiveProgram.postUpdate(0)
// log cycle end
LastEnd.sendCommand(new DateTimeType())
end
rule "Irrigation - valve updated, turn on the timer"
when
Item GroupIrrigationValves changed
then
// protection against overwatering
// log the state of all valves
GroupIrrigationValves.members.forEach [valve |
logDebug(logName, "Irrigation valve: " + valve.name + " " + valve.state)
]
// a valve was turned on
if (GroupIrrigationValves.state == ON) {
if (IrrigationTimerMax.state == OFF) {
// timer is not set yet, start the timer and log cycle start
logDebug(logName, "Irrigation valve open, starting protection timer")
IrrigationTimerMax.sendCommand(ON)
LastStart.sendCommand(new DateTimeType())
}
else {
// the timer is already running
logDebug(logName, "Irrigation valve open, timer already started, nothing to do")
}
}
else {
logDebug(logName, "All irrigation valves closed, stopping protection timer")
IrrigationTimerMax.postUpdate(OFF)
}
end
rule "Irrigation - protection timer off, close all valves"
when
Item IrrigationTimerMax changed to OFF
then
// protection timer expired - turn all valves off
logWarn(logName, "Irrigation protection timer expired - close all valves")
// close all valves from the group
GroupIrrigationValves.members.forEach [valve |
logDebug(logName, "Closing valve: " + valve.name)
valve.sendCommand(OFF)
]
end
sitemap irrigation label="Beregening"
{
Frame label="Status" {
Switch item=IrrigationLock icon="lock" mappings=[ON="Automatisch", OFF="Uit"]
Text item=GroupIrrigationValves label="Beregening" icon="water"
// Last cycle start
Text item=LastStart icon="time"
// Last cycle end
Text item=LastEnd icon="time"
Text item=IrrigationSectionRemainingTime visibility=[IrrigationSectionRemainingTime > 0] label="Resterende tijd huidige zone [%d min]" icon="time"
Text item=ActiveProgram visibility=[ActiveProgram > 0] label="Actieve programma [%d]" icon="text"
}
Frame label="Zones" {
Switch item=IrrigationValveZone1 label="Zone 1: Druppel border achtertuin" /*visibility=[IrrigationLock.state==OFF]*/ icon="faucet"
Switch item=IrrigationValveZone2 label="Zone 2: Sproeier 1 achtertuin" icon="faucet"
Switch item=IrrigationValveZone3 label="Zone 3: Druppel bomen achtertuin" icon="faucet"
Switch item=IrrigationValveZone4 label="Zone 4: Sproeier 2 achtertuin" icon="faucet"
Switch item=IrrigationValveZone5 label="Zone 5: Sproeier 1 voortuin" icon="faucet"
Switch item=IrrigationValveZone6 label="Zone 6: Druppel bomen voortuin" icon="faucet"
Switch item=IrrigationValveZone7 label="Zone 7: Sproeier 2 voortuin" icon="faucet"
}
Frame label="Groepen" {
Switch item=IrrigationValveZone8 icon="faucet"
Switch item=IrrigationValveZone9 icon="faucet"
Switch item=IrrigationValveZone10 icon="faucet"
}
Frame label="Metingen" {
// rainfall past 24h
Text item=SumRainLast24h icon="rain"
// rainfall forecast 24h
Text item=SumRainNext24h icon="rain"
// Coefficient factor
Text item=CoefficientPercentage icon="chart"
// Average temperature past 24h
Text item=AverageTemperature24h icon="temperature"
// Average humidity past 24h
Text item=AverageHumidity24h icon="humidity"
// Current wind speed
Text item=localCurrentWindSpeed label="Huidige windsnelheid" icon="wind"
}
Frame label="Instellingen" {
Text label="Algemeen" icon="settings" {
Frame label="Beregeningsduur" {
Setpoint item=IrrigationValveZone1Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone2Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone3Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone4Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone5Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone6Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone7Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone8Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone9Time minValue=0 maxValue=3600 step=60 icon="time"
Setpoint item=IrrigationValveZone10Time minValue=0 maxValue=3600 step=60 icon="time"
}
Frame label="Weersomstandigheden" {
Setpoint item=MaxAllowedRain label="Max neerslag" minValue=0 maxValue=20 step=1 icon="rain"
Setpoint item=MaxAllowedWindSpeed label="Max windsnelheid" minValue=5 maxValue=150 step=5 icon="wind"
}
Frame label="Weersafhankelijke parameters" {
Setpoint item=TempBaseLine label="Temperatuur uitgangspunt (default 20°C) [%d °C]" minValue=15 maxValue=25 step=1 icon="temperature"
Setpoint item=TempAdjustment label="Temperatuur aanpassingsfactor (default 5) [%d]" minValue=2 maxValue=10 step=1 icon="heating-on"
Setpoint item=HumidityBaseLine label="Luchtvochtigheid uitgangspunt (default 60%) [%.0f %%]" minValue=40 maxValue=80 step=1 icon="humidity"
Setpoint item=RainAdjustment label="Regen aanpassingsfactor (default 8) [%d]" minValue=1 maxValue=20 step=1 icon="water"
}
}
// split settings and program times - Program 1
Text label="Programma 1" icon="time" {
Frame label="Starttijd" {
Selection item=Program1IrrigationStartAtSpecificHour icon="sunrise" label="Start beregening" mappings=["OFF"="Voor zonsopkomst", "ON"="Op vast tijdstip"]
Setpoint item=Program1IrrigationHoursBeforeSunrise icon="time" minValue=0 maxValue=23 visibility=[Program1IrrigationStartAtSpecificHour==OFF]
Selection item=Program1IrrigationStartTime visibility=[Program1IrrigationStartAtSpecificHour==ON] mappings=[
"0"="00:00", "1"="01:00", "2"="02:00",
"3"="03:00", "4"="04:00", "5"="05:00",
"6"="06:00", "7"="07:00", "8"="08:00",
"9"="09:00", "10"="10:00", "11"="11:00",
"12"="12:00", "13"="13:00", "14"="14:00",
"15"="15:00", "16"="16:00", "17"="17:00",
"18"="18:00", "19"="19:00", "20"="20:00",
"21"="21:00", "22"="22:00", "23"="23:00"
]
//Switch item=Program1EOD label="Laatste 24u actief []" mappings=["ON"="Ja", "OFF"="Nee"]
Text item=Program1HoursSinceLastRun icon="time"
Text item=Program1LastRun icon="time"
}
Frame {
Selection item=Program1SpecificDays icon="water" label="Beregeningsdagen" mappings=["OFF"="Om de dag", "ON"="Op vaste dagen"]
Switch item=Program1WeatherAdjust icon="line" mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1IrrigationDay1 visibility=[Program1SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1IrrigationDay2 visibility=[Program1SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1IrrigationDay3 visibility=[Program1SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1IrrigationDay4 visibility=[Program1SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1IrrigationDay5 visibility=[Program1SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1IrrigationDay6 visibility=[Program1SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1IrrigationDay7 visibility=[Program1SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Setpoint item=Program1MinHoursBetween icon="time" visibility=[Program1SpecificDays==OFF]
}
Frame label="Actieve zones" {
Switch item=Program1Zone1 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone2 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone3 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone4 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone5 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone6 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone7 mappings=[ON="Wel", OFF="Niet"]
}
Frame label="Actieve groepen" {
Switch item=Program1Zone8 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone9 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program1Zone10 mappings=[ON="Wel", OFF="Niet"]
}
}
//
// split settings and program times - Program 2
Text label="Programma 2" icon="time" {
Frame label="Starttijd" {
Selection item=Program2IrrigationStartAtSpecificHour icon="sunrise" label="Start beregening" mappings=["OFF"="Uit", "ON"="Op vast tijdstip"]
Text label="" icon="" visibility=[Program2IrrigationStartAtSpecificHour==OFF]
Selection item=Program2IrrigationStartTime visibility=[Program2IrrigationStartAtSpecificHour==ON] mappings=[
"0"="00:00", "1"="01:00", "2"="02:00",
"3"="03:00", "4"="04:00", "5"="05:00",
"6"="06:00", "7"="07:00", "8"="08:00",
"9"="09:00", "10"="10:00", "11"="11:00",
"12"="12:00", "13"="13:00", "14"="14:00",
"15"="15:00", "16"="16:00", "17"="17:00",
"18"="18:00", "19"="19:00", "20"="20:00",
"21"="21:00", "22"="22:00", "23"="23:00"
]
Text item=Program2HoursSinceLastRun icon="time"
Text item=Program2LastRun icon="time"
}
Frame visibility=[Program2IrrigationStartAtSpecificHour==ON] {
Selection item=Program2SpecificDays icon="water" label="Beregeningsdagen" mappings=["OFF"="Om de dag", "ON"="Op vaste dagen"]
Switch item=Program2WeatherAdjust icon="line" mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2IrrigationDay1 visibility=[Program2SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2IrrigationDay2 visibility=[Program2SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2IrrigationDay3 visibility=[Program2SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2IrrigationDay4 visibility=[Program2SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2IrrigationDay5 visibility=[Program2SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2IrrigationDay6 visibility=[Program2SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2IrrigationDay7 visibility=[Program2SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Setpoint item=Program2MinHoursBetween icon="time" visibility=[Program2SpecificDays==OFF]
}
Frame label="Actieve zones" visibility=[Program2IrrigationStartAtSpecificHour==ON] {
Switch item=Program2Zone1 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone2 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone3 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone4 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone5 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone6 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone7 mappings=[ON="Wel", OFF="Niet"]
}
Frame label="Actieve groepen" visibility=[Program2IrrigationStartAtSpecificHour==ON] {
Switch item=Program2Zone8 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone9 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program2Zone10 mappings=[ON="Wel", OFF="Niet"]
}
}
//
// split settings and program times - Program 3
Text label="Programma 3" icon="time" {
Frame label="Starttijd" {
Selection item=Program3IrrigationStartAtSpecificHour icon="sunrise" label="Start beregening" mappings=["OFF"="Uit", "ON"="Op vast tijdstip"]
Text label="" icon="" visibility=[Program3IrrigationStartAtSpecificHour==OFF]
Selection item=Program3IrrigationStartTime visibility=[Program3IrrigationStartAtSpecificHour==ON] mappings=[
"0"="00:00", "1"="01:00", "2"="02:00",
"3"="03:00", "4"="04:00", "5"="05:00",
"6"="06:00", "7"="07:00", "8"="08:00",
"9"="09:00", "10"="10:00", "11"="11:00",
"12"="12:00", "13"="13:00", "14"="14:00",
"15"="15:00", "16"="16:00", "17"="17:00",
"18"="18:00", "19"="19:00", "20"="20:00",
"21"="21:00", "22"="22:00", "23"="23:00"
]
Text item=Program3HoursSinceLastRun icon="time"
Text item=Program3LastRun icon="time"
}
Frame visibility=[Program3IrrigationStartAtSpecificHour==ON] {
Selection item=Program3SpecificDays icon="water" label="Beregeningsdagen" mappings=["OFF"="Om de dag", "ON"="Op vaste dagen"]
Switch item=Program3WeatherAdjust icon="line" mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3IrrigationDay1 visibility=[Program3SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3IrrigationDay2 visibility=[Program3SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3IrrigationDay3 visibility=[Program3SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3IrrigationDay4 visibility=[Program3SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3IrrigationDay5 visibility=[Program3SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3IrrigationDay6 visibility=[Program3SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3IrrigationDay7 visibility=[Program3SpecificDays==ON] mappings=[ON="Wel", OFF="Niet"]
Setpoint item=Program3MinHoursBetween icon="time" visibility=[Program3SpecificDays==OFF]
}
Frame label="Actieve zones" visibility=[Program3IrrigationStartAtSpecificHour==ON] {
Switch item=Program3Zone1 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone2 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone3 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone4 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone5 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone6 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone7 mappings=[ON="Wel", OFF="Niet"]
}
Frame label="Actieve groepen" visibility=[Program3IrrigationStartAtSpecificHour==ON] {
Switch item=Program3Zone8 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone9 mappings=[ON="Wel", OFF="Niet"]
Switch item=Program3Zone10 mappings=[ON="Wel", OFF="Niet"]
}
}
}
}