Regelabbruch mit 2 Timern

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Abraxsas
Beiträge: 56
Registriert: 24. Feb 2019 13:58
Answers: 0

Regelabbruch mit 2 Timern

Beitrag von Abraxsas »

Guten Tag zusammen,

ich brauche bitte ein bisschen Unterstützung.

Ich habe eine kleine einfache Stuerung für meine Gartenbewässerung.

Kurze Erklärung.

Durch den Startbutton schaltet ein Wasserkreis für eine im Timer eingestellte Zeit ein. Nach Ablauf des Timers schaltet Kreis 1 aus und Kreis 2 wird für die gleiche Zeit eingeschaltet. Der Stoppbutton soll alles ausschalten und die Timer Resetten.

Jetzt zum Problem: Wenn Kreis 1 an ist und ich drücke auf stop, dann geht zwar kreis 1 aus aber nach ablauf des Timers geht dann kreis 2 an, das sorge schon für eine nasse überraschung :shock: .

Wie kann man die Regel ganz abbrechen und die Timer resetten.

Items:

Code: Alles auswählen

Switch Aussen_Rasensprenger_Hinten "Hinten" {channel="shelly:shelly25-relay:98cdac2476ad:relay1#output"}
Switch Aussen_Rasensprenger_Vorn "Vorne" {channel="shelly:shelly25-relay:98cdac2476ad:relay2#output"}
Switch Rasenprenger_Auto "Automatik"
Switch Timer_Auto "Timer Automatik"
Number Timerzeit "Zeit [%d min]"
Rule:

Code: Alles auswählen

var Timer tZeit = null

var vartimer
rule "RasensprengerAuto"

when 
	Item Rasenprenger_Auto received update
then
	if (Rasenprenger_Auto.state == ON) {
		Aussen_Rasensprenger_Hinten.sendCommand(ON)
		val Integer Timer_Time = (Timerzeit.state as DecimalType).intValue
		
		
        tZeit = createTimer(ZonedDateTime.now.plusMinutes(Timer_Time),[|
		        Aussen_Rasensprenger_Hinten.sendCommand(OFF)
                tZeit = null
		Aussen_Rasensprenger_Vorn.sendCommand(ON)
		
		

		tZeit = createTimer(ZonedDateTime.now.plusMinutes(Timer_Time),[|
                Aussen_Rasensprenger_Vorn.sendCommand(OFF)
                tZeit = null
		Rasenprenger_Auto.sendCommand(OFF)
		
		])
		])
	
	}

	if (Rasenprenger_Auto.state == OFF)  {
		
		tZeit = null
		tZeit2 = null
		Aussen_Rasensprenger_Hinten.sendCommand(OFF)
		Aussen_Rasensprenger_Vorn.sendCommand(OFF)
		

	} return

 
end
Sitemap:

Code: Alles auswählen

Switch item=Aussen_Rasensprenger_Hinten label="Rasensprenger Hinten"
 Switch item=Aussen_Rasensprenger_Vorn label="Rasensprenger Vorne"
 Switch item=Rasenprenger_Auto label="Rasensprenger Automatik" mappings=[ON="Start",OFF="Stopp"] icon=water
 Setpoint item=Timerzeit label="Dauer in Minuten [%d min]" step=1 minValue=1 maxValue=30 icon=time
Danke für die Hilfe

Gruß
Tim

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

Re: Regelabbruch mit 2 Timern

Beitrag von udo1toni »

Zu kompliziert :)

Aber der Reihe nach: tZeit = null überschreibt lediglich den Zeiger auf den Timer mit null, hat aber keinen Einfluss auf den Timer. Du kannst nur nicht mehr zugreifen.
Du willst auch gar keine zwei Timer (und Du nutzt auch nur einen... aber viel zu umständlich...).
Du möchtest einen Timer, der mehrfach läuft, und im zweiten Durchlauf etwas anderes macht als im ersten Durchlauf.

Dein Rule Code ist auch an einigen anderen Stellen suboptimal :)

Hier mal mein Vorschlag:

Code: Alles auswählen

var Timer   tRasen = null
var Integer iRasen = 30                                                 // default Wert

rule "RasensprengerAuto"
when 
    Item Rasenprenger_Auto changed                                      // nur bei Änderung Triggern
then
    tRasen?.cancel                                                      // lösche existierende Timer
    if(Rasenprenger_Auto.state != ON) {                                 // Falls nicht ON
        if(Aussen_Rasensprenger_Hinten.state != OFF)                    // Falls Rasensprnger aktiv
            Aussen_Rasensprenger_Hinten.sendCommand(OFF)                // abschalten
        if(Aussen_Rasensprenger_Vorn.state != OFF)                      // Falls Rasensprnger aktiv
            Aussen_Rasensprenger_Vorn.sendCommand(OFF)                  // abschalten
        return;                                                         // und Rule abbrechen (Semikolon beachten!)
    }
    Aussen_Rasensprenger_Hinten.sendCommand(ON)                         // Schalte Sprenger Hinten ein
    if(Timerzeit.state instanceof Number)                               // falls gültiger Wert
        iRasen = (Timerzeit.state as Number).intValue                   // übernimm diesen als Einstellung
        
    tRasen = createTimer(ZonedDateTime.now.plusMinutes(iRasen), [|      // Erzeuge Timer
        if(Aussen_Rasensprenger_Hinten.state == ON) {                   // Falls Sprenger Hinten aktiv
            Aussen_Rasensprenger_Hinten.sendCommand(OFF)                // Schalte Sprenger hinten aus
            Aussen_Rasensprenger_Vorn.sendCommand(ON)                   // Schalte Sprenger vorn ein
            tRasen.reschedule(ZonedDateTime.now.plusMinutes(iRasen))    // Plane den Timer erneut
        } else {                                                        // ansonsten
            Aussen_Rasensprenger_Vorn.sendCommand(OFF)                  // Schalter Sprenger vorn aus
            tRasen = null                                               // Lösche Zeiger
        }
    ])
end
Es gibt zwei globale Variablen, eine für den Timer, eine für die Beregnungsdauer. t für Timer, i für Integer, Rasen für... Rasensprenger...
Die Rule löst aus, wenn sich der Status des Items ändert. Es kann aus verschiedenen Gründen ein Update ohne Änderung geben, Du möchtest in der Situation nicht, dass der Timer neu gestartet wird.

Als erstes stoppt die Rule einen laufenden Timer (das geht mit .cancel). Da wir nicht wissen, ob der Timer überhaupt existiert, tun wir das nur, wenn die Variable ungleich null ist (das ist das ? am Ende des Variablennamens, vor dem .cancel)

Sollte der Status ungleich ON sein, so prüft die Rule den Status der beiden Regner und schaltet sie bei Bedarf aus. Anschließend wird die Rule verlassen. Hinten am return muss zwingend ein ; stehen, da return einen Rückgabewert sendet. Das ist das, was hinter return steht. Rules können aber keine Rückgabewerte senden... Deshalb muss der Befehl in diesem Fall mit einem Semikolon abgeschlossen werden.

Ab jetzt steht also fest, dass der Beregnungsvorgang gestartet wurde.
Der Regner hinten wird eingeschaltet, die Rule prüft, ob der Status von Timerzeit eine gültige Zahl enthält. Ist das der Fall, so wird die Variable iRasen mit diesem Wert gefüllt (ansonsten bleibt halt der Default Wert von der globalen Definition)
Nun wird der Timer angelegt und die Rule ist beendet.

Läuft der Timer ab, so prüft der Code im Timer, ob der Regner Hinten eingeschaltet ist. Ist das der Fall, so handelt es sich um den ersten Teil der Beregnung. der Regner hinten wird ab- der Regner vorn angeschaltet. Zum Abschluss wird der Timer erneut geplant (reschedule).
Sollte der Regner hinten aus sein, wenn der Timer abläuft, so handelt es sich um den zweiten Teil der Beregnung. der Regner vorn wird abgeschaltet und die Variable wird auf null gesetzt.

Diese Rule lässt sich mit nur sehr wenig Aufwand auf eine beliebige Anzahl Regner erweitern, ohne dass viel mehr Code benötigt wird (vielleicht insgesamt 3 Zeilen!) Bei zwei Regnern lohnt sich das natürlich nicht :)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Abraxsas
Beiträge: 56
Registriert: 24. Feb 2019 13:58
Answers: 0

Re: Regelabbruch mit 2 Timern

Beitrag von Abraxsas »

Wow vielen vielen dank für die Lösung UND vor allem um die Erklärung, das hilft mir sehr weiter... ich schaffe es heute nicht dieses zu testen (Frau hat andere Pläne ;-)) Ich gebe definitiv eine Rückmeldung !

Gruß Tim

Abraxsas
Beiträge: 56
Registriert: 24. Feb 2019 13:58
Answers: 0

Re: Regelabbruch mit 2 Timern

Beitrag von Abraxsas »

Hmm konnte es jetzt doch testen... Funktioniert fast perfekt nur ein kleinesProblem besteht noch.

Was geht:
Start Button:
Kreis 1 Läuft über die eingestellte Timer Zeit und wechselt dann zu Kreis 2 welcher auch über die Timer Zeit läuft, von daher macht was es soll.
Stopp Button:
Auch der macht was er soll:-)

Was geht nicht:
Nach Regulärer beendigung springt der Button nicht zurück auf Stopp, sondern bleibt auf Start stehen. Wo muss ich diesen Status dann neu setzen?

Gruß
Tim

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

Re: Regelabbruch mit 2 Timern

Beitrag von udo1toni »

Ah. Ja, den Befehl hab ich glatt vergessen.
An der Stelle, wo tRasen = null steht, ergänzt Du einfach noch eine Zeile und trägst dort Rasenprenger_Auto.postUpdate(OFF) ein.
Die Reihenfolge ist dabei egal, wichtig ist nur, dass der Befehl im gleichen Block steht - dem Bereich zwischen den zueinander gehörenden Klammern { und }

Eigentlich sollte die Rule am besten auf received command triggern, nicht auf changed... Das setzt allerdings voraus, dass das Item Rasenprenger_Auto über die UI ein- und ausgeschaltet wird.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Abraxsas
Beiträge: 56
Registriert: 24. Feb 2019 13:58
Answers: 0

Re: Regelabbruch mit 2 Timern

Beitrag von Abraxsas »

Super klappt :-) Danke

Antworten