====== Полив ======
[[https://www.ab-log.ru/forum/viewtopic.php?p=47013#p47013|Источник vassap » 15 окт 2021, 21:50]]
В телеграме спрашивали код виджета полива, вот.
===== Виджеты =====
uid: Watering_v1
tags: []
props:
parameters:
- description: A text prop
label: Prop 1
name: prop1
required: false
type: TEXT
- context: item
description: An item to control
label: Item
name: item
required: false
type: TEXT
parameterGroups: []
timestamp: Aug 23, 2021, 9:24:51 PM
component: f7-card
config:
style:
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
height: auto
margin: 5px
line-height: 1
font-family: sans-serif
slots:
default:
- component: f7-card-header
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: Label
config:
text: Полив
style:
font-size: 250%
- component: f7-card-content
config:
style:
margin: 5px
padding: 0px
slots:
default:
- component: f7-row
slots:
default:
- component: f7-segmented
config:
strong: true
color: green
class:
- segmented-strong
style:
--f7-segmented-strong-padding: 5px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 300
--f7-segmented-strong-bg-color: transparent
--f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.15)
width: 100%
outline: true
slots:
default:
- component: oh-button
config:
text: Утром
action: variable
actionVariable: select
actionVariableValue: 1
active: =(vars.select == 1)
outline: =(vars.select == 1)
style:
font-weight: 400
font-size: 150%
- component: oh-button
config:
text: Вечером
action: variable
actionVariable: select
actionVariableValue: 2
active: =(vars.select == 2)
outline: =(vars.select == 2)
style:
font-weight: 400
font-size: 150%
- component: oh-button
config:
text: Днём
action: variable
actionVariable: select
actionVariableValue: 3
active: =(vars.select == 3)
outline: =(vars.select == 3)
style:
font-weight: 400
font-size: 150%
- component: f7-tab
config:
visible: =(vars.select == 1 || vars.select == NULL)
style:
animation: f7-fade-in 300ms
padding: 0px
margin: 5px
margin-right: 5px
class:
- display-flex
- justify-content-space-between
- flex-direction-column
slots:
default:
- component: f7-row
config:
style:
margin: 5px
font-size: 120%
slots:
default:
- component: Label
config:
text: Утренний полив
- component: oh-toggle
config:
item: IrrigationStartAtSunrise
color: green
- component: f7-row
config:
style:
margin: 5px
font-size: 120%
slots:
default:
- component: f7-row
config: {}
slots:
default:
- component: Label
config:
text: "Рассвет:"
style:
margin-right: 10px
- component: Label
config:
text: =items.Voshod.displayState
- component: f7-row
config: {}
slots:
default:
- component: Label
config:
text: Время после рассвета
style:
margin-right: 10px
- component: oh-link
config:
color: green
text: =items.IrrigationHoursAfterSunrise.state
action: popup
popoverOpen: .timerpopover
slots:
default:
- component: f7-popover
config:
class:
- timerpopover
slots:
default:
- component: oh-stepper-card
config:
color: green
item: IrrigationHoursAfterSunrise
title: Минут после рассвета
min: 0
max: 180
step: 10
- component: f7-row
config:
style:
margin: 5px
margin-bottom: 15px
font-size: 120%
slots:
default:
- component: f7-row
config: {}
slots:
default:
- component: Label
config:
text: "Время начала полива:"
style:
margin-right: 10px
- component: Label
config:
text: =items.IrrigationStartTime.displayState
- component: f7-row
config:
style:
padding: 5px
margin: 0px
font-size: 120%
border: 1px solid green
border-radius: var(--f7-card-expandable-border-radius)
display: inline
slots:
default:
- component: oh-repeater
config:
accordionList: true
fragment: false
for: item
sourceType: itemsInGroup
groupItem: GroupIrrigationValves
slots:
default:
- component: f7-row
config:
style:
margin-top: 5px
display: flex
justify-content: flex-start
align-items: center
slots:
default:
- component: oh-link
config:
iconMaterial: opacity
color: '=items[loop.item.name].state == "ON" ? "blue" : "gray"'
iconSize: 25px
action: popover
popoverOpen: ='.m'+loop.item.name
slots:
default:
- component: f7-popover
config:
class: ='m'+loop.item.name
slots:
default:
- component: f7-block
config:
style:
animate: true
align-self: center
justify-self: center
justify-content: center
text-align: center
slots:
default:
- component: Label
config:
text: Запуск вручную
- component: oh-button
config:
text: =items[loop.item.name].state
color: green
action: toggle
actionCommand: ON
actionCommandAlt: OFF
actionItem: =loop.item.name
- component: oh-button
config:
text: =loop.item.label
action: analyzer
actionAnalyzerItems: =[loop.item.name]
style:
--f7-button-hover-bg-color: green
color: var(--f7-button-text-color)
font-size: 20px
margin-left: 10px
- component: oh-stepper
config:
item: =(loop.item.name + 'Time1')
title: Время полива
min: 0
max: 180
step: 1
round: true
color: green
autorepeat: true
autorepeat-dynamic: true
style:
margin-left: auto
- component: oh-button
config:
iconF7: gear_alt_fill
color: '=vars[loop.item.name + "S"] === true ? "green" : "gray"'
action: variable
actionVariable: =(loop.item.name + 'S')
actionVariableValue: =!(vars[loop.item.name + 'S'] === true)
- component: f7-segmented
config:
strong: true
small: true
outline: true
color: green
class:
- segmented-round
style:
--f7-segmented-strong-padding: 0px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 300
--f7-segmented-strong-bg-color: transparent
--f7-segmented-strong-button-hover-bg-color: rgba(0, 255, 0, 0.1)
--f7-segmented-strong-button-active-bg-color: transparent
margin-top: 5px
slots:
default:
- component: oh-repeater
config:
fragment: true
for: day
sourceType: array
in:
- name: 1
label: Пн
- name: 2
label: Вт
- name: 3
label: Ср
- name: 4
label: Чт
- name: 5
label: Пт
- name: 6
label: Сб
- name: 7
label: Вс
slots:
default:
- component: oh-button
config:
text: =loop.day.label
action: toggle
actionCommand: ON
actionCommandAlt: OFF
actionItem: =(loop.item.name + 'M' + loop.day.name)
fill: "=(items[loop.item.name + 'M' + loop.day.name].state === 'ON' ? true : false)"
style:
font-weight: 400
- component: f7-row
config:
visible: =vars[loop.item.name + 'S'] === true
style:
margin: 10px
display: flex
justify-content: space-around
align-items: center
slots:
default:
- component: f7-row
config:
style:
align-items: center
slots:
default:
- component: Label
config:
text: Коррекция
style:
font-size: 12px
- component: f7-row
config:
style:
align-items: center
justify-content: space-between
slots:
default:
- component: Label
config:
text: по температуре
style:
font-size: 12px
margin-right: 10px
- component: oh-toggle
config:
color: green
item: =(loop.item.name + 'TimeCorrection')
- component: Label
config:
text: по осадкам
style:
font-size: 12px
margin: 0px 10px
- component: oh-toggle
config:
color: green
item: =(loop.item.name + 'RainCorrection')
- component: f7-tab
config:
visible: =(vars.select == 2)
style:
animation: f7-fade-in 300ms
padding: 0px
margin: 5px
margin-right: 5px
class:
- display-flex
- justify-content-space-between
- flex-direction-column
slots:
default:
- component: f7-row
config:
style:
margin: 5px
font-size: 120%
slots:
default:
- component: Label
config:
text: Вечерний полив
- component: oh-toggle
config:
item: IrrigationStartAtSundown
color: green
- component: f7-row
config:
style:
margin: 5px
font-size: 120%
slots:
default:
- component: f7-row
config: {}
slots:
default:
- component: Label
config:
text: "Закат:"
style:
margin-right: 10px
- component: Label
config:
text: =items.Zakat.displayState
- component: f7-row
config: {}
slots:
default:
- component: Label
config:
text: Время до заката
style:
margin-right: 10px
- component: oh-link
config:
color: green
text: =items.IrrigationHoursBeforeSundown.state
action: popover
popoverOpen: .timerpopover
slots:
default:
- component: f7-popover
config:
class:
- timerpopover
slots:
default:
- component: oh-stepper-card
config:
color: green
item: IrrigationHoursBeforeSundown
title: Минут после рассвета
min: 0
max: 180
step: 10
- component: f7-row
config:
style:
margin: 5px
margin-bottom: 15px
font-size: 120%
slots:
default:
- component: f7-row
config: {}
slots:
default:
- component: Label
config:
text: "Время начала полива:"
style:
margin-right: 10px
- component: Label
config:
text: =items.IrrigationStartTime3.displayState
- component: f7-row
config:
style:
padding: 5px
margin: 0px
font-size: 120%
border: 1px solid green
border-radius: var(--f7-card-expandable-border-radius)
display: inline
slots:
default:
- component: oh-repeater
config:
fragment: false
for: item
sourceType: itemsInGroup
groupItem: GroupIrrigationValves
slots:
default:
- component: f7-row
config:
style:
margin-top: 5px
display: flex
justify-content: flex-start
align-items: center
slots:
default:
- component: oh-link
config:
iconMaterial: opacity
color: '=items[loop.item.name].state == "ON" ? "blue" : "gray"'
iconSize: 25px
action: popover
popoverOpen: ='.m'+loop.item.name
slots:
default:
- component: f7-popover
config:
class: ='m'+loop.item.name
slots:
default:
- component: f7-block
config:
style:
animate: true
align-self: center
justify-self: center
justify-content: center
text-align: center
slots:
default:
- component: Label
config:
text: Запуск вручную
- component: oh-button
config:
text: =items[loop.item.name].state
color: green
action: toggle
actionCommand: ON
actionCommandAlt: OFF
actionItem: =loop.item.name
- component: oh-button
config:
text: =loop.item.label
action: analyzer
actionAnalyzerItems: =[loop.item.name]
style:
--f7-button-hover-bg-color: green
color: white
font-size: 20px
margin-left: 10px
- component: oh-stepper
config:
item: =(loop.item.name + 'Time2')
title: Время полива
min: 0
max: 180
step: 1
round: true
color: green
autorepeat: true
autorepeat-dynamic: true
style:
margin-left: auto
- component: oh-button
config:
iconF7: gear_alt_fill
color: '=vars[loop.item.name + "S"] === true ? "green" : "gray"'
action: variable
actionVariable: =(loop.item.name + 'S')
actionVariableValue: =!(vars[loop.item.name + 'S'] === true)
- component: f7-segmented
config:
strong: true
small: true
outline: true
color: green
class:
- segmented-round
style:
--f7-segmented-strong-padding: 0px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 300
--f7-segmented-strong-bg-color: transparent
--f7-segmented-strong-button-hover-bg-color: rgba(0, 255, 0, 0.1)
--f7-segmented-strong-button-active-bg-color: transparent
margin-top: 5px
slots:
default:
- component: oh-repeater
config:
fragment: true
for: day
sourceType: array
in:
- name: 1
label: Пн
- name: 2
label: Вт
- name: 3
label: Ср
- name: 4
label: Чт
- name: 5
label: Пт
- name: 6
label: Сб
- name: 7
label: Вс
slots:
default:
- component: oh-button
config:
text: =loop.day.label
action: toggle
actionCommand: ON
actionCommandAlt: OFF
actionItem: =(loop.item.name + 'E' + loop.day.name)
fill: "=(items[loop.item.name + 'E' + loop.day.name].state === 'ON' ? true : false)"
style:
font-weight: 400
- component: f7-row
config:
visible: =vars[loop.item.name + 'S'] === true
style:
margin: 10px
display: flex
justify-content: space-around
align-items: center
slots:
default:
- component: f7-row
config:
style:
align-items: center
slots:
default:
- component: Label
config:
text: Коррекция
style:
font-size: 12px
- component: f7-row
config:
style:
align-items: center
justify-content: space-around
slots:
default:
- component: Label
config:
text: по температуре
style:
font-size: 12px
margin-right: 10px
- component: oh-toggle
config:
color: green
item: =(loop.item.name + 'TimeCorrection')
- component: Label
config:
text: по осадкам
style:
font-size: 12px
margin: 0px 10px
- component: oh-toggle
config:
color: green
item: =(loop.item.name + 'RainCorrection')
- component: f7-block
config:
visible: =(vars.select == 3)
style:
animation: f7-fade-in 300ms
width: 99%
padding: 0px
margin: 5px
margin-right: 5px
class:
- display-flex
- justify-content-space-between
- flex-direction-column
slots:
default:
- component: f7-row
config:
style:
margin: 5px
width: 99%
font-size: 120%
slots:
default:
- component: Label
config:
text: Дневной полив
- component: oh-toggle
config:
item: IrrigationStartAtSpecificHour
color: green
- component: f7-row
config:
style:
margin: 5px
slots:
default:
- component: Label
config:
text: Время начала полива
- component: oh-link
config:
color: green
text: =items.IrrigationStartTime2.displayState
action: popup
actionModal: widget:timepicker_1
actionModalConfig:
item: IrrigationStartTime2
- component: f7-row
config:
style:
padding: 5px
margin: 0px
font-size: 120%
border: 1px solid green
border-radius: var(--f7-card-expandable-border-radius)
display: inline
slots:
default:
- component: oh-repeater
config:
fragment: false
for: item
sourceType: itemsInGroup
groupItem: GroupIrrigationValves
slots:
default:
- component: f7-row
config:
style:
margin-top: 5px
display: flex
justify-content: flex-start
align-items: center
slots:
default:
- component: oh-link
config:
iconMaterial: opacity
color: '=items[loop.item.name].state == "ON" ? "blue" : "gray"'
iconSize: 25px
action: popover
popoverOpen: ='.m'+loop.item.name
slots:
default:
- component: f7-popover
config:
class: ='m'+loop.item.name
slots:
default:
- component: f7-block
config:
style:
animate: true
align-self: center
justify-self: center
justify-content: center
text-align: center
slots:
default:
- component: Label
config:
text: Запуск вручную
- component: oh-button
config:
text: =items[loop.item.name].state
color: green
action: toggle
actionCommand: ON
actionCommandAlt: OFF
actionItem: =loop.item.name
- component: oh-button
config:
text: =loop.item.label
action: analyzer
actionAnalyzerItems: =[loop.item.name]
style:
--f7-button-hover-bg-color: green
color: white
font-size: 20px
margin-left: 10px
- component: oh-stepper
config:
item: =(loop.item.name + 'Time')
title: Время полива
min: 0
max: 180
step: 1
round: true
color: green
autorepeat: true
autorepeat-dynamic: true
style:
margin-left: auto
- component: oh-button
config:
iconF7: gear_alt_fill
color: '=vars[loop.item.name + "S"] === true ? "green" : "gray"'
action: variable
actionVariable: =(loop.item.name + 'S')
actionVariableValue: =!(vars[loop.item.name + 'S'] === true)
- component: f7-segmented
config:
strong: true
small: true
outline: true
color: green
class:
- segmented-round
style:
--f7-segmented-strong-padding: 0px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 300
--f7-segmented-strong-bg-color: transparent
--f7-segmented-strong-button-hover-bg-color: rgba(0, 255, 0, 0.1)
--f7-segmented-strong-button-active-bg-color: transparent
margin-top: 5px
slots:
default:
- component: oh-repeater
config:
fragment: true
for: day
sourceType: array
in:
- name: 1
label: Пн
- name: 2
label: Вт
- name: 3
label: Ср
- name: 4
label: Чт
- name: 5
label: Пт
- name: 6
label: Сб
- name: 7
label: Вс
slots:
default:
- component: oh-button
config:
text: =loop.day.label
action: toggle
actionCommand: ON
actionCommandAlt: OFF
actionItem: =(loop.item.name + 'D' + loop.day.name)
fill: "=(items[loop.item.name + 'D' + loop.day.name].state === 'ON' ? true : false)"
style:
font-weight: 400
- component: f7-row
config:
visible: =vars[loop.item.name + 'S'] === true
style:
margin: 10px
display: flex
justify-content: space-around
align-items: center
slots:
default:
- component: f7-row
config:
style:
align-items: center
slots:
default:
- component: Label
config:
text: Коррекция
style:
font-size: 12px
- component: f7-row
config:
style:
align-items: center
justify-content: space-between
slots:
default:
- component: Label
config:
text: по температуре
style:
font-size: 12px
margin-right: 10px
- component: oh-toggle
config:
color: green
item: =(loop.item.name + 'TimeCorrection')
- component: Label
config:
text: по осадкам
style:
font-size: 12px
margin: 0px 10px
- component: oh-toggle
config:
color: green
item: =(loop.item.name + 'RainCorrection')
uid: WateringSettings
tags: []
props:
parameters: []
parameterGroups: []
timestamp: Sep 13, 2021, 11:51:23 PM
component: f7-card
config:
style:
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
height: auto
margin: 5px
line-height: 1
font-family: sans-serif
slots:
default:
- component: f7-col
config:
style:
width: 100%
slots:
default:
- component: oh-chart
config:
chartType: ""
period: D
label: Температуры
slots:
title:
- component: oh-chart-title
config:
text: Температуры
top: 0px
middle: 0px
grid:
- component: oh-chart-grid
config:
width: 85%
includeLabels: true
xAxis:
- component: oh-time-axis
config:
gridIndex: 0
yAxis:
- component: oh-value-axis
config:
gridIndex: 0
name: °C
min: -30
series:
- component: oh-time-series
config:
name: Температура улица
gridIndex: 1
xAxisIndex: 0
yAxisIndex: 0
type: line
item: TemperatureUlica
smooth: true
markPoint:
data:
- type: max
name: Максимальная
- type: min
name: Минимальная
- type: average
name: Средняя
- component: oh-time-series
config:
name: Температура теплица
gridIndex: 1
xAxisIndex: 0
yAxisIndex: 0
type: line
min: -20
item: TemperatureTeplicaCorrected
smooth: true
areaStyle:
color:
type: linear
x: 0
y: 0
x2: 0
y2: 1
colorStops:
- offset: 0
color: rgb(70, 123, 168, 0.0)
- offset: 0.5
color: rgb(70, 123, 168, 0.5)
- offset: 1
color: rgb(70, 123, 168, 1.0)
tooltip:
- component: oh-chart-tooltip
config:
confine: true
smartFormatter: true
visualMap:
- component: oh-chart-visualmap
config:
show: false
presetPalette: greenred
orient: vertical
type: continuous
- component: oh-chart
config:
height: 180px
chartType: ""
period: D
label: Клапана полива
slots:
grid:
- component: oh-chart-grid
config:
includeLabels: true
xAxis:
- component: oh-time-axis
config:
gridIndex: 0
yAxis:
- component: oh-value-axis
config:
gridIndex: 0
series:
- component: oh-time-series
config:
name: Газон
gridIndex: 0
xAxisIndex: 0
yAxisIndex: 0
type: line
areaStyle: {}
slots:
markArea:
- component: oh-mark-area
config:
name: Газон
item: IrrigationValveZone3
- component: oh-time-series
config:
name: Картошка
gridIndex: 0
xAxisIndex: 0
yAxisIndex: 0
type: line
areaStyle: {}
slots:
markArea:
- component: oh-mark-area
config:
name: Картошка
item: IrrigationValveZone4
- component: oh-time-series
config:
name: Клубника
gridIndex: 0
xAxisIndex: 0
yAxisIndex: 0
type: line
areaStyle: {}
slots:
markArea:
- component: oh-mark-area
config:
name: Клубника
item: IrrigationValveZone2
- component: oh-time-series
config:
name: Теплица
gridIndex: 0
xAxisIndex: 0
yAxisIndex: 0
type: line
areaStyle: {}
slots:
markArea:
- component: oh-mark-area
config:
name: Теплица
item: IrrigationValveZone1
tooltip:
- component: oh-chart-tooltip
config:
confine: true
smartFormatter: true
legend:
- component: oh-chart-legend
config:
bottom: 3
type: scroll
dataZoom:
- component: oh-chart-datazoom
config:
type: inside
- component: f7-row
config:
style:
padding: 5px
align-items: center
justify-content: space-around
slots:
default:
- component: Label
config:
text: Осадки сегодня
- component: Label
config:
text: =items.SumRainLast24h.state
- component: f7-row
config:
style:
padding: 5px
align-items: center
justify-content: space-around
slots:
default:
- component: Label
config:
text: Осадки завтра
- component: Label
config:
text: =items.SumRainNext24h.state
- component: f7-row
config:
style:
margin: 5px
align-items: center
justify-content: space-around
slots:
default:
- component: Label
config:
text: Сумма осадков
- component: Label
config:
text: =items.irrRainSum.state
- component: f7-row
config:
style:
margin: 7px
align-items: center
justify-content: space-around
slots:
default:
- component: Label
config:
text: Температурный коэффициент
- component: Label
config:
text: =items.IrrigationDurationCoefficientFactor.state
- component: f7-row
config:
style:
margin: 7px
align-items: center
justify-content: space-around
slots:
default:
- component: Label
config:
text: Время до конца полива текущей зоны
- component: Label
config:
text: =items.IrrigationSectionRemainingTime.state+" мин"
- component: f7-row
config:
style:
margin: 10px
align-items: center
justify-content: space-around
slots:
default:
- component: Label
config:
text: Лимит осадков
- component: oh-stepper
config:
item: MaxAllowedRain
round: true
color: green
step: 0.1
style:
margin-left: auto
margin-right: 15px
- component: Label
config:
text: мм
- component: f7-row
config:
style:
margin: 10px
align-items: center
justify-content: flex-start
slots:
default:
- component: Label
config:
text: Максимальная скорость ветра
- component: oh-stepper
config:
round: true
color: green
item: MaxAllowedWindSpeed
style:
margin-left: auto
margin-right: 10px
- component: Label
config:
text: км/ч
===== Правила =====
/*
* Irrigation rules
*/
val logName = "Irrigation"
var Timer irrigationTimer = null
var String timeOfDay = ""
var String timeNumber = ""
// watering time correction factor - based on the average temperature
var coefficientFactor = 1.0
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 (IrrigationHoursAfterSunrise.state == NULL)
IrrigationHoursAfterSunrise.sendCommand(1)
if (IrrigationValveZone1Time.state == NULL)
IrrigationValveZone1Time.sendCommand(1)
if (IrrigationValveZone2Time.state == NULL)
IrrigationValveZone2Time.sendCommand(1)
if (IrrigationValveZone3Time.state == NULL)
IrrigationValveZone3Time.sendCommand(1)
if (IrrigationValveZone4Time.state == NULL)
IrrigationValveZone4Time.sendCommand(1)
if (IrrigationStartAtSpecificHour.state == NULL)
IrrigationStartAtSpecificHour.sendCommand(OFF)
if (IrrigationStartTime.state == NULL)
IrrigationStartTime.sendCommand(20)
if (IrrigationHoursBeforeSundown.state == NULL)
IrrigationHoursBeforeSundown.sendCommand(60)
if (IrrigationHoursBeforeSundown.state == NULL)
IrrigationHoursAfterSunrise.sendCommand(40)
if (IrrigationStartTime2.state == NULL)
IrrigationStartTime2.sendCommand(now())
if (IrrigationStartTime3.state == NULL)
IrrigationStartTime.sendCommand(20)
// close all valves
GroupIrrigationValves.members.filter[valve | valve.state != OFF].forEach[valve | valve.sendCommand(OFF)]
IrrigationCurrentValve.postUpdate(OFF)
end
rule "Irrigation - calculate whether to start watering"
when
Time cron "0 * * ? * *" // every minute
then
var Number wateringHour = 25
var Number wateringMinute = 61
var Number wateringHour2 = 25
var Number wateringMinute2 = 61
var Number wateringHour3 = 25
var Number wateringMinute3 = 61
try {
logDebug(logName, "Calculating whether to start irrigation")
// calculate rainfall
SumRainLast24h.sendCommand((Forecast_Current_Rain.sumSince(now.minusHours(24), "influxdb") as Number).doubleValue)
SumRainNext24h.sendCommand(Forecast_ForecastTomorrow_Rain.state as Number)
// wait to propagate item states - not sure if necessary
Thread.sleep(200)
logDebug(logName, "Rain - last 24h (sum): {} mm", String::format("%.2f", (SumRainLast24h.state as Number).doubleValue))
logDebug(logName, "Rain - forecast 24h (sum): {} mm", String::format("%.2f", (SumRainNext24h.state as Number).doubleValue))
///////////////////
// start calculations, whether to start and for how long
///////////////////
// check for the manual lock
if (IrrigationLock.state == ON) {
logDebug(logName, "Irrigation lock is on")
return
}
// check the week day
//val Number day = now.getDayOfWeek()
//val dayItem = ScriptServiceUtil.getItemRegistry.getItem("IrrigationDay" + day)
//if (dayItem === null || dayItem.state == OFF || dayItem.state == NULL) {
// logInfo(logName, "Inappropriate day to start irrigation", dayItem)
// return
//}
// set the default irrigation hour to X hours after the sunrise
val localSunrise = (IrrigationStartTime.state as DateTimeType).getZonedDateTime()
if (IrrigationStartAtSunrise.state == ON) {
wateringHour = localSunrise.getHour()
wateringMinute = localSunrise.getMinute()
logDebug(logName, "Watering at: {}:{}", wateringHour, wateringMinute)
}
else {
wateringHour = 25
wateringMinute = 61
}
// set the default irrigation hour to X hours before the sundown
val localSunDown = (IrrigationStartTime3.state as DateTimeType).getZonedDateTime()
if (IrrigationStartAtSundown.state == ON) {
wateringHour3 = localSunDown.getHour()
wateringMinute3 = localSunDown.getMinute()
logDebug(logName, "Watering at: {}:{}", wateringHour3, wateringMinute3)
}
else {
wateringHour3 = 25
wateringMinute3 = 61
}
// if there is a specific hour in settings, then use it
val specificHour = (IrrigationStartTime2.state as DateTimeType).getZonedDateTime()
if (IrrigationStartAtSpecificHour.state == ON) {
wateringHour2 = specificHour.getHour()
wateringMinute2 = specificHour.getMinute()
logDebug(logName, "Watering at: {}:{}", wateringHour2, wateringMinute2)
}
else {
wateringHour2 = 25
wateringMinute2 = 61
}
// check if the current time is the watering time (full hour)
if ((now.getHour != wateringHour || now.getMinute != wateringMinute) && (now.getHour != wateringHour2 || now.getMinute != wateringMinute2) && (now.getHour != wateringHour3 || now.getMinute != wateringMinute3)) {
// nope - good bye
logDebug(logName, "Inappropriate time to start irrigation")
return
}
else if (now.getHour == wateringHour && now.getMinute == wateringMinute) {
timeOfDay = "M"
timeNumber = "1"
}
else if (now.getHour == wateringHour2 && now.getMinute == wateringMinute2) {
timeOfDay = "D"
timeNumber = ""
}
else if (now.getHour == wateringHour3 && now.getMinute == wateringMinute3) {
timeOfDay = "E"
timeNumber = "2"
}
logInfo(logName, "It is watering time")
// check the weather, and based on that set the watering time coefficient factor
// if the temperature is to low, don't start watering
val avgTemperatureLast24h = (Forecast_Current_Temperature.averageSince(now.minusHours(24), "influxdb") as Number).doubleValue
logInfo(logName, "Average temperature for the last 24h: {}", avgTemperatureLast24h)
if (avgTemperatureLast24h <= 10) {
logInfo(logName, "Temperature too low to start irrigation")
return
}
else {
// coefficient factor should be between 1 and 2
// this part could, and should be better
coefficientFactor = (avgTemperatureLast24h / 20).floatValue
IrrigationDurationCoefficientFactor.sendCommand(coefficientFactor)
logInfo(logName, "Setting irrigation coefficient factor to {}", coefficientFactor)
}
///////////////////
// ok, let's start watering, cascading all of the valves from the GroupIrrigationValves
///////////////////
// starting with the Zone 1, other zones will be turned on in sequence by the separate rule
logDebug(logName, "Starting the irrigation sequence")
IrrigationCurrentValve.sendCommand(IrrigationValveZone1.name)
}
catch (Exception e) {
logError(logName, "Error calculating whether to start irrigation: " + e)
}
end
rule "Irrigation - cascading"
when
Item IrrigationCurrentValve received command
then
// check if the current wind speed is higher then the max allowed
logDebug(logName, "Current wind speed: {} km/h", String::format("%.2f", (Forecast_Current_Windspeed.state as Number).doubleValue))
if (Forecast_Current_Windspeed.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
val rainSum = (SumRainLast24h.state as Number).doubleValue + (SumRainNext24h.state as Number).doubleValue
logDebug(logName, "Past and forecasted average rain: {} mm", String::format("%.2f", rainSum))
IrrigationMasterValve.sendCommand(ON)
if (WaterPump.state == "ON") {
WaterPump.sendCommand(OFF)
}
try {
// get the currently open valve
val currValve = GroupIrrigationValves.members.findFirst[valve | valve.name == receivedCommand.toString]
val currValveNum = Integer::parseInt(currValve.name.split("Zone").get(1))
val currValveMins = GroupIrrigationTimes.members.findFirst[t | t.name == currValve.name+"Time"+timeNumber ].state as Number
logDebug(logName, "Current valve {}, duration {}", currValve.name, currValveMins)
val currRainCorrection = Group_Irrigation_Settings.members.findFirst[t | t.name == currValve.name+"RainCorrection" ].state.toString
val currDayOnOff = Group_Irrigation_Settings.members.findFirst[t | t.name == currValve.name+timeOfDay+now.getDayOfWeek.getValue ].state.toString
logDebug(logName, "Current rain correction {}, irrigation of this zone today is {}", currRainCorrection, currDayOnOff)
// 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)
// open the current valve
val currTimeCorrection = Group_Irrigation_Settings.members.findFirst[t | t.name == currValve.name+"TimeCorrection" ].state.toString
var Number valveOpenTime = 0
if (currTimeCorrection != "OFF") {
valveOpenTime = currValveMins * coefficientFactor
}
else {
valveOpenTime = currValveMins
}
if ((rainSum > (MaxAllowedRain.state as Number).doubleValue) && (currRainCorrection != "OFF")) {
logInfo(logName, "To heavy rain to irrigate (past and forcasted)")
if (nextValve !== null) {
// this will invoke cascading valves, "Irrigation - cascading" rule
IrrigationCurrentValve.sendCommand(nextValve.name)
}
else {
IrrigationMasterValve.sendCommand(OFF)
IrrigationSecondaryValve.sendCommand(OFF)
if (DefenceSystem.state == "ON") {
WaterPump.sendCommand(OFF)
}
logInfo(logName, "Irrigation is complete")
}
} else if (currDayOnOff != "OFF") {
logInfo(logName, "Opening {} for {} mins", currValve.name, valveOpenTime)
currValve.sendCommand(ON)
IrrigationSectionRemainingTime.postUpdate(valveOpenTime.intValue)
// set the timer, after expiring turn off the current valve and turn on the next one
irrigationTimer = createTimer(now.plusMinutes(valveOpenTime.intValue), [ |
if (nextValve !== null) {
// this will invoke cascading valves, "Irrigation - cascading" rule
IrrigationCurrentValve.sendCommand(nextValve.name)
}
else {
IrrigationMasterValve.sendCommand(OFF)
IrrigationSecondaryValve.sendCommand(OFF)
if (DefenceSystem.state == "ON") {
WaterPump.sendCommand(OFF)
}
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 if (nextValve !== null) {
// this will invoke cascading valves, "Irrigation - cascading" rule
IrrigationCurrentValve.sendCommand(nextValve.name)
}
else {
IrrigationMasterValve.sendCommand(OFF)
IrrigationSecondaryValve.sendCommand(OFF)
if (DefenceSystem.state == "ON") {
WaterPump.sendCommand(OFF)
}
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 > 0)
IrrigationSectionRemainingTime.postUpdate((IrrigationSectionRemainingTime.state as Number) - 1)
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)
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 |
logInfo(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
logInfo(logName, "Irrigation valve open, starting protection timer")
IrrigationTimerMax.sendCommand(ON)
}
else {
// the timer is already running
logInfo(logName, "Irrigation valve open, timer already started, nothing to do")
}
}
else {
logInfo(logName, "All irrigation valves closed, stopping protection timer")
IrrigationTimerMax.postUpdate(OFF)
}
//triggeringItem.postUpdate(triggeringItem.state)
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 |
logInfo(logName, "Closing valve: " + valve.name)
valve.sendCommand(OFF)
]
end
===== Items =====
// settings group
Group Group_Irrigation_Settings
// irrigation lock
Switch IrrigationLock "Запрет полива" (Group_Irrigation_Settings) { ga="Switch" }
// protection against too long watering, 2h default
Switch IrrigationTimerMax "Максимальное время полива [MAP(irrigation.map):%s]" { expire = "2h,command=OFF" }
// all valves group
Group:Switch:OR(ON,OFF) GroupIrrigationValves "Клапана полива [MAP(irrigation.map):%s]"
Group:Number:SUM GroupIrrigationTimes "Полное время полива [%d min.]"
// cascading valves - current zone
String IrrigationCurrentValve "Текущая зона полива [MAP(irrigation.map):%s]"
// irrigation master valve switch
Switch IrrigationMasterValve "Главный клапан полива" (Group_Irrigation_Settings)
// irrigation valves' switches
Switch IrrigationValveZone1 "Теплица" (GroupIrrigationValves) { ga="Switch" }
Switch IrrigationValveZone2 "Клубника" (GroupIrrigationValves) { ga="Switch" }
Switch IrrigationValveZone3 "Газон" (GroupIrrigationValves) { ga="Switch" }
Switch IrrigationValveZone4 "Картошка" (GroupIrrigationValves)
// irrigation times
Number IrrigationValveZone1Time "Время полива теплицы" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone2Time "Время полива клубники" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone3Time "Время полива газона" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone4Time "Время полива картошки" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone1Time1 "Время полива теплицы на рассвете" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone2Time1 "Время полива клубники на рассвете" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone3Time1 "Время полива газона на рассвете" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone4Time1 "Время полива картошки на рассвете" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone1Time2 "Время полива теплицы на закате" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone2Time2 "Время полива клубники на закате" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone3Time2 "Время полива газона на закате" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationValveZone4Time2 "Время полива картошки на закате" (GroupIrrigationTimes, Group_Irrigation_Settings) { stateDescription=" "[ pattern="%d min" ] }
Number IrrigationDurationCoefficientFactor "Коэффициент коррекции полива"
Number IrrigationSectionRemainingTime "Время до конца полива [%d]"
// switch - whether to start at a particular hour or before the sunrise
Switch IrrigationStartAtSpecificHour "Полив в заданное время" (Group_Irrigation_Settings)
Switch IrrigationStartAtSunrise "Полив на рассвете" (Group_Irrigation_Settings)
Switch IrrigationStartAtSundown "Полив на закате" (Group_Irrigation_Settings)
Number IrrigationStartTime "Время полива после восхода" (Group_Irrigation_Settings)
Number IrrigationStartTime2 "Время полива заданное" (Group_Irrigation_Settings)
Number IrrigationStartTime3 "Время полива перед закатом" (Group_Irrigation_Settings)
Number IrrigationHoursAfterSunrise "Старт полива после восхода [%d h]" (Group_Irrigation_Settings)
Nunber IrrigationHoursBeforeSundown "Старт полива перед закатом [%d h]" (Group_Irrigation_Settings)
// irrigation week days
Switch IrrigationDay1 "Понедельник"
Switch IrrigationDay2 "Вторник"
Switch IrrigationDay3 "Среда"
Switch IrrigationDay4 "Четверг"
Switch IrrigationDay5 "Пятница"
Switch IrrigationDay6 "Суббота"
Switch IrrigationDay7 "Воскресенье"
Number:Length SumRainLast24h "Осадки за сегодня [%.2f mm]"
Number:Length SumRainNext24h "Осадки завтра [%.2f mm]"
Number:Speed MaxAllowedWindSpeed "Максимальная скорость ветра [%d km/h]" (Group_Irrigation_Settings)
Number:Length MaxAllowedRain "Максимальная сумма осадков [%.1f mm]" (Group_Irrigation_Settings)
Switch IrrigationValveZone1TimeCorrection "Коррекция времени полива теплицы" (Group_Irrigation_Settings)
Switch IrrigationValveZone2TimeCorrection "Коррекция времени полива клубники" (Group_Irrigation_Settings)
Switch IrrigationValveZone3TimeCorrection "Коррекция времени полива газона" (Group_Irrigation_Settings)
Switch IrrigationValveZone4TimeCorrection "Коррекция времени полива картошки" (Group_Irrigation_Settings)
Switch IrrigationValveZone1RainCorrection "Коррекция времени полива теплицы" (Group_Irrigation_Settings)
Switch IrrigationValveZone2RainCorrection "Коррекция времени полива клубники" (Group_Irrigation_Settings)
Switch IrrigationValveZone3RainCorrection "Коррекция времени полива газона" (Group_Irrigation_Settings)
Switch IrrigationValveZone4RainCorrection "Коррекция времени полива картошки" (Group_Irrigation_Settings)
Switch IrrigationValveZone1M1 "Полив теплицы утром понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone1M2 "Полив теплицы утром вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone1M3 "Полив теплицы утром среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone1M4 "Полив теплицы утром четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone1M5 "Полив теплицы утром пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone1M6 "Полив теплицы утром суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone1M7 "Полив теплицы утром воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone2M1 "Полив клубники утром понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone2M2 "Полив клубники утром вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone2M3 "Полив клубники утром среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone2M4 "Полив клубники утром четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone2M5 "Полив клубники утром пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone2M6 "Полив клубники утром суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone2M7 "Полив клубники утром воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone3M1 "Полив газона утром понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone3M2 "Полив газона утром вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone3M3 "Полив газона утром среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone3M4 "Полив газона утром четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone3M5 "Полив газона утром пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone3M6 "Полив газона утром суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone3M7 "Полив газона утром воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone4M1 "Полив картошки утром понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone4M2 "Полив картошки утром вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone4M3 "Полив картошки утром среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone4M4 "Полив картошки утром четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone4M5 "Полив картошки утром пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone4M6 "Полив картошки утром суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone4M7 "Полив картошки утром воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone1D1 "Полив теплицы днём понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone1D2 "Полив теплицы днём вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone1D3 "Полив теплицы днём среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone1D4 "Полив теплицы днём четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone1D5 "Полив теплицы днём пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone1D6 "Полив теплицы днём суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone1D7 "Полив теплицы днём воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone2D1 "Полив клубники днём понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone2D2 "Полив клубники днём вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone2D3 "Полив клубники днём среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone2D4 "Полив клубники днём четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone2D5 "Полив клубники днём пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone2D6 "Полив клубники днём суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone2D7 "Полив клубники днём воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone3D1 "Полив газона днём понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone3D2 "Полив газона днём вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone3D3 "Полив газона днём среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone3D4 "Полив газона днём четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone3D5 "Полив газона днём пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone3D6 "Полив газона днём суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone3D7 "Полив газона днём воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone4D1 "Полив картошки днём понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone4D2 "Полив картошки днём вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone4D3 "Полив картошки днём среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone4D4 "Полив картошки днём четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone4D5 "Полив картошки днём пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone4D6 "Полив картошки днём суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone4D7 "Полив картошки днём воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone1E1 "Полив теплицы вечером понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone1E2 "Полив теплицы вечером вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone1E3 "Полив теплицы вечером среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone1E4 "Полив теплицы вечером четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone1E5 "Полив теплицы вечером пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone1E6 "Полив теплицы вечером суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone1E7 "Полив теплицы вечером воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone2E1 "Полив клубники вечером понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone2E2 "Полив клубники вечером вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone2E3 "Полив клубники вечером среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone2E4 "Полив клубники вечером четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone2E5 "Полив клубники вечером пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone2E6 "Полив клубники вечером суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone2E7 "Полив клубники вечером воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone3E1 "Полив газона вечером понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone3E2 "Полив газона вечером вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone3E3 "Полив газона вечером среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone3E4 "Полив газона вечером четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone3E5 "Полив газона вечером пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone3E6 "Полив газона вечером суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone3E7 "Полив газона вечером воскресенье" (Group_Irrigation_Settings)
Switch IrrigationValveZone4E1 "Полив картошки вечером понедельник" (Group_Irrigation_Settings)
Switch IrrigationValveZone4E2 "Полив картошки вечером вторник" (Group_Irrigation_Settings)
Switch IrrigationValveZone4E3 "Полив картошки вечером среда" (Group_Irrigation_Settings)
Switch IrrigationValveZone4E4 "Полив картошки вечером четверг" (Group_Irrigation_Settings)
Switch IrrigationValveZone4E5 "Полив картошки вечером пятница" (Group_Irrigation_Settings)
Switch IrrigationValveZone4E6 "Полив картошки вечером суббота" (Group_Irrigation_Settings)
Switch IrrigationValveZone4E7 "Полив картошки вечером воскресенье" (Group_Irrigation_Settings)
Непричёсан для использования другими, чего-то может не хватать, но разобраться и скорректировать под себя должно быть несложно.