Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Benutzeravatar
Romel
Beiträge: 42
Registriert: 21. Mai 2020 15:32

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von Romel »

Ich hab es nach dieser Beschreibung gemacht:
https://youtu.be/Cx0xujk_x9o

Benutzeravatar
udo1toni
Beiträge: 13948
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von udo1toni »

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?
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Benutzeravatar
Romel
Beiträge: 42
Registriert: 21. Mai 2020 15:32

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von Romel »

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.

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

JoergB
Beiträge: 3
Registriert: 16. Jan 2019 08:32

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von JoergB »

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 :mrgreen:
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 :D

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

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)
RULES:

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.

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

Nach einem Systemneustart, wird geprüft ob ggf. noch Magnetventile offen sind und werden entsprechend geschlossen.

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
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 "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
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 "Update rain yesterday"
when
   		Time cron "0 59 23 * * ?" //23:59:00
then
	if (RainToday.state !== null)
	{
		RainYesterday.postUpdate(RainToday)
	}
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.
Beispiel: Normale Laufzeit eines Regners sind 15Min.(100%). Wenn nun der Scale Factor bei 115% liegt, läuft der Regner 17,25Min.

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
Hier wird die Startzeit gesetzt, die man via Sitemap eingegeben hat.

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
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 "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
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 "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
Seppy sagt mir, dass das Ganze nicht ohne einen "Watchdog" laufen sollte...es sei denn man möchte einen Sumpf anlegen :mrgreen:
Der Watchdog schaut alle 15Min. nach, ob ein Magnetventil fälschlicherweise geöffnet ist

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
Zum guter letzt möchte man eine laufende Beregnung ggf. mal abbrechen. Dazu dient diese Rule.

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
So, ich weiß, das ist erstmal ne Menge Holz, aber ich habe versucht im Code viele Kommentare zur Erklärung einzufügen.
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
Hallo 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

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von Cyrelian »

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

DonGyros
Beiträge: 6
Registriert: 23. Jul 2018 13:02

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von DonGyros »

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.

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von Cyrelian »

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.
Hi DonGyros,

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 :mrgreen:
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

DonGyros
Beiträge: 6
Registriert: 23. Jul 2018 13:02

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von DonGyros »

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..

Benutzeravatar
udo1toni
Beiträge: 13948
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von udo1toni »

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

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

Re: Automatisch Gartenbewässerung / Beregnung mit openHAB und Sonoff

Beitrag von Cyrelian »

udo1toni hat geschrieben: 23. Jul 2020 09:46 An dieser Stelle wäre es ja das einfachste, auf das Wort else zu verzichten ;)
Habs mal angepasst ;)

Gesperrt