Полив
Источник 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)
Непричёсан для использования другими, чего-то может не хватать, но разобраться и скорректировать под себя должно быть несложно.