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

Gesperrt
Pepe1907
Beiträge: 167
Registriert: 1. Jun 2020 17:29
Answers: 2

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

Beitrag von Pepe1907 »

Vielen Dank für die schnellen und hilfreichen Antworten.
Jetzt habe ich nur noch das Problem meine Pumpe die auch über openhab gesteuert werden soll, in die Rule hineinzubekommen.
Die Pumpe hat den Item Namen channel4, welchen ich natürlich ändern kann.
Es ist für einen Schlosser, der seinen Vater helfen möchte schwerer als gedacht. Respekt vor euren grandiosen Arbeit und eurer Hilfe :D

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

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

Beitrag von udo1toni »

Am einfachsten kannst Du die Pumpe vor dem Starten des Timers einschalten. Das Ausschalten erledigst Du entsprechend wenn der Timercode den letzten Regner deaktiviert hat, also an der Stelle, wo auch Sperre.postUpdate(OFF) gesendet wird.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Pepe1907
Beiträge: 167
Registriert: 1. Jun 2020 17:29
Answers: 2

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

Beitrag von Pepe1907 »

Also müsste es dann so aussehen?


beregnung.items

Code: Alles auswählen

Switch Sperre // nur für visibility...
Group gRegner "Alle Regneritems"
Switch Regner_Power_001      "Regner hinten [%s]" (gRegner) { gpio="pin26 activelow:no" }
Switch Regner_Power_002      "Regner vorne  [%s]" (gRegner) { gpio="pin19 activelow:no" }
Switch Regner_Power_003      "Regner Straße [%s]" (gRegner) { gpio="pin13 activelow:no" }

Switch Regner_Sperre_001     "Regner hinten [MAP(enable.map):%s]" (gRegner) // ungebundenes Item
Switch Regner_Sperre_002     "Regner vorne  [MAP(enable.map):%s]" (gRegner) // ungebundenes Item
Switch Regner_Sperre_003     "Regner Straße [MAP(enable.map):%s]" (gRegner) // ungebundenes Item

Number Regner_Dauer_001      "Regner hinten [%d min]" <time> (gRegner) // ungebundenes Item
Number Regner_Dauer_002      "Regner vorne  [%d min]" <time> (gRegner) // ungebundenes Item
Number Regner_Dauer_003      "Regner Straße [%d min]" <time> (gRegner) // ungebundenes Item

//Pumpe
Switch brunnenpumpe         "Brunnenpumpe"                { gpio="pin6 activelow:no "}

Code: Alles auswählen

// globale Variablen immer zu Beginn der Datei definieren!

var Timer tRegner = null
var int iRegner = 0

rule "Beregnung"
when
    Item Beregnung received command ON
then
    logInfo("watering","Beregnung gestartet.")
    if(tRegner !== null) {
        logInfo("watering","Regner scheint noch zu laufen! Abbruch")
        return;
    }
    iRegner = 0
    Sperre.postUpdate(ON)
    brunnenpumpe.sendCommand(ON)
    tRegner = createTimer(now.plusMillis(10),[|
        iRegner++                                // nächsten Regener anwählen
        logInfo("regner","{}. Durchlauf",iRegner)
        gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)] // alle Regner abschalten
        val maxRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].size             // wieviele Regner sollen insgesamt beregnen?
        logInfo("regner","{}. Durchlauf von {} Durchläufen.",iRegner,maxRegner)
        if(iRegner > maxRegner) {                // letzten Regner schon erreicht?
            logInfo("regner","Alle Regner sind schon gelaufen!")
            tRegner = null                       // Dann Schluss!
            Sperre.postUpdate(OFF)
            return;
        }
        Thread::sleep(500)                       // kleine(!) Pause einlegen
        val strRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].sortBy[name].get(iRegner-1).name.split("_").get(2) //Namen des Regner ermitteln
        logInfo("regner","Nächster Regner: {}",strRegner)
        gRegner.members.filter[i|i.name.contains("Power") && i.name.contains(strRegner)].head.sendCommand(ON)  // Regner einschalten
        val Dauer =(gRegner.members.filter[i|i.name.contains("60") && i.name.contains(strRegner)].head.state as Number).intValue
        logInfo("regner","Regenr wird nach {60} Minuten wieder abgeschaltet.")
        tRegner.reschedule(now.plusMinutes(1)) // Nächste Ausführung planen
        brunnenpumpe.sendCommand(OFF)
    ])
end
Nur wie bekomme ich jezt noch den zweiten und dritten Regnerkreis auf jeweils andere Dauer eingestellt?
Wie implentiere ich die Wetterdaten( nutze das Openweathermap Binding)?
Desweiteren eine startuhrzeit setzen.
Bin auch gerne bereit fürs Forum etwas zu spenden da meine Fragen bzw die Erfüllung meiner "Anforderungen" sehr mühsam sind.
Hoffe dennoch auf Verständnis

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

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

Beitrag von Romel »

Hallo,

Ich hab mal versucht Startzeit und Wochentag einzubinden.
Wochentag ist mir gelungen aber bei der Zeit stecke ich fest. :)

Code: Alles auswählen

var Timer tRegner = null
var int iRegner = 0

rule "Beregnung AUS"
when 
    Item Beregnung received command OFF or
    System started
then
    logInfo("watering","Beregnung wird abgebrochen!")
    tRegner?.cancel
    tRegner = null
    gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)] // alle Regner abschalten
    Sperre.postUpdate(OFF)
end

rule "Startzeit einstellen"
when
    Item Startzeit_Minuten received update or
    Item Startzeit_Stunden received update
then
	if (Startzeit_Minuten.state == 60){
		Startzeit_Minuten.sendCommand(0)
	}
	if (Startzeit_Stunden.state == 24){
		Startzeit_Stunden.sendCommand(0)
	}
    var int minutes = (Startzeit_Minuten.state as DecimalType).intValue()
    var int hours = (Startzeit_Stunden.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  
    Startzeit.sendCommand(String::format("%02d:%02d", startTime.getHourOfDay(), startTime.getMinuteOfHour()))
end

rule "Wochentage"
when
    Item Beregnung received update ON
then
    logInfo("watering","Kontrolliere Wochentag")
   var dayOfWeekSetting = newArrayList(
		Monday.state, 
		Tuesday.state, 
		Wednesday.state, 
		Thursday.state, 
		Friday.state, 
		Saturday.state, 
		Sunday.state
	)
    if (dayOfWeekSetting.get(now.getDayOfWeek-1) == OFF)
        {
        Beregnung.sendCommand(OFF)
        tRegner = null
        gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)] // alle Regner abschalten
        Sperre.postUpdate(OFF)
        logInfo("watering","Wochentag ist AUS, Abbruch Beregnung")
    	return;
        } 
    else 
        {
		Beregnung_Zeit.sendCommand(ON)
        logInfo("watering","Wochentag ist EIN")
        }
end 

rule "Startzeit freigeben"
when 
    Item Beregnung_Zeit received command ON
then 
     // Startzeit in eine joda.time.DateTime für heute umwandeln
        var int minutes = (Startzeit_Minuten.state as DecimalType).intValue()
		var int hours = (Startzeit_Stunden.state as DecimalType).intValue()
		var DateTime startTime = parse(now.getYear() + "-" + now.getMonthOfYear() + "-" + now.getDayOfMonth() + "T" + hours + ":" + minutes)
        logInfo("watering","Beregnung: " + startTime)
        var DateTime endTime    
    if (startTime.isAfter(now))
            {
            endTime = startTime.plusMinutes
            }
            else 
            {
            Beregnung_Wochentag.sendCommand(ON)
            }
            }  
end 

rule "Beregnung EIN"
when
    Item Beregnung_Wochentag received command ON
then
    logInfo("watering","Beregnung gestartet.")
    if(tRegner !== null) {
        logInfo("watering","Regner scheint noch zu laufen! Abbruch")
        return;
    }
    iRegner = 0
    Sperre.postUpdate(ON)
    tRegner = createTimer(now.plusMillis(10),[|
        iRegner++                                // nächsten Regener anwählen
        logInfo("regner","{}. Durchlauf",iRegner)
        gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)] // alle Regner abschalten
        val maxRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].size             // wieviele Regner sollen insgesamt beregnen?
        logInfo("regner","{}. Durchlauf von {} Durchläufen.",iRegner,maxRegner)
        if(iRegner > maxRegner) {                // letzten Regner schon erreicht?
            logInfo("regner","Alle Regner sind schon gelaufen!")
            tRegner = null                       // Dann Schluss!
            Sperre.postUpdate(OFF)
            return;
        }
        Thread::sleep(500)                       // kleine(!) Pause einlegen
        val strRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].sortBy[name].get(iRegner-1).name.split("_").get(2) //Namen des Regner ermitteln
        logInfo("regner","Nächster Regner: {}",strRegner)
        gRegner.members.filter[i|i.name.contains("Power") && i.name.contains(strRegner)].head.sendCommand(ON)  // Regner einschalten
        val Dauer =(gRegner.members.filter[i|i.name.contains("Dauer") && i.name.contains(strRegner)].head.state as Number).intValue
        logInfo("regner","Regenr wird nach {} Minuten wieder abgeschaltet.",Dauer)
        tRegner.reschedule(now.plusMinutes(Dauer)) // Nächste Ausführung planen
    ])
end
Danke im voraus für die Hilfe.

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

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

Beitrag von udo1toni »

Du denkst zu kompliziert ;)

Im Grunde reichen zwei Rules (um die beiden Funktionen Zeitsteuerung und Beregnung zu trennen).
Damit die Beregnung automatisch zur eingestellten Zeit startet, muss openHAB bei Bedarf einen Timer starten. Sinnvollerweise wird das täglich geprüft. Die Rule "Startzeit einstellen" kümmert sich um Zeit und Wochentage. Damit die Rule bei Änderungen am Wochentag triggert, müssen alle Wochentag-Items in der Gruppe gWeekdays zusammengefasst werden. Die Rule triggert bei einer Änderung an einem der Wochentage, der Startminuten oder Startstunden und täglich um Mitternacht. Da jeder Timer eine gewisse Zeit braucht, bis er soweit ist, ist eine Startzeit um 00:00 Uhr nicht möglich, aber das sollte zu verschmerzen sein.
Die Wochentag-Status werden im Array hinterlegt.
Danach werden die Variablen für Minuten und Stunden initialisiert und falls die Items einen gültigen Wert enthalten, werden die Variablen mit diesem Wert gefüllt. Ansonsten stehen sie auf 0.
Die Werte werden auf Ober- und Untergrenze getestet und gegebenenfalls angepasst. Abschließend wird der Wert ins Item zurückgeschrieben.
Ein Setpoint Widget in der Sitemap kann entsprechend ohne Ober- und Untergrenze definiert werden, die Eingabe springt passend um (sowohl nach oben als auch nach unten).
Die Startzeit wird als Startminute am Tag gemerkt, für später.
Nun wird ein eventuell laufender StartTimer abgebrochen.
Jetzt prüft die Rule, ob "heute" bewässert werden soll. Ist das der Fall, prüft sie, ob die eingestellte Zeit schon erreicht ist. Ist das nicht der Fall, so wird ein StartTimer angelegt, der zur gewünschten Zeit die Beregnung startet.

Die Beregnung selbst läuft wie gehabt. Ich habe lediglich Start und Stop in einer Rule zusammengefasst. Das hat den Vorteil, dass die logisch zusammengehörenden Codeteile auch örtlich zusammengefasst sind.
Ich habe auch jeweils einen Pumpen-Ein- bzw. Ausschaltbefehl eingebaut :)

Zeitauswahl und Wochentagsauswahl sollten ebenfalls gesperrt werden, analog zur Regnerauswahl. Wenn der Schalter Beregnung in die Oberfläche integriert ist, kann man einen gestarteten Beregnungsvorgang jederzeit stoppen, auch, um eine andere Startzeit zu wählen.
Wichtig ist aber, dass die Startzeit noch nicht erreicht ist, zum Testen um 15:14 muss man also 15:15 einstellen,damit der Timer genug Zeit zur Steuerung hat.

Code: Alles auswählen

var Timer tRegner = null
var int iRegner = 0
var Timer tStartRegner = null

rule "Startzeit einstellen"
when
    Member of gWeekdays changed or                                                                                         // Wochentag geändert
    Item Startzeit_Minuten changed or                                                                                      // Minuten geändert
    Item Startzeit_Stunden changed or                                                                                      // Stunden geändert
    Time cron "1 0 0 * * ?"                                                                                                // täglich um 00:00:01 Uhr
then
                                         // Alle Wochentag-Items müssen in der Gruppe gWeekdays zusammengefasst sein, damit der Trigger oben funktioniert
    var dayOfWeekSetting = newArrayList(
        Monday.state, 
        Tuesday.state, 
        Wednesday.state, 
        Thursday.state, 
        Friday.state, 
        Saturday.state, 
        Sunday.state
    )
    var int minutes = 0                                                                                     // Initialwert für Minuten definieren
    if(Startzeit_Minuten.state instanceof Number) {                                                         // Falls das Item eine gültige Zahl enthält
        minutes = Startzeit_Minuten.state as Number                                                         // Setze minutes auf diese Zahl
        if(minutes > 59) minutes = 0                                                                        // Falls Obergrenze überschritten setze auf 0
        if(minutes < 0) minutes = 59                                                                        // Falls Untergrente unterschritten setze auf 59
    }
    Startzeit_Minuten.postUpdate(minutes)                                                                   // Schreibe Wert in das Item
    var int hours = 0                                                                                       // Initialwert für Sunden definieren
    if(Startzeit_Stunden.state instanceof Number) {                                                         // Falls das Item eine gültige Zahl enthält
        hours = Startzeit_Stunden.state as Number                                                           // Setze hours auf diese Zahl
        if(hours > 23) hours = 0                                                                            // Falls Obergrenze überschritten setze auf 0
        if(hours < 0) hours = 23                                                                            // Falls Untergrente unterschritten setze auf 23
    }
    Startzeit_Stunden.postUpdate(hours)                                                                     // Schreibe Wert in das Item
    val int startMinutes = hours * 60 + minutes                                                             // Zeit in Minuten
    logInfo("watering","Kontrolliere Wochentag")
    tStartRegner?.cancel                                                                                    // geplante Beregnung canceln
    if(dayOfWeekSetting.get(now.getDayOfWeek-1) == ON) {                                                    // Falls heute Beregnung gewünscht
        if(now.getMinuteOfDay < startMinutes) {                                                             // Falls Startzeit noch nicht erreicht
            tStartRegner = createTimer(now.withTimeAtStartOfDay.plusMinutes(startMinutes),[|                // Setze einen Timer auf gewünschte Startzeit
                Beregnung.sendCommand(ON)                                                                   // Starte zur gewünschten Zeit
            ])
        }
    }
end

rule "Beregnung An und Aus"
when
    Item Beregnung received command
then
    if(receivedCommand == OFF) {
        logInfo("watering","Beregnung wird abgebrochen!")
        tRegner?.cancel                                                                                                                                         // Timer stoppen
        tRegner = null                                                                                                                                          // Variable leeren
        gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)]                                              // alle Regner abschalten
        Pumpe.sendCommand(OFF)                                                                                                                                  // Pumpe abschalten
        Sperre.postUpdate(OFF)                                                                                                                                  // Bediensperre aufheben
    } else {
        logInfo("watering","Beregnung gestartet.")
        if(tRegner !== null) {                                                                                                                                  // falls ein Timer läuft
            logInfo("watering","Regner scheint noch zu laufen! Abbruch der Rule!")
            return;                                                                                                                                             // Abbruch
        }
        iRegner = 0                                                                                                                                             // Zähler auf 0
        Sperre.postUpdate(ON)                                                                                                                                   // Bediensperre aktivieren
        Pumpe.sendCommand(ON)                                                                                                                                   // Pumpe starten
        tRegner = createTimer(now.plusMillis(10), [|                                                                                                            // Timer anlegen
            iRegner++                                                                                                                                           // nächsten Regener anwählen
            logInfo("watering","{}. Durchlauf",iRegner)
            gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)]                                          // alle Regner abschalten
            val maxRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].size                                                  // wieviele Regner sollen insgesamt beregnen?
            logInfo("watering","{}. Durchlauf von {} Durchläufen.",iRegner,maxRegner)
            if(iRegner > maxRegner) {                                                                                                                           // letzten Regner schon erreicht?
                logInfo("watering","Alle Regner sind schon gelaufen!")
                tRegner = null                                                                                                                                  // Dann Schluss!
                Sperre.postUpdate(OFF)                                                                                                                          // Sperre deaktivieren
                Beregnung.postUpdate(OFF)                                                                                                                       // Item zurücksetzen
                Pumpe.sendCommand(OFF)                                                                                                                          // Pumpe aus
                return;                                                                                                                                         // und Timer verlassen 
            }
            Thread::sleep(500)                                                                                                                                  // kleine(!) Pause einlegen
            val strRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].sortBy[name].get(iRegner-1).name.split("_").get(2)    // Namen des Regner ermitteln
            logInfo("watering","Nächster Regner: {}",strRegner)
            gRegner.members.filter[i|i.name.contains("Power") && i.name.contains(strRegner)].head.sendCommand(ON)                                               // Regner einschalten
            val Dauer =(gRegner.members.filter[i|i.name.contains("Dauer") && i.name.contains(strRegner)].head.state as Number).intValue
            logInfo("watering","Regenr wird nach {} Minuten wieder abgeschaltet.",Dauer)
            tRegner.reschedule(now.plusMinutes(Dauer))                                                                                                          // Nächste Ausführung planen
        ])
    }
end
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

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

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

Beitrag von Romel »

Du denkst zu kompliziert ;)
Du hast recht !!! :D

Es gibt noch irgendwo einen Hacken.

Code: Alles auswählen

2020-06-03 14:24:05.461 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'Beregnung.rules'

==> /var/log/openhab2/events.log <==

2020-06-03 14:24:09.493 [ome.event.ItemCommandEvent] - Item 'Startzeit_Minuten' received command 24

2020-06-03 14:24:09.503 [vent.ItemStateChangedEvent] - Startzeit_Minuten changed from 23 to 24

2020-06-03 14:24:09.798 [ome.event.ItemCommandEvent] - Item 'Startzeit_Minuten' received command 25

2020-06-03 14:24:09.814 [vent.ItemStateChangedEvent] - Startzeit_Minuten changed from 24 to 25

==> /var/log/openhab2/openhab.log <==

2020-06-03 14:24:10.738 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Startzeit einstellen': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_greaterThan(int,int) on instance: null

2020-06-03 14:24:10.739 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Startzeit einstellen': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_greaterThan(int,int) on instance: null

==> /var/log/openhab2/events.log <==

2020-06-03 14:24:12.435 [ome.event.ItemCommandEvent] - Item 'Startzeit_Minuten' received command 26

2020-06-03 14:24:12.446 [vent.ItemStateChangedEvent] - Startzeit_Minuten changed from 25 to 26

==> /var/log/openhab2/openhab.log <==

2020-06-03 14:24:12.451 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Startzeit einstellen': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_greaterThan(int,int) on instance: null

==> /var/log/openhab2/events.log <==

2020-06-03 14:24:15.571 [ome.event.ItemCommandEvent] - Item 'Beregnung' received command ON

==> /var/log/openhab2/openhab.log <==

2020-06-03 14:24:15.578 [INFO ] [ipse.smarthome.model.script.watering] - Beregnung gestartet.

==> /var/log/openhab2/events.log <==

2020-06-03 14:24:15.582 [vent.ItemStateChangedEvent] - Beregnung changed from OFF to ON

2020-06-03 14:24:15.592 [vent.ItemStateChangedEvent] - Sperre changed from OFF to ON

==> /var/log/openhab2/openhab.log <==

2020-06-03 14:24:15.602 [INFO ] [clipse.smarthome.model.script.regner] - 1. Durchlauf

2020-06-03 14:24:15.686 [INFO ] [clipse.smarthome.model.script.regner] - 1. Durchlauf von 5 Durchläufen.

2020-06-03 14:24:16.213 [INFO ] [clipse.smarthome.model.script.regner] - Nächster Regner: 001

==> /var/log/openhab2/events.log <==

2020-06-03 14:24:16.217 [ome.event.ItemCommandEvent] - Item 'Regner_Power_001' received command ON

2020-06-03 14:24:16.225 [vent.ItemStateChangedEvent] - Regner_Power_001 changed from OFF to ON

2020-06-03 14:24:16.227 [GroupItemStateChangedEvent] - Power changed from OFF to ON through Regner_Power_001

==> /var/log/openhab2/openhab.log <==

2020-06-03 14:24:16.236 [INFO ] [clipse.smarthome.model.script.regner] - Regenr wird nach 1 Minuten wieder abgeschaltet.

==> /var/log/openhab2/events.log <==

2020-06-03 14:24:32.704 [ome.event.ItemCommandEvent] - Item 'Beregnung' received command OFF
Es hält nicht an bei der Startzeit, sondern startet die Bewässerung.

Code: Alles auswählen

var Timer tRegner = null
var int iRegner = 0
var Timer tStartRegner = null



rule "Startzeit einstellen"
when
    Member of gWeekdays changed or                                                                                         // Wochentag geändert
    Item Startzeit_Minuten changed or                                                                                      // Minuten geändert
    Item Startzeit_Stunden changed or                                                                                      // Stunden geändert
    Time cron "1 0 0 * * ?"                                                                                                // täglich um 00:00:01 Uhr
then
    // Alle Wochentag-Items müssen in der Gruppe gWeekdays zusammengefasst sein, damit der Trigger oben funktioniert
    var dayOfWeekSetting = newArrayList(
        Monday.state, 
        Tuesday.state, 
        Wednesday.state, 
        Thursday.state, 
        Friday.state, 
        Saturday.state, 
        Sunday.state
    )
    var int minutes = 0                                                                                     // Initialwert für Minuten definieren
    if(Startzeit_Minuten.state instanceof Number) {                                                         // Falls das Item eine gültige Zahl enthält
        minutes = Startzeit_Minuten.state as Number                                                         // Setze minutes auf diese Zahl
        if(minutes > 59) minutes = 0                                                                        // Falls Obergrenze überschritten setze auf 0
        if(minutes < 0) minutes = 59                                                                         // Falls Untergrente unterschritten setze auf 59
    }
    Startzeit_Minuten.postUpdate(minutes)                                                                   // Schreibe Wert in das Item
    var int hours = 0                                                                                       // Initialwert für Sunden definieren
    if(Startzeit_Stunden.state instanceof Number) {                                                         // Falls das Item eine gültige Zahl enthält
        hours = Startzeit_Stunden.state as Number                                                           // Setze hours auf diese Zahl
        if(hours > 23) hours = 0                                                                            // Falls Obergrenze überschritten setze auf 0
        if(hours < 0) hours = 23                                                                            // Falls Untergrente unterschritten setze auf 23
    }
    Startzeit_Stunden.postUpdate(hours)                                                                     // Schreibe Wert in das Item
    val int startMinutes = hours * 60 + minutes                                                             // Zeit in Minuten
    tStartRegner?.cancel                                                                                    // geplante Beregnung canceln
    if(dayOfWeekSetting.get(now.getDayOfWeek-1) == ON) { 
        logInfo("watering","Kontrolliere Wochentag")                                                   // Falls heute Beregnung gewünscht
        if(now.getMinuteOfDay < startMinutes) {                                                             // Falls Startzeit noch nicht erreicht
            tStartRegner = createTimer(now.withTimeAtStartOfDay.plusMinutes(startMinutes),[|                // Setze einen Timer auf gewünschte Startzeit
                Beregnung.sendCommand(ON)                                                                   // Starte zur gewünschten Zeit
            ])
        }
    }
end

rule "Beregnung EIN"
when
    Item Beregnung received command
then
    if(receivedCommand == OFF) {
        logInfo("watering","Beregnung wird abgebrochen!")
        tRegner?.cancel                                                                                                                                         // Timer stoppen
        tRegner = null                                                                                                                                          // Variable leeren
        gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)]                                              // alle Regner abschalten
        //Pumpe.sendCommand(OFF)                                                                                                                                  // Pumpe abschalten
        Sperre.postUpdate(OFF)                                                                                                                                  // Bediensperre aufheben
    } else {
    logInfo("watering","Beregnung gestartet.")
    if(tRegner !== null) {
        logInfo("watering","Regner scheint noch zu laufen! Abbruch")
        return;
    }
    iRegner = 0
    Sperre.postUpdate(ON)
    //Pumpe.sendCommand(ON)
    tRegner = createTimer(now.plusMillis(10),[|
        iRegner++                                // nächsten Regener anwählen
        logInfo("regner","{}. Durchlauf",iRegner)
        gRegner.members.filter[i|i.name.contains("Power")].filter[j| j.state != OFF].forEach[r|r.sendCommand(OFF)] // alle Regner abschalten
        val maxRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].size             // wieviele Regner sollen insgesamt beregnen?
        logInfo("regner","{}. Durchlauf von {} Durchläufen.",iRegner,maxRegner)
        if(iRegner > maxRegner) {                // letzten Regner schon erreicht?
            logInfo("regner","Alle Regner sind schon gelaufen!")
            tRegner = null                       // Dann Schluss!
            Sperre.postUpdate(OFF)
            Beregnung.postUpdate(OFF)                                                                                                                       // Item zurücksetzen
            //Pumpe.sendCommand(OFF)  
            return;
        }
        Thread::sleep(500)                       // kleine(!) Pause einlegen
        val strRegner = gRegner.members.filter[i|i.name.contains("Sperre")].filter[j| j.state == OFF].sortBy[name].get(iRegner-1).name.split("_").get(2) //Namen des Regner ermitteln
        logInfo("regner","Nächster Regner: {}",strRegner)
        gRegner.members.filter[i|i.name.contains("Power") && i.name.contains(strRegner)].head.sendCommand(ON)  // Regner einschalten
        val Dauer =(gRegner.members.filter[i|i.name.contains("Dauer") && i.name.contains(strRegner)].head.state as Number).intValue
        logInfo("regner","Regenr wird nach {} Minuten wieder abgeschaltet.",Dauer)
        tRegner.reschedule(now.plusMinutes(Dauer)) // Nächste Ausführung planen
    ])
    }
end
Danke !!

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

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

Beitrag von udo1toni »

Das kann nicht sein. Der Befehl Beregnung.sendCommand(ON) kann nicht von dieser Rule kommen, denn vorher steht ein logInfo() Befehl, welcher nicht im log auftaucht.
Da so nicht wirklich klar wird, wo der Fehler auftritt, müssen wir noch ein wenig logging hinzufügen:

Code: Alles auswählen

rule "Startzeit einstellen"
when
    Member of gWeekdays changed or                                                                                         // Wochentag geändert
    Item Startzeit_Minuten changed or                                                                                      // Minuten geändert
    Item Startzeit_Stunden changed or                                                                                      // Stunden geändert
    Time cron "1 0 0 * * ?"                                                                                                // täglich um 00:00:01 Uhr
then
    // Alle Wochentag-Items müssen in der Gruppe gWeekdays zusammengefasst sein, damit der Trigger oben funktioniert
    logInfo("watering","Rule getriggert durch {}",triggeringItem.name)
    var dayOfWeekSetting = newArrayList(
        Monday.state, 
        Tuesday.state, 
        Wednesday.state, 
        Thursday.state, 
        Friday.state, 
        Saturday.state, 
        Sunday.state
    )
    var int minutes = 0                                                                                     // Initialwert für Minuten definieren
    if(Startzeit_Minuten.state instanceof Number) {                                                         // Falls das Item eine gültige Zahl enthält
        minutes = Startzeit_Minuten.state as Number                                                         // Setze minutes auf diese Zahl
        if(minutes > 59) minutes = 0                                                                        // Falls Obergrenze überschritten setze auf 0
        if(minutes < 0) minutes = 59                                                                         // Falls Untergrente unterschritten setze auf 59
    }
    Startzeit_Minuten.postUpdate(minutes)                                                                   // Schreibe Wert in das Item
    logInfo("watering","Minuten auf {} gesetzt.",minutes)
    var int hours = 0                                                                                       // Initialwert für Sunden definieren
    if(Startzeit_Stunden.state instanceof Number) {                                                         // Falls das Item eine gültige Zahl enthält
        hours = Startzeit_Stunden.state as Number                                                           // Setze hours auf diese Zahl
        if(hours > 23) hours = 0                                                                            // Falls Obergrenze überschritten setze auf 0
        if(hours < 0) hours = 23                                                                            // Falls Untergrente unterschritten setze auf 23
    }
    Startzeit_Stunden.postUpdate(hours)                                                                     // Schreibe Wert in das Item
    logInfo("watering","Stunden auf {} gesetzt.",hours)
    val int startMinutes = hours * 60 + minutes                                                             // Zeit in Minuten
    logInfo("watering","Startminuten auf {} gesetzt.",startMinutes)
    tStartRegner?.cancel                                                                                    // geplante Beregnung canceln
    logInfo("watering","Wochentag ist {} und auf {} gesetzt.",now.getDayOfWeek,dayOfWeekSetting.get(now.getDayOfWeek-1).toString)
    if(dayOfWeekSetting.get(now.getDayOfWeek-1) == ON) { 
        logInfo("watering","Zeitpunkt schon überschritten?")                                                   // Falls heute Beregnung gewünscht
        if(now.getMinuteOfDay < startMinutes) {                                                             // Falls Startzeit noch nicht erreicht
            tStartRegner = createTimer(now.withTimeAtStartOfDay.plusMinutes(startMinutes),[|                // Setze einen Timer auf gewünschte Startzeit
                logInfo("watering","Timer zum Starten abgelaufen, starte Beregnung.")
                Beregnung.sendCommand(ON)                                                                   // Starte zur gewünschten Zeit
            ])
        }
    }
end
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

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

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

Beitrag von Romel »

Sobald ich die Startzeit verstelle, erscheint im Log ein Fehler.

Code: Alles auswählen

2020-06-03 20:16:09.053 [ome.event.ItemCommandEvent] - Item 'Startzeit_Stunden' received command 20

2020-06-03 20:16:09.065 [vent.ItemStateChangedEvent] - Startzeit_Stunden changed from 21 to 20

==> /var/log/openhab2/openhab.log <==

2020-06-03 20:16:09.068 [INFO ] [ipse.smarthome.model.script.watering] - Kontrolliere Minuten

2020-06-03 20:16:09.073 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Startzeit einstellen': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_greaterThan(int,int) on instance: null

Ich habe eine zweite logInfo Zeile gesetzt

Code: Alles auswählen

var int minutes = 0                                                                                     // Initialwert für Minuten definieren
    if(Startzeit_Minuten.state instanceof Number) {
        logInfo("watering","Kontrolliere Minuten")                                                         // Falls das Item eine gültige Zahl enthält
        minutes = Startzeit_Minuten.state as Number                                                         // Setze minutes auf diese Zahl
        if(minutes > 59) minutes = 0                                                                        // Falls Obergrenze überschritten setze auf 0
        if(minutes < 0) minutes = 59
        logInfo("watering","Kontrolliere Minuten2")                                                                         
    }
Diese erscheint nicht.
Auch wenn ich die Stunden verstelle geht es nicht über die Minuten Kontrolle.

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

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

Beitrag von Romel »

UPDATE

Ich hab jetzt noch mehr logInfos gesetzt und habe Zeilen ausgeschlossen.

Code: Alles auswählen

    var int minutes = 0                                                                                     // Initialwert für Minuten definieren
    if(Startzeit_Minuten.state instanceof Number) {
        logInfo("watering","Kontrolliere Minuten")                                                         // Falls das Item eine gültige Zahl enthält
        minutes = Startzeit_Minuten.state as Number                                                         // Setze minutes auf diese Zahl
        //if(minutes > 59) minutes = 0                                                                         // Falls Obergrenze überschritten setze auf 0
        //if(minutes < 0) minutes = 59                                                                         // Falls Untergrente unterschritten setze auf 59
    }
    Startzeit_Minuten.postUpdate(minutes)
    logInfo("watering","Kontrolliere Minuten2")                                                                   // Schreibe Wert in das Item
    var int hours = 0                                                                                       // Initialwert für Sunden definieren
    if(Startzeit_Stunden.state instanceof Number) {
        logInfo("watering","Kontrolliere Stunden")                                                         // Falls das Item eine gültige Zahl enthält
        hours = Startzeit_Stunden.state as Number                                                           // Setze hours auf diese Zahl
        //if(hours > 23) hours = 0                                                                            // Falls Obergrenze überschritten setze auf 0
        //if(hours < 0) hours = 23                                                                            // Falls Untergrente unterschritten setze auf 23
    }
    Startzeit_Stunden.postUpdate(hours)
    logInfo("watering","Kontrolliere Stunden2")                                                                     // Schreibe Wert in das Item
    val int startMinutes = hours * 60 + minutes
    logInfo("watering","Umrechnung Stunden")                                                           // Zeit in Minuten
    tStartRegner?.cancel                                                                                  // geplante Beregnung canceln
    if(dayOfWeekSetting.get(now.getDayOfWeek-1) == ON) { 
        logInfo("watering","Kontrolliere Wochentag")                                                   // Falls heute Beregnung gewünscht
        if(now.getMinuteOfDay < startMinutes) {                                                             // Falls Startzeit noch nicht erreicht
            tStartRegner = createTimer(now.withTimeAtStartOfDay.plusMinutes(startMinutes),[|                // Setze einen Timer auf gewünschte Startzeit
                Beregnung.sendCommand(ON)                                                                   // Starte zur gewünschten Zeit
            ])
        }
    }
end
Log

Code: Alles auswählen

2020-06-03 21:11:54.963 [INFO ] [ipse.smarthome.model.script.watering] - Kontrolliere Minuten

2020-06-03 21:11:54.966 [INFO ] [ipse.smarthome.model.script.watering] - Kontrolliere Minuten2

2020-06-03 21:11:54.968 [INFO ] [ipse.smarthome.model.script.watering] - Kontrolliere Stunden

2020-06-03 21:11:54.971 [INFO ] [ipse.smarthome.model.script.watering] - Kontrolliere Stunden2

2020-06-03 21:11:54.973 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Startzeit einstellen': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_multiply(int,int) on instance: null
Zur Umrechnung Stunde in Minuten kommt es nicht.
Zuletzt geändert von Romel am 3. Jun 2020 21:17, insgesamt 1-mal geändert.

Darkwin101
Beiträge: 424
Registriert: 6. Mär 2019 11:19
Answers: 14

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

Beitrag von Darkwin101 »

Versuche mal
minutes = (Startzeit_Minuten.state as Number).intValue
Nach meiner Meinung fehlt hier die Wandlung von Number zu Int

Gesperrt