Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
- Romel
- Beiträge: 42
- Registriert: 21. Mai 2020 15:32
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Ich hab es nach dieser Beschreibung gemacht:
https://youtu.be/Cx0xujk_x9o
https://youtu.be/Cx0xujk_x9o
- udo1toni
- Beiträge: 13951
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Ich kann nicht so ganz nachvollziehen, warum es noch eine dritte Backupvariante sein muss.
openHABian bringt amanda für Komplettbackups mit, für openHAB viel interessanter ist aber openhab-cli backup, die eingebaute Backup-Funktion. Sie erstellt nur ein (vollständiges) Backup aller Konfigurationsdateien und der internen Persistence (das sind mapDB und RRD4J). Das geht ohne openHAB zu beenden.
Ein vollständigen Backup des gesamten Systems zurückzuspielen, geht auch nicht viel schneller als das Neuaufsetzen und anschließende Zurückspielen der Konfiguration, mit dem Unterschied, dass man anschließend ein sauberes System hat.
Es ist wirklich keine gute Idee, openHAB regelhaft nachts neustarten zu lassen.
Natürlich kann man das konkrete Problem des Timers am nächsten Tag lösen, indem man die Startzeit in ein Item rettet, welches per mapDB persistiert und beim Start per restoreOnStartup wiederhergestellt wird. Dann braucht es noch eine Rule, die per System started aufgerufen wird und prüft, ob das Item ungleich NULL ist. Ist das der Fall, wurde der letzte Wert schon geladen und kann ausgewertet werden. Ist das Item NULL, muss ein Timer gestartet werden, um nach einiger Zeit nochmals zu prüfen, ob das item inzwischen gefüllt wurde.
Wie gesagt, alles machbar, aber vergleichsweise aufwändig. openHAB sollte nicht ohne triftigen Grund ständig neu gestartet werden.
Hab ich schon erwähnt, dass openHAB besser durchlaufen sollte?
openHABian bringt amanda für Komplettbackups mit, für openHAB viel interessanter ist aber openhab-cli backup, die eingebaute Backup-Funktion. Sie erstellt nur ein (vollständiges) Backup aller Konfigurationsdateien und der internen Persistence (das sind mapDB und RRD4J). Das geht ohne openHAB zu beenden.
Ein vollständigen Backup des gesamten Systems zurückzuspielen, geht auch nicht viel schneller als das Neuaufsetzen und anschließende Zurückspielen der Konfiguration, mit dem Unterschied, dass man anschließend ein sauberes System hat.
Es ist wirklich keine gute Idee, openHAB regelhaft nachts neustarten zu lassen.
Natürlich kann man das konkrete Problem des Timers am nächsten Tag lösen, indem man die Startzeit in ein Item rettet, welches per mapDB persistiert und beim Start per restoreOnStartup wiederhergestellt wird. Dann braucht es noch eine Rule, die per System started aufgerufen wird und prüft, ob das Item ungleich NULL ist. Ist das der Fall, wurde der letzte Wert schon geladen und kann ausgewertet werden. Ist das Item NULL, muss ein Timer gestartet werden, um nach einiger Zeit nochmals zu prüfen, ob das item inzwischen gefüllt wurde.
Wie gesagt, alles machbar, aber vergleichsweise aufwändig. openHAB sollte nicht ohne triftigen Grund ständig neu gestartet werden.
Hab ich schon erwähnt, dass openHAB besser durchlaufen sollte?
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet
- Romel
- Beiträge: 42
- Registriert: 21. Mai 2020 15:32
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Werde mir das auch anschauen.
Habe aber jetzt noch ein anderes Problem:
Ich habe die Gartenbewässerung dupliziert und alles mit einen "b" ergänzt.
Natürlich auch neue items angelegt.
Ich bekomme es nicht zum starten.
Keine logInfo wird eingespielt egal wie ich es trigger.
In der Log sehe ich nur wie sich die Werte ändern.
Mit der Version "a" ist alles ok.
Habe aber jetzt noch ein anderes Problem:
Ich habe die Gartenbewässerung dupliziert und alles mit einen "b" ergänzt.
Natürlich auch neue items angelegt.
Ich bekomme es nicht zum starten.
Keine logInfo wird eingespielt egal wie ich es trigger.
In der Log sehe ich nur wie sich die Werte ändern.
Mit der Version "a" ist alles ok.
Code: Alles auswählen
var Timer btRegner = null
var int biRegner = 0
var Timer btStartRegner = null
// Beregnung B
rule "Startzeit einstellen"
when
System started or
Member of bgWeekdays changed or // Wochentag geändert
Item bStartzeit_Minuten changed or // Minuten geändert
Item bStartzeit_Stunden changed or // Stunden geändert
Time cron "1 0 12 * * ?" // täglich um 12:01 Uhr
then
// Alle Wochentag-Items müssen in der Gruppe gWeekdays zusammengefasst sein, damit der Trigger oben funktioniert
var bdayOfWeekSetting = newArrayList(
bMonday.state,
bTuesday.state,
bWednesday.state,
bThursday.state,
bFriday.state,
bSaturday.state,
bSunday.state
)
var int bminutes = 0 // Initialwert für Minuten definieren
if(bStartzeit_Minuten.state instanceof Number) { // Falls das Item eine gültige Zahl enthält
bminutes = (bStartzeit_Minuten.state as Number).intValue // Setze minutes auf diese Zahl
if(bminutes > 59) bminutes = 0 // Falls Obergrenze überschritten setze auf 0
if(bminutes < 0) bminutes = 59 // Falls Untergrente unterschritten setze auf 59
}
bStartzeit_Minuten.postUpdate(bminutes) // Schreibe Wert in das Item
var int bhours = 0 // Initialwert für Sunden definieren
if(bStartzeit_Stunden.state instanceof Number) { // Falls das Item eine gültige Zahl enthält
bhours = (bStartzeit_Stunden.state as Number).intValue // Setze hours auf diese Zahl
if(bhours > 23) bhours = 0 // Falls Obergrenze überschritten setze auf 0
if(bhours < 0) bhours = 23 // Falls Untergrente unterschritten setze auf 23
}
bStartzeit_Stunden.postUpdate(bhours) // Schreibe Wert in das Item
val int bstartMinutes = bhours * 60 + bminutes // Zeit in Minuten
btStartRegner?.cancel
logInfo("watering B","Kontrolliere Wochentag") // geplante Beregnung canceln
if(bdayOfWeekSetting.get(now.getDayOfWeek-1) == ON) { // Falls heute Beregnung gewünscht
if(now.getMinuteOfDay < bstartMinutes) {
logInfo("watering B","Warte auf Startzeit")
Info.sendCommand("Starte Beregnung um " + (bStartzeit_Stunden.state as Number) + ":" + if((bStartzeit_Minuten.state as Number) < 10)"0" + (bStartzeit_Minuten.state as Number) else (bStartzeit_Minuten.state as Number) )
bInfo.sendCommand(ON) // Falls Startzeit noch nicht erreicht
btStartRegner = createTimer(now.withTimeAtStartOfDay.plusMinutes(bstartMinutes),[| // Setze einen Timer auf gewünschte Startzeit
bWetterPrognose.sendCommand(ON) // Starte zur gewünschten Zeit
])
}
}
else logInfo("watering B","Wochentag ist Ausgeschaltet")
end
rule "Wetter und Feuchtigkeit einbinden"
when
Item bWetterPrognose received command
then
//Wind
var wind = 0
if(WetterAktuellWindgesch.state instanceof Number){
wind = ((WetterAktuellWindgesch.state as Number).floatValue).intValue
var maxwind = 0
if(bmaxWind.state instanceof Number)
maxwind = ((bmaxWind.state as Number).floatValue).intValue
if(wind >= maxwind){
bBeregnung.sendCommand(OFF)
logWarn("watering B","Derzeit ist es zu windig! {} km/h: Abbruch!", wind)
Info.sendCommand("Windgeschwidigkeit zu hoch: Abbruch!")
bInfo.sendCommand(ON)
}
//Regen
if(WetterAktuellRegen.state instanceof Number && Wetter3hRegen.state instanceof Number && Wetter6hRegen.state instanceof Number && Wetter12hRegen.state instanceof Number && Wetter24hRegen.state instanceof Number && Wetter72hRegen.state instanceof Number){
RegenPrognose_24.postUpdate(((WetterAktuellRegen.state as Number + Wetter3hRegen.state as Number + Wetter6hRegen.state as Number + Wetter12hRegen.state as Number + Wetter24hRegen.state as Number) * 1000) * 2)
logInfo("watering B","RegenPrognose_24: " + RegenPrognose_24.state)
if((RegenPrognose_24.state as Number) >= (bminRegen.state as Number)){
logWarn("watering B","Es wird genug Regnen! {} mm/m²: Abbruch !", RegenPrognose_24.state)
Info.sendCommand("Es wird genug Regnen: Abbruch!")
bBeregnung.postUpdate(OFF)
}
//Feuchtigkeit
if(gFeuchtDurchschnitt.state <= 300) {
logInfo("watering B","Feuchtigkeit ist {} : Abbruch !", gFeuchtDurchschnitt.state)
//Info.postUpdate("Feuchtigkeit ist {} : Abbruch !", gFeuchtDurchschnitt.state)
bBeregnung.postUpdate(OFF)
}
else
{
bBeregnung.sendCommand(ON)
}
}
}
end
rule "Beregnung EIN"
when
Item bBeregnung received command
then
if(receivedCommand == OFF) {
logWarn("watering B","Beregnung wird abgebrochen!")
sendBroadcastNotification("Beregnung wird abgebrochen!") //Nachricht an openhab APP
postUpdate(Info, "Beregnung abgebrochen !")
bInfo.sendCommand(ON) // Info Bestätigung einschalten
btRegner?.cancel // Timer stoppen
btRegner = null // Variable leeren
bgRegner.members.filter[i|i.name.contains("bPower")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)] // alle Regner abschalten
//gPumpe.sendCommand(OFF) // Pumpe abschalten
bSperre.postUpdate(OFF) // Bediensperre aufheben
}
else
{
if(btRegner !== null) {
logWarn("watering B","Regner scheint noch zu laufen! Abbruch")
return;
}
biRegner = 0
bSperre.postUpdate(ON)
//gPumpe.sendCommand(ON)
postUpdate(Info, "Beregnung gestartet !")
sendBroadcastNotification("Beregnung gestartet !")
btRegner = createTimer(now.plusMillis(10),[|
biRegner++ // nächsten Regener anwählen
logInfo("regner B","{}. Durchlauf",biRegner)
bgRegner.members.filter[i|i.name.contains("bPower")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)] // alle Regner abschalten
val bmaxRegner = bgRegner.members.filter[i|i.name.contains("bSperre")].filter[j| j.state == OFF].size // wieviele Regner sollen insgesamt beregnen?
logInfo("regner B","{}. Durchlauf von {} Durchläufen.",biRegner,bmaxRegner)
if(biRegner > bmaxRegner) { // letzten Regner schon erreicht?
logInfo("regner B","Alle Regner sind schon gelaufen!")
sendBroadcastNotification("Beregnung Fertig !")
postUpdate(Info, "Beregnung Fertig !")
bInfo.sendCommand(ON) // Info Bestätigung einschalten
btRegner = null // Dann Schluss!
bSperre.postUpdate(OFF)
bBeregnung.postUpdate(OFF) // Item zurücksetzen
//gPumpe.sendCommand(OFF)
return;
}
Thread::sleep(15000) // kleine(15 sec) Pause einlegen
val bstrRegner = bgRegner.members.filter[i|i.name.contains("bSperre")].filter[j| j.state == OFF].sortBy[name].get(biRegner-1).name.split("_").get(2) //Namen des Regner ermitteln
logInfo("regner B","Nächster Regner: {}",bstrRegner)
bgRegner.members.filter[i|i.name.contains("bPower") && i.name.contains(bstrRegner)].head.sendCommand(ON) // Regner einschalten
val bDauer =(bgRegner.members.filter[i|i.name.contains("bDauer") && i.name.contains(bstrRegner)].head.state as Number).intValue
logInfo("regner B","Regenr wird nach {} Minuten wieder abgeschaltet.",bDauer)
btRegner.reschedule(now.plusMinutes(bDauer)) // Nächste Ausführung planen
])
}
end
-
- Beiträge: 3
- Registriert: 16. Jan 2019 08:32
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Hallo Cyrelian,Cyrelian hat geschrieben: ↑23. Jun 2018 13:09 Hallo Forumgemeinde,
in den letzten Wochen hab ich mich intensiv mit meiner automatischen Gartenbewässerung / Beregnung beschäftigt und möchte nun die Ergebnisse mit euch teilen.
Als erstes mal jede Menge PE-HD Rohr unter die Erde bringen
Verbaut habe ich Rain Bird Regner und Hunter Magentventile (Empfehlung von Seppy )
Wer weitere Details zu den Komponenten der eingentlichen Bewässerung haben möchte, bitte PN an mich.
Steuerung:
Für die Steuerung der Beregnung habe ich folgende Komponenten verbaut:
Aktor(WIFI): Sonoff 4CH R2 (sehr günstige Alternative zum HomeMatic Funk-Schaltaktor 4-fach / Hutschiene)
Wichtig ist hier die PRO R2 Version!
Trafo(24VAC): Vemer vn318200 Trafo TMC 24/24
Auf den Sonoff habe ich selbstverständlich Tasmota geflashed
In der Unterverteilung sieht das Ganze dann so aus:
Verteiler.jpeg
So nun kommen wir mal zum opemHAB-Teil des Projektes. Die ITEMS und Rules wurden unter openHAB 2.3 erstellt!
ITEMS:
Als erstes nutze ich das Wunderground-Binding und seine ITEMS
Wunderground-Items
irrigation.items
RULES:Code: Alles auswählen
/* ------------- BEREGNUNG -------------------- */ //--------------- Magnetventilschalter Hutschiene (Sonoff 4CH Pro R2) ---------------- Group:Switch:OR(ON, OFF) gABBeregnung "Gartenbewässerung" <irrigation> (gGarten) Switch ABBeregnungMGV1 "MGV1 - Beregnung Segment (vorne)" <irrigation> (gABBeregnung,gIrrigation,gInitializeOff) {mqtt=">[mosquitto:sonoff/ABBeregnung/cmnd/POWER1:command:*:default], <[mosquitto:sonoff/ABBeregnung/stat/POWER1:state:default]"} Switch ABBeregnungMGV2 "MGV2 - Beregnung Segment (mitte)" <irrigation> (gABBeregnung,gIrrigation,gInitializeOff) {mqtt=">[mosquitto:sonoff/ABBeregnung/cmnd/POWER2:command:*:default], <[mosquitto:sonoff/ABBeregnung/stat/POWER2:state:default]"} Switch ABBeregnungMGV3 "MGV3 - Beregnung Segment (hinten)" <irrigation> (gABBeregnung,gIrrigation,gInitializeOff) {mqtt=">[mosquitto:sonoff/ABBeregnung/cmnd/POWER3:command:*:default], <[mosquitto:sonoff/ABBeregnung/stat/POWER3:state:default]"} Switch ABBeregnungMGV4 "MGV4 - Beregnung Segment (xxxx)" <irrigation> (gABBeregnung,gIrrigation,gInitializeOff) {mqtt=">[mosquitto:sonoff/ABBeregnung/cmnd/POWER4:command:*:default], <[mosquitto:sonoff/ABBeregnung/stat/POWER4:state:default]"} Number ABBeregnung_RSSI "Magnetventilschalter RSSI [%d %%]" <network> (gSysRSSI) {mqtt="<[mosquitto:sonoff/ABBeregnung/tele/STATE:state:JSONPATH($.Wifi.RSSI)]"} Switch ABBeregnung_Unreach "Magnetventilschalter unreachable" <siren> (gSysUnreach) {mqtt="<[mosquitto:sonoff/ABBeregnung/tele/LWT:state:MAP(unreach.map)]"} String ABBeregnung_FW "Magnetventilschalter Firmware [%s]" <sonoff_4chpro> (gSysSonoff_Maintenance) {mqtt="<[mosquitto:stat/ABBeregnung/STATUS2:state:JSONPATH($.StatusFWR.Version)"} /* ------------- GRUPPEN -------------------- */ Group gProgramSettings "Einstellungen" (gIrrigation) //Programm A Group gProgramASettings "Programm A - Einstellungen" <settings> (gProgramSettings) Group gProgramADuration "Laufzeit" (gProgramASettings) Group gProgramADayOfWeek "Wochentag" (gProgramASettings) //Programm B Group gProgramBSettings "Programm B - Einstellungen" <settings> (gProgramSettings) Group gProgramBDuration "Laufzeit" (gProgramBSettings) Group gProgramBDayOfWeek "Wochentag" (gProgramBSettings) /* ------------- ITEMS -------------------- */ //MISC Number ABBeregnung_Scale_Factor "Skalierungsfaktor (Rain, Temp., Humidity) [%d %%]" <water> (gIrrigation) //Virtuelle Schalter Beregnung Switch ABBeregnungMGV1_State "MGV1 - Beregnungssegment (vorne)" <irrigation> (gIrrigation,gInitializeOff) Switch ABBeregnungMGV2_State "MGV2 - Beregnungssegment (mitte)" <irrigation> (gIrrigation,gInitializeOff) Switch ABBeregnungMGV3_State "MGV3 - Beregnungssegment (hinten)" <irrigation> (gIrrigation,gInitializeOff) Switch ABBeregnung_Disable "Deaktivierung der kompletten Beregnung" <irrigation> (gIrrigation,gInitializeOff) //letzter Beregnungslauf DateTime ABBeregnungMGV1_LastRun "Letzte Beregnung (vorne) [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (gIrrigation) DateTime ABBeregnungMGV2_LastRun "Letzte Beregnung (mitte) [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (gIrrigation) DateTime ABBeregnungMGV3_LastRun "Letzte Beregnung (hinten) [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (gIrrigation) // Programm A Master Einstellungen Switch ProgramA_Master "Bewässerungsprogramm A" <irrigation> (gProgramASettings) Switch ProgramA_Master_DayofWeek "Programm A Wochentag [%s]" <calendar> (gProgramASettings) Switch ProgramA_Master_Weather "Regen im Forecast (Rain Delay) [%s]" <rain> (gProgramASettings) Number ProgramA_ScaleFactor "Scale Factor [%d %%]" <water> (gProgramASettings) String ProgramA_StartTime "nächste Startzeit [%s]" <calendar> (gProgramASettings) Number ProgramA_StartTime_Hours "Startzeit - Stunden [%d]" <time> (gProgramASettings) Number ProgramA_StartTime_Minutes "Startzeit - Minuten [%d]" <time> (gProgramASettings) // Programm A Einstellungen Number ABBeregnungMGV1_Duration_A "Laufzeit Beregnungssegment (vorne) [%d Min.]" <time> (gProgramASettings, gProgramADuration) Number ABBeregnungMGV2_Duration_A "Laufzeit Beregnungssegment (mitte) [%d Min.]" <time> (gProgramASettings, gProgramADuration) Number ABBeregnungMGV3_Duration_A "Laufzeit Beregnungssegment (hinten) [%d Min.]" <time> (gProgramASettings, gProgramADuration) Number ABBeregnungMGV4_Duration_A "Laufzeit Beregnungssegment 4 [%d Min.]" <time> (gProgramASettings, gProgramADuration) Switch Monday_ProgramA "Montag [%s]" <calendar> (gProgramASettings, gProgramADayOfWeek) Switch Tuesday_ProgramA "Dienstag [%s]" <calendar> (gProgramASettings, gProgramADayOfWeek) Switch Wednesday_ProgramA "Mittwoch [%s]" <calendar> (gProgramASettings, gProgramADayOfWeek) Switch Thursday_ProgramA "Donnerstag [%s]" <calendar> (gProgramASettings, gProgramADayOfWeek) Switch Friday_ProgramA "Freitag [%s]" <calendar> (gProgramASettings, gProgramADayOfWeek) Switch Saturday_ProgramA "Samstag [%s]" <calendar> (gProgramASettings, gProgramADayOfWeek) Switch Sunday_ProgramA "Sonntag [%s]" <calendar> (gProgramASettings, gProgramADayOfWeek) // Programm B Master Einstellungen Switch ProgramB_Master "Bewässerungsprogramm B" <irrigation> (gProgramBSettings) Switch ProgramB_Master_DayofWeek "Programm B Wochentag [%s]" <calendar> (gProgramBSettings) Switch ProgramB_Master_Weather "Programm B Rain Delay [%s]" <water> (gProgramBSettings) Number ProgramB_ScaleFactor "Scale Factor [%d %%]" <water> (gProgramBSettings) String ProgramB_StartTime "Startzeit [%s]" <calendar> (gProgramBSettings) Number ProgramB_StartTime_Hours "Stunden [%d]" <time> (gProgramBSettings) Number ProgramB_StartTime_Minutes "Minuten [%d]" <time> (gProgramBSettings) // Programm B Einstellungen Number ABBeregnungMGV1_Duration_B "Segment (vorne) Laufzeit[%d Min.]" <water> (gProgramBSettings) Number ABBeregnungMGV2_Duration_B "Segment (mitte) Laufzeit[%d Min.]" <water> (gProgramBSettings) Number ABBeregnungMGV3_Duration_B "Segment (hinten) Laufzeit[%d Min.]" <water> (gProgramBSettings) Number ABBeregnungMGV4_Duration_B "Segment 4 Laufzeit[%d Min.]" <water> (gProgramBSettings) Switch Monday_ProgramB "Montag [%s]" <calendar> (gProgramBSettings) Switch Tuesday_ProgramB "Dienstag [%s]" <calendar> (gProgramBSettings) Switch Wednesday_ProgramB "Mittwoch [%s]" <calendar> (gProgramBSettings) Switch Thursday_ProgramB "Donnerstag [%s]" <calendar> (gProgramBSettings) Switch Friday_ProgramB "Freitag [%s]" <calendar> (gProgramBSettings) Switch Saturday_ProgramB "Samstag [%s]" <calendar> (gProgramBSettings) Switch Sunday_ProgramB "Sonntag [%s]" <calendar> (gProgramBSettings)
irrigation.rules
Der nachfolgende Code steht in einem Rule File, aber der Übersicht halber splitte ich mal Rule für Rule und kommentiere ein bischen.
Los geht es mit den globalen Variablen.
Nach einem Systemneustart, wird geprüft ob ggf. noch Magnetventile offen sind und werden entsprechend geschlossen.Code: Alles auswählen
val String filename = "irrigation.rules" // Loggername // Automatische Beregnungstimer var Timer MGV1StartTimer = null var Timer MGV1StopTimer = null var Timer MGV2StartTimer = null var Timer MGV2StopTimer = null var Timer MGV3StartTimer = null var Timer MGV3StopTimer = null //var Timer WateringStopTimer = null // Manuelle Beregnugstimer var Timer IrrigationTimer = null // val int maxOffDays = 2 //nach 2 Tagen wird der ProgramA_Master_Weather OFF geschaltet val int minPrecipPercent = 50 //die minimale Niederschlagswahrscheinlichkeit zum Einschalten des ProgramA_Master_Weather val int minPrecip = 4 //die Mindestmenge an Regen in den letzten 24 Stunden zum Einschalten des ProgramA_Master_Weather
In dieser Rule wird geschaut, ob es heute geregnet hat, oder ob Regen im Forecast für morgen ist. Dazu werden die die IST-Werte mit den beiden Variablen minPrecip und minPrecipPercent verglichen. Sollte es hier eine Übereinstimmung geben, wird die Beregnung für die nächsten 2 Tage deaktiviert.Code: Alles auswählen
rule "Irrigation startup" when System started then gABBeregnung?.allMembers.filter(x | x.state != OFF).forEach[ item | logInfo(filename,"Beregnung: Beregnung wird deaktiviert") item.sendCommand(OFF) ] end
Da Joda Time leider kein now.withTimeAtEndOfDay kann, schreibe ich den Regen Tageswert um 23:59 weg und schiebe es in die persistence.Code: Alles auswählen
rule "Rain Delay" when Time cron "5 15 23 ? * * *" //23:15:05 then if (ProgramA_Master_Weather.lastUpdate.before(now.minusDays(maxOffDays))) { ProgramA_Master_Weather.sendCommand(OFF) } else { var boolean delay = false //Es hat heute geregnet min. 4mm if ((RainToday.state as QuantityType<Number>).doubleValue >= minPrecip) { delay = true } //Regen im Forecast min. 50% if ((ForecastProbaPrecip_day1.state as QuantityType<Number>).doubleValue >= minPrecipPercent) { delay = true } if (delay) { ProgramA_Master_Weather.sendCommand(ON) logInfo(filename,"Beregnung: Es hat geregnet oder Regen im Forecast") sendPushoverMessage(pushoverBuilder("Es hat geregnet heute geregnet oder die Regenwahrscheinlichkeit für morgen liegt über 50%. Die beregnung wird für 2 tage deaktiviert")) } else { ProgramA_Master_Weather.sendCommand(OFF) } } end
Nun folgt einer der wichtigsten Teile der Beregnung, die Berechnung des Scale Factors nach der Zimmermann Methode von Opensprinkler. Der Scale Factor dient dazu die Laufzeit der Regner dem Wetter anzupassen.Code: Alles auswählen
rule "Update rain yesterday" when Time cron "0 59 23 * * ?" //23:59:00 then if (RainToday.state !== null) { RainYesterday.postUpdate(RainToday) } end
Beispiel: Normale Laufzeit eines Regners sind 15Min.(100%). Wenn nun der Scale Factor bei 115% liegt, läuft der Regner 17,25Min.
Hier wird die Startzeit gesetzt, die man via Sitemap eingegeben hat.Code: Alles auswählen
rule "Calculate irrigation scale factor" when Time cron "35 0/15 * * * ?" //alle 15Min und 15sek then // die Durchschnittswerte der letzten 24 Stunden via persistence ermitteln // Luftfeuchtigkeit var Number averageHumidity = 30.0 averageHumidity = Humidity.averageSince(now.minusHours(24), "influxdb") // Temperatur var Number averageTemp = 20.0 averageTemp = Temperature.averageSince(now.minusHours(24), "influxdb") // Regen var Number rainToday = 0 rainToday = RainToday.state var Number rainYesterday = 0 if (RainYesterday.historicState(now.withTimeAtStartOfDay, "influxdb") !== null) { rainYesterday = RainYesterday.historicState(now.withTimeAtStartOfDay, "influxdb").state as DecimalType } // Berechnung der verschiedenen Skalierungsfaktoren var Number humidityFactor = (30.0 - averageHumidity) * 1 var Number tempFactor = (averageTemp - 21.0) * 4 var Number rainFactor = (rainToday * -10.0) + (rainYesterday * -6.0) // Berechnung des Gesamtskalenfaktors var Number scaleFactor = (100 + humidityFactor + tempFactor + rainFactor) // apply limits (0 to 200%) if (scaleFactor < 0) scaleFactor = 0 else if (scaleFactor > 200) scaleFactor = 200 // Update veröffentlichen, damit die Bewässerungsregeln es verwenden können. ABBeregnung_Scale_Factor.postUpdate(scaleFactor.intValue) // die berechneten Werte protokollieren logInfo(filename,"Beregnung: Scale factor parameters: avgHumidity=" + String::format("%.2f", averageHumidity.floatValue) + ", avgTemp=" + String::format("%.2f", averageTemp.floatValue) + ", rainToday=" + String::format("%.1f", rainToday.floatValue) + ", rainYesterday=" + String::format("%.1f", rainYesterday.floatValue)) logInfo(filename,"Beregnung: Calculated scale factor is " + scaleFactor.intValue + "% (humidity=" + String::format("%.2f", humidityFactor.floatValue) + ", temp=" + String::format("%.2f", tempFactor.floatValue) + ", rain=" + String::format("%.2f", rainFactor.floatValue) + ")") end
Jetzt kommt das Herzstück der automatischen Beregnung. Hier werden die Faktoren aktivierte oder deaktivierte Beregnung, Wochentag, Automower, Wind, Regen und Scale Factor berücksichtigt.Code: Alles auswählen
rule "Set Program A Startime" when Item ProgramA_StartTime_Minutes received update or Item ProgramA_StartTime_Hours received update then if (ProgramA_StartTime_Minutes.state == 60){ ProgramA_StartTime_Minutes.sendCommand(0) } if (ProgramA_StartTime_Hours.state == 24){ ProgramA_StartTime_Hours.sendCommand(0) } var int minutes = (ProgramA_StartTime_Minutes.state as DecimalType).intValue() var int hours = (ProgramA_StartTime_Hours.state as DecimalType).intValue() // Zeitpunkt des Programmstarts festlegen var DateTime startTime = parse(now.getYear() + "-" + now.getMonthOfYear() + "-" + now.getDayOfMonth() + "T" + hours + ":" + minutes) // update der Startzeit in der für Rules und Anzeige ProgramA_StartTime.sendCommand(String::format("%02d:%02d", startTime.getHourOfDay(), startTime.getMinuteOfHour())) end
Da man von Zeit zu Zeit ja auch mal manuell beregnen möchte, folgen hier die manuellen Rules unter Berücksichtigung der entpsrechenden Laufzeiten für die einzelnen Segmente.Code: Alles auswählen
rule "Automatic Irrigation" when Item ProgramA_Master received update ON or Time cron "15 30 5 ? * * *" then var dayOfWeekSetting = newArrayList( Monday_ProgramA.state, Tuesday_ProgramA.state, Wednesday_ProgramA.state, Thursday_ProgramA.state, Friday_ProgramA.state, Saturday_ProgramA.state, Sunday_ProgramA.state ) if (dayOfWeekSetting.get(now.getDayOfWeek-1) == OFF){ ProgramA_Master_DayofWeek.sendCommand(OFF) return } else { ProgramA_Master_DayofWeek.sendCommand(ON) } if (ABBeregnung_Disable.state == ON) { //Das gesamte Bewässerungssystem ist deaktiviert. logInfo(filename,"Beregnung: Gesamte Beregnung deaktiviert!") return } if (ProgramA_Master_Weather.state == ON) { //Regen im Forecast. logInfo(filename,"Beregnung: Es hat geregnet oder Regen im Forecast") return } if (ABBeregnung_Scale_Factor.state < 10) { //Scale Factor ist kleiner 10%..keine Beregnung nötig logDebug(filename,"Beregnung: Der Boden ist feucht genug, Beregung nicht notwendig") return } if (ProgramA_Master.state == ON) { logInfo(filename,"Beregnung: Programm A wird geladen") // liefert den Skalierungsfaktor - wird verwendet, um die Laufzeiten zu reduzieren var Number scaleFactor = ABBeregnung_Scale_Factor.state as DecimalType logInfo(filename,"Beregnung: Skalierungsfaktor " + scaleFactor) // Startzeit in eine joda.time.DateTime für heute umwandeln var int minutes = (ProgramA_StartTime_Minutes.state as DecimalType).intValue() var int hours = (ProgramA_StartTime_Hours.state as DecimalType).intValue() var DateTime startTime = parse(now.getYear() + "-" + now.getMonthOfYear() + "-" + now.getDayOfMonth() + "T" + hours + ":" + minutes) logInfo(filename,"Beregnung: Startzeit Programm A: " + startTime) var DateTime endTime sendPushoverMessage(pushoverBuilder("Das Wetter sieht gut aus und die Beregnung wird für " + hours + ":" + minutes + " eingeplant")) // liefert die Rohlaufzeiten für jede Zone (in mins) var Number MGV1Mins = ABBeregnungMGV1_Duration_A.state as DecimalType var Number MGV2Mins = ABBeregnungMGV2_Duration_A.state as DecimalType var Number MGV3Mins = ABBeregnungMGV3_Duration_A.state as DecimalType // in die tatsächlichen Laufzeiten umrechnen (durch Anwendung des Skalierungsfaktors) var int MGV1Time = ((MGV1Mins * scaleFactor) / 100).intValue var int MGV2Time = ((MGV2Mins * scaleFactor) / 100).intValue var int MGV3Time = ((MGV3Mins * scaleFactor) / 100).intValue // jede Zone nacheinander einschalten (mit einem Abstand von einer Minute zwischen jeder Zonenaktivierung) if (startTime.isAfter(now)){ if (MGV1Time > 0) { endTime = startTime.plusMinutes(MGV1Time) MGV1StartTimer = createTimer(startTime) [| //Prüfen ob der Automower in der Ladestation ist (laden oder warten) if (Automower_StatusCode.state != 1014 && Automower_StatusCode.state != 1056 && Automower_StatusCode.state != 1016) { logInfo(filename,"Beregnung: Automower fährt noch! Timer werden gestoppt.") sendPushoverMessage(pushoverBuilder("Automower fährt noch! Timer werden gestoppt.")) MGV1StartTimer.cancel MGV1StartTimer = null MGV1StopTimer.cancel MGV1StopTimer = null } if ((WindSpeed.state as QuantityType<Number>).doubleValue >= 4) { //Prüfen der Windgeschwindigkeit logInfo(filename,"Beregnung: Derzeit ist es zu windig! Timer werden gestoppt.") sendPushoverMessage(pushoverBuilder("Derzeit zu windig! Timer werden gestoppt.")) MGV1StartTimer.cancel MGV1StartTimer = null MGV1StopTimer.cancel MGV1StopTimer = null } else { ABBeregnungMGV1.sendCommand(ON) ABBeregnungMGV1_State.postUpdate(ON) } ] MGV1StopTimer = createTimer(endTime) [| ABBeregnungMGV1.sendCommand(OFF) ABBeregnungMGV1_State.postUpdate(OFF) ABBeregnungMGV1_LastRun.postUpdate(new DateTimeType()) ] logInfo(filename,"Beregnung: Beregnung für Segment (vorne) gestartet um ["+ startTime +"] und endet ["+ endTime +"]") startTime = endTime.plusMinutes(1) } if (MGV2Time > 0) { endTime = startTime.plusMinutes(MGV2Time) MGV2StartTimer = createTimer(startTime) [| //Prüfen ob der Automower in der Ladestation ist (laden oder warten) if (Automower_StatusCode.state != 1014 && Automower_StatusCode.state != 1056 && Automower_StatusCode.state != 1016) { logInfo(filename,"Beregnung: Automower fährt noch! Timer werden gestoppt.") MGV2StartTimer.cancel MGV2StartTimer = null MGV2StopTimer.cancel MGV3StopTimer = null } if ((WindSpeed.state as QuantityType<Number>).doubleValue >= 4) { //Prüfen der Windgeschwindigkeit logInfo(filename,"Beregnung: Derzeit ist es zu windig! Timer werden gestoppt.") sendPushoverMessage(pushoverBuilder("Derzeit zu windig! Timer werden gestoppt.")) MGV1StartTimer.cancel MGV1StartTimer = null MGV1StopTimer.cancel MGV1StopTimer = null } else { ABBeregnungMGV2.sendCommand(ON) ABBeregnungMGV2_State.postUpdate(ON) } ] MGV2StopTimer = createTimer(endTime) [| ABBeregnungMGV2.sendCommand(OFF) ABBeregnungMGV2_State.postUpdate(OFF) ABBeregnungMGV2_LastRun.postUpdate(new DateTimeType()) ] logInfo(filename,"Beregnung: Beregnung für Segment (mitte) gestartet um ["+ startTime +"] und endet ["+ endTime +"]") startTime = endTime.plusMinutes(1) } if (MGV3Time > 0) { endTime = startTime.plusMinutes(MGV3Time) MGV3StartTimer = createTimer(startTime) [| //Prüfen ob der Automower in der Ladestation ist (laden oder warten) if (Automower_StatusCode.state != 1014 && Automower_StatusCode.state != 1056 && Automower_StatusCode.state != 1016) { logInfo(filename,"Beregnung: Automower fährt noch! Timer werden gestoppt.") MGV3StartTimer.cancel MGV3StartTimer = null MGV3StopTimer.cancel MGV3StopTimer = null } if ((WindSpeed.state as QuantityType<Number>).doubleValue >= 4) { //Prüfen der Windgeschwindigkeit logInfo(filename,"Beregnung: Derzeit ist es zu windig! Timer werden gestoppt.") sendPushoverMessage(pushoverBuilder("Derzeit zu windig! Timer werden gestoppt.")) MGV1StartTimer.cancel MGV1StartTimer = null MGV1StopTimer.cancel MGV1StopTimer = null } else { ABBeregnungMGV3.sendCommand(ON) ABBeregnungMGV3_State.postUpdate(ON) } ] MGV3StopTimer = createTimer(endTime) [| ABBeregnungMGV3.sendCommand(OFF) ABBeregnungMGV3_State.postUpdate(OFF) ABBeregnungMGV3_LastRun.postUpdate(new DateTimeType()) ] logInfo(filename,"Beregnung: Beregnung für Segment (hinten) gestartet um ["+ startTime +"] und endet ["+ endTime +"]") startTime = endTime.plusMinutes(1) } } else { logInfo(filename,"Beregnung: Startzeit liegt in der Vergangenheit") } } else { logInfo(filename,"Beregnung: Programm A nicht ausgeführt, Master Switch deaktiviert.") sendPushoverMessage(pushoverBuilder("Bewässerungsprogramm A ist deaktiviert, es wird heute keine Bewässerung eingeplant")) } end
Seppy sagt mir, dass das Ganze nicht ohne einen "Watchdog" laufen sollte...es sei denn man möchte einen Sumpf anlegenCode: Alles auswählen
rule "MGV1 manual Irrigation" when Item ABBeregnungMGV1_State received command then if (ABBeregnung_Disable.state == ON) { //Das gesamte Bewässerungssystem ist deaktiviert logInfo(filename,"Beregnung: Gesamte Beregnung deaktiviert!") return } if (receivedCommand == ON) { if (IrrigationTimer === null){ logInfo(filename,"Beregnung: Beregnung für \"Beregnungssegment (vorne)\" manuell aktiviert, starte Timer") IrrigationTimer = createTimer(now.plusMinutes(Integer::parseInt(ABBeregnungMGV1_Duration_A.state.toString))) [| ABBeregnungMGV1_State.sendCommand(OFF) ABBeregnungMGV1_LastRun.postUpdate(new DateTimeType()) logInfo(filename,"Beregnung: Manuelle Bewässerung für \"Beregnungssegment (vorne)\" beendet") sendPushoverMessage(pushoverBuilder("Manuelle Bewässerung für \"Beregnungssegment (vorne)\" nach einer Laufzeit von " + ABBeregnungMGV1_Duration_A.state.toString + " Minuten beendet")) IrrigationTimer = null ] } ABBeregnungMGV1.sendCommand(ON) logInfo(filename,"Beregnung: Magnetventil \"Beregnungssegment (vorne)\" geschaltet [ON]") } else { ABBeregnungMGV1.sendCommand(OFF) ABBeregnungMGV1_LastRun.postUpdate(new DateTimeType()) if (IrrigationTimer !== null){ IrrigationTimer.cancel() IrrigationTimer = null } logInfo(filename,"Beregnung: Magnetventil \"Beregnungssegment (vorne)\" geschaltet [OFF]") } end rule "MGV2 manual Irrigation" when Item ABBeregnungMGV2_State received command then if (ABBeregnung_Disable.state == ON) { //Das gesamte Bewässerungssystem ist deaktiviert logInfo(filename,"Beregnung: Gesamte Beregnung deaktiviert!") return } if (receivedCommand == ON) { if (IrrigationTimer === null){ logInfo(filename,"Beregnung: Beregnung für \"Beregnungssegment (mitte)\" manuell aktiviert, starte Timer") IrrigationTimer = createTimer(now.plusMinutes(Integer::parseInt(ABBeregnungMGV2_Duration_A.state.toString))) [| ABBeregnungMGV2_State.sendCommand(OFF) ABBeregnungMGV2_LastRun.postUpdate(new DateTimeType()) logInfo(filename,"Beregnung: Manuelle Bewässerung für \"Beregnungssegment (mitte)\" beendet") sendPushoverMessage(pushoverBuilder("Manuelle Bewässerung für \"Beregnungssegment (mitte)\" nach einer Laufzeit von " + ABBeregnungMGV2_Duration_A.state.toString + " Minuten beendet")) IrrigationTimer = null ] } ABBeregnungMGV2.sendCommand(ON) logInfo(filename,"Beregnung: Magnetventil \"Beregnungssegment (mitte)\" geschaltet [ON]") } else { ABBeregnungMGV2.sendCommand(OFF) ABBeregnungMGV2_LastRun.postUpdate(new DateTimeType()) if (IrrigationTimer !== null){ IrrigationTimer.cancel() IrrigationTimer = null } logInfo(filename,"Beregnung: Magnetventil \"Beregnungssegment (mitte)\" geschaltet [OFF]") } end rule "MGV3 manual Irrigation" when Item ABBeregnungMGV3_State received command then if (ABBeregnung_Disable.state == ON) { //Das gesamte Bewässerungssystem ist deaktiviert logInfo(filename,"Beregnung: Gesamte Beregnung deaktiviert!") return } if (receivedCommand == ON) { if (IrrigationTimer === null){ logInfo(filename,"Beregnung: Beregnung für \"Beregnungssegment (hinten)\" manuell aktiviert, starte Timer") IrrigationTimer = createTimer(now.plusMinutes(Integer::parseInt(ABBeregnungMGV3_Duration_A.state.toString))) [| ABBeregnungMGV3_State.sendCommand(OFF) ABBeregnungMGV3_LastRun.postUpdate(new DateTimeType()) logInfo(filename,"Beregnung: Manuelle Bewässerung für \"Beregnungssegment (hinten)\" beendet") sendPushoverMessage(pushoverBuilder("Manuelle Bewässerung für \"Beregnungssegment (hinten)\" nach einer Laufzeit von " + ABBeregnungMGV3_Duration_A.state.toString + " Minuten beendet")) IrrigationTimer = null ] } ABBeregnungMGV3.sendCommand(ON) logInfo(filename,"Beregnung: Magnetventil \"Beregnungssegment (hinten)\" geschaltet [ON]") } else { ABBeregnungMGV3.sendCommand(OFF) ABBeregnungMGV3_LastRun.postUpdate(new DateTimeType()) if (IrrigationTimer !== null){ IrrigationTimer.cancel() IrrigationTimer = null } logInfo(filename,"Beregnung: Magnetventil \"Beregnungssegment (hinten)\" geschaltet [OFF]") } end
Der Watchdog schaut alle 15Min. nach, ob ein Magnetventil fälschlicherweise geöffnet ist
Zum guter letzt möchte man eine laufende Beregnung ggf. mal abbrechen. Dazu dient diese Rule.Code: Alles auswählen
rule "Irrigation Watchdog" when Time cron "0 0/15 5-23 * * ?" then if (ABBeregnung_Disable.state == ON) { //Das gesamte Bewässerungssystem ist deaktiviert gABBeregnung?.allMembers.filter(x | x.state != OFF).forEach[ item | logInfo(filename,"Beregnung: Beregnung wird deaktiviert") item.sendCommand(OFF) ] return } if (ABBeregnungMGV1.state == ON && ABBeregnungMGV1_State.state == OFF){ ABBeregnungMGV1.sendCommand(OFF) logInfo(filename,"Beregnung: MGV1 per Watchdog abgeschaltet") } else if (ABBeregnungMGV2.state == ON && ABBeregnungMGV2_State.state == OFF){ ABBeregnungMGV2.sendCommand(OFF) logInfo(filename,"Beregnung: MGV2 per Watchdog abgeschaltet") } else if (ABBeregnungMGV3.state == ON && ABBeregnungMGV3_State.state == OFF){ ABBeregnungMGV3.sendCommand(OFF) logInfo(filename,"Beregnung: MGV3 per Watchdog abgeschaltet") } end
So, ich weiß, das ist erstmal ne Menge Holz, aber ich habe versucht im Code viele Kommentare zur Erklärung einzufügen.Code: Alles auswählen
rule "Abort Irrigation" when Item ABBeregnung_Disable received update ON then // Beregnung abbrechen, wenn sie gestartet wurde if (MGV1StartTimer !== null) { MGV1StartTimer.cancel MGV1StartTimer = null logInfo(filename, "Beregnung: MGV1StartTimer gestoped") } if (MGV1StopTimer !== null) { MGV1StopTimer.cancel MGV1StopTimer = null logInfo(filename, "Beregnung: MGV1StopTimer gestoped") } if (MGV2StartTimer !== null) { MGV2StartTimer.cancel MGV2StartTimer = null logInfo(filename, "Beregnung: MGV2StartTimer gestoped") } if (MGV2StopTimer !== null) { MGV2StopTimer.cancel MGV2StopTimer = null logInfo(filename, "Beregnung: MGV2StopTimer gestoped") } if (MGV3StartTimer !== null) { MGV3StartTimer.cancel MGV3StartTimer = null logInfo(filename, "Beregnung: MGV3StartTimer gestoped") } if (MGV3StopTimer !== null) { MGV3StopTimer.cancel MGV3StopTimer = null logInfo(filename, "Beregnung: MGV3StopTimer gestoped") } /* if(WateringStopTimer !== null) { WateringStopTimer.cancel WateringStopTimer = null logInfo(filename, "Watering_starting/stoping: WateringStopTimer stoped") } */ ABBeregnungMGV1_State.sendCommand(OFF) ABBeregnungMGV2_State.sendCommand(OFF) ABBeregnungMGV3_State.sendCommand(OFF) end
Natürlich ist das hier nicht alles auf meinem Mist gewachsen und deshalb möchte ich mich bei folgenden Leuten bedanken:
Seppy, Alexander H., ben_jones, udo1toni, Michal_Szymanski, Spilota und Joshua A,
Hoffe wie immer hilft es dem einen oder anderen von Euch weiter und bin für Verbesserungsvorschläge immer offen
CYA
Cyrelian
ich habe eine Frage zum Item ProgramA_ScaleFactor. Wozu/wann wird der benutzt? Der Scale-Faktor wird doch in ABBeregnung_Scale_Factor berechnet und in den Regeln benutzt. Wozu dann noch der ProgramA_ScaleFactor?
Viele Grüße,
Jörg
- Cyrelian
- Beiträge: 601
- Registriert: 24. Sep 2015 17:55
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Hi Jörg,
ProgramA_ScaleFactor wir derzeit nicht genutzt. Es gab mal die Überlegung hier einen Wert manuell zu übergeben. Habe das aber verworfen.
CU
Cyrelian
ProgramA_ScaleFactor wir derzeit nicht genutzt. Es gab mal die Überlegung hier einen Wert manuell zu übergeben. Habe das aber verworfen.
CU
Cyrelian
-
- Beiträge: 6
- Registriert: 23. Jul 2018 13:02
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Auch von mir an Dankeschön an Cyrelian für die Vorstellung des Beregnungs-Projektes sowie allen anderen die hier hilfreiche Infos geliefert haben!
@Cyrelian:
Ist das Ziel in der Rule "Irrigation Watchdog" nicht möglichst alle fälschlicherweise geöffneten Ventile auf einen Schlag zu schließen?
Deine If\ElseIf Bedingung verhindert dies allerdings und somit dauert es 45 Minuten bis alle drei Ventile geschlossen werden.
@Cyrelian:
Ist das Ziel in der Rule "Irrigation Watchdog" nicht möglichst alle fälschlicherweise geöffneten Ventile auf einen Schlag zu schließen?
Deine If\ElseIf Bedingung verhindert dies allerdings und somit dauert es 45 Minuten bis alle drei Ventile geschlossen werden.
- Cyrelian
- Beiträge: 601
- Registriert: 24. Sep 2015 17:55
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Hi DonGyros,DonGyros hat geschrieben: ↑22. Jul 2020 12:27 Auch von mir an Dankeschön an Cyrelian für die Vorstellung des Beregnungs-Projektes sowie allen anderen die hier hilfreiche Infos geliefert haben!
@Cyrelian:
Ist das Ziel in der Rule "Irrigation Watchdog" nicht möglichst alle fälschlicherweise geöffneten Ventile auf einen Schlag zu schließen?
Deine If\ElseIf Bedingung verhindert dies allerdings und somit dauert es 45 Minuten bis alle drei Ventile geschlossen werden.
ja, das Ziel in der Rule "Irrigation Watchdog" ist alle fälschlicherweise geöffneten Ventile zu schließen.
Von der Logik her hast Du vollkommen Recht, dass es 45 Minuten dauern würde bis alle drei Ventile geschlossen werden.....ABER
Der Sonoff 4CH Pro R2 läuft im "interlock modus". Das heißt, es kann immer nur ein Channel/Ventil geschaltet werden. Bedeutet also für die Rule, dass entweder ABBeregnungMGV1 oder ABBeregnungMGV2 oder ABBeregnungMGV3 "ON" ist und somit die Rule im ersten Lauf das offene Ventil dicht macht.
Geht bestimmt auch schöner...funktioniert aber .
CU
Cyrelian
-
- Beiträge: 6
- Registriert: 23. Jul 2018 13:02
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
Ah ok, das mit dem Interlock Mode hatte ich nicht gesehen. Dann ergibt das wieder Sinn
Noch eine Frage zum Inching Mode, kann man hier wirklich nur eine Range von 1 Sekunde -16 Sekunden einstellen?
Wenn man längere Zeiträume einstellen könnte wäre das ja ein perfekter Sicherheitsmechanismus um zu verhindern das der Garten voll läuft falls man z.B im Eifer des Gefechtes einen Logikfehler in die entsprechenden Rules gebaut hat bzw. die openHab Hardware abraucht usw..
Noch eine Frage zum Inching Mode, kann man hier wirklich nur eine Range von 1 Sekunde -16 Sekunden einstellen?
Wenn man längere Zeiträume einstellen könnte wäre das ja ein perfekter Sicherheitsmechanismus um zu verhindern das der Garten voll läuft falls man z.B im Eifer des Gefechtes einen Logikfehler in die entsprechenden Rules gebaut hat bzw. die openHab Hardware abraucht usw..
- udo1toni
- Beiträge: 13951
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff
An dieser Stelle wäre es ja das einfachste, auf das Wort else zu verzichten
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet
- Cyrelian
- Beiträge: 601
- Registriert: 24. Sep 2015 17:55