Rule mit while loop und variablen Items

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Maggi
Beiträge: 27
Registriert: 22. Okt 2019 20:09
Wohnort: Hanau

Rule mit while loop und variablen Items

Beitrag von Maggi »

Hi zusammen,

ich möchte Eine Regel für eine Gartenbewässerung mit 4 Ventilen, welche auf eine bestimmte Uhrzeit gestartet wird und dann je nach dem für welche Ventilkreise Zeiten hinterlegt sind, sollen diese entsprechend nacheinander geschaltet werden.
Meine Regel sieht wie folgt aus. Durchläuft auch die Schleife, aber mit den Variablen Items kann sie nicht umgehen. Deshlab wird der "IF" Teil komplett ignoriert.
Gibt es überhaupt eine Möglichkeit Items mit einer Nummer dahinter variabel zu machen in einer Rule ?

Code: Alles auswählen

var Timer timerVENTIL = null

rule "Bewässerungsautomatik"
    when
        Time cron "0 * * * * ?"
then
if (BWA_Switch.state == ON) {
		var sollMinute = (BWA_Switch_M.state as DecimalType).intValue
		var sollStunde = (BWA_Switch_H.state as DecimalType).intValue
		var Kreis1 = (BWA_Switch_T1.state as DecimalType).intValue
		var Kreis2 = (BWA_Switch_T2.state as DecimalType).intValue
		var Kreis3 = (BWA_Switch_T3.state as DecimalType).intValue
		var Kreis4 = (BWA_Switch_T4.state as DecimalType).intValue
		
		var Boolean K1 = if(Kreis1 > 0) true else false
		var Boolean K2 = if(Kreis2 > 0) true else false
		var Boolean K3 = if(Kreis3 > 0) true else false
		var Boolean K4 = if(Kreis4 > 0) true else false

if (sollMinute == now.getMinuteOfHour && sollStunde == now.getHourOfDay) {
logInfo("Bew", "Gartenbewässerung gestartet " + K1)
		var i = 0
			while ((i=i+1) <= 4) {
				logInfo("Bew", "Kreis" + i)
				if ("K"+i) {
				var sollTimer = ("Kreis"+i)
				logInfo("Bew", "Timer Kreis" + i + sollTimer)
				sendCommand("BEW_Ventil_"+i, ON)
				timerVENTIL = createTimer(now.plusMinutes(sollTimer))[
				sendCommand("BEW_Ventil_"+i, OFF)]
				}
			}
}
}
end

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

Re: Rule mit while loop und variablen Items

Beitrag von udo1toni »

Grundsätzlich kannst Du das so machen, es ist aber umständlich. Denke daran, dass i ein Integer ist. Du kannst ei. Integer und einen String nicht miteinander verketten. Du musst mittels i.toString erst nach String wandeln.

Da gerade vom Handy nur so knapp...
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Maggi
Beiträge: 27
Registriert: 22. Okt 2019 20:09
Wohnort: Hanau

Re: Rule mit while loop und variablen Items

Beitrag von Maggi »

Ich habe versucht das i toString zu wandeln, aber bekomme trotzdem einen Fehler im Log. Ich schaffe es einfach nicht eine Variable zu erzeugen die dann den Namen es Item ergibt und in den Syntax passt.
Habe jetzt auch schon versucht mit folgenden Variablen zu arbeiten

Code: Alles auswählen

val vBWA = BWA_Switch_T1.name.split("_").get(0)
val vSwitch = BWA_Switch_T1.name.split("_").get(1)
		
		
		
um dann eine variable zu bekommen welche dann das Item in der Schleife ergibt, aber auch das mag er nicht zur weiteren Verarbeitung.

Code: Alles auswählen

				val vItem = vBWA + "_" + vSwitch + "_T" + i
				if (vItem > 0) {
				var sollTimer = (vItem)
				logInfo("Bew", "Timer Kreis" + i + sollTimer)
				sendCommand(InsertItemHere, ON)
				timerVENTIL = createTimer(now.plusMinutes(sollTimer))[
				sendCommand(InsertItemHere, OFF)]
				}

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

Re: Rule mit while loop und variablen Items

Beitrag von udo1toni »

Ich muss leider schon zum Dienst, werde aber versuchen, bis heute Abend etwas ausführlicher zu antworten...
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

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

Re: Rule mit while loop und variablen Items

Beitrag von udo1toni »

Die gute Lösung dieses Problems funktioniert anders.
Die DSL bietet objektorientierte Programmierung, da braucht es gar kein loop. Auch die Lösung, jede Minute nach der Sollzeit zu schauen ist suboptimal.

Du hast pro Ventil zwei Items, über das eine wird das Ventil gesteuert, über das andere wird die Bewässerungsdauer in Minuten angegeben, wobei 0 für "überspringen" steht. Es bietet sich an, diese Items in Gruppen zusammenzufassen.
Wichtig ist dabei, dass die Items beider Itemtypen in einem Namensteil identisch sind, so dass man von dem einen auf das andere schließen kann. Nehmen wir der Einfachheit halber zwei Gruppen gBWA_Dauer und gBWA_Ventile.
Es soll jeweils nur ein Kreis laufen, wir müssen also lediglich eine Gruppe durchlaufen, um alles zu erledigen.

Code: Alles auswählen

var Timer       tBWA = null                                                                                                       // Timer für BWA
var Integer iBWAStep = 0                                                                                                          // Zähler für BWA

rule "enable und disable BWA"
when
    Item BWA_Switch changed or                                                                                                    // Zustand geändert
    Item BWA_Switch_H changed or                                                                                                  // Stunde geändert
    Item BWA_Switch_M changed                                                                                                     // Minute geändert
then
    tBWA?.cancel                                                                                                                  // Timer stoppen
    if(newState =! ON) {                                                                                                          // Fall inaktiv
        gBWA_Ventile.members.filter[i|i.state != OFF].forEach[v|v.sendCommand(OFF)]                                               // Alle regner aus
        return;                                                                                                                   // Und Rule beenden
    }
    iBWAStep = 0                                                                                                                  // Zähler auf 0
    var Integer iMinute = 0                                                                                                       // Startzeit auf 0
    if(BWA_Switch_M.state instanceof Number)                                                                                      // Falls Minute gültig
        iMinute += (BWA_Switch_M.state as Number).intValue                                                                        // zur Startzeit addieren
    if(BWA_Switch_H.state instanceof Number)                                                                                      // Falls Stunde gültig
        iMinute += (BWA_Switch_H.state as Number).intValue * 60                                                                   // zur Startzeit addieren
    if(iMinute == 0)                                                                                                              // Falls Startzeit 0
        return;                                                                                                                   // Abbruch
    if(iMinute < now.getMinuteOfDay)                                                                                              // Falls startzeit überschritten
        iMinute += 60 * 24                                                                                                        // auf nächsten Tag verschieben
    tBWA = createTimer(now.withStartOfDay.plusMinutes(iMinute), [|                                                                // Timer anlegen
        gBWA_Ventile.members.filter[i|i.state != OFF].head.sendCommand(OFF)                                                       // Laufende Regenr stoppen
        iBWAStep ++                                                                                                               // Zähler erhöhen
        if(iBWAStep > gBWA_Ventile.members.size) {                                                                                // Falls Listenende überschritten
            tBWA = null                                                                                                           // Timer löschen
            BWA_Switch.postUpdate(OFF)                                                                                            // Und Automatik aus
        } else {                                                                                                                  // Ansonsten
            val Integer iDauer = (gBWA_Dauer.members.filter[ i|i.name.contains(iBWAStep.toString)].head.state as Number).intValue // Dauer ermitteln
            if(iDauer == 0)                                                                                                       // Falls Dauer 0
                tBWA.reschedule(now.plusMillis(10))                                                                               // Timer sofort erneut ausführen
            else {                                                                                                                // Ansonsten
                gBWA_Ventile.members.filter[i|i.name.contains(iBWAStep.toString)].head.sendCommand(ON)                            // Betreffenden regner starten
                tBWA.reschedule(now.plusMinutes(iDauer))                                                                          // Und Timer erneut einplanen
            }
        }
    ])
end
Ablauf der Rule:
Die Rule löst aus, wenn die Automatik aktiviert oder deaktiviert wurde, oder die Startzeit angepasst wurde.
Zunächst wird ein eventuell laufender Timer abgebrochen.
Falls die Automatik deaktiviert ist, werden alle Regner, die eventuell aktiv sind ausgeschaltet. Damit ist die Rule fertig.

Falls die Automatik aktiviert ist, wird die Startzeit bestimmt. Dazu werden Minute und Stunde ausgelesen und passend aufaddiert. Anschließend erfolgt eine Trivialprüfung, nämlich ob die Startzeit auf Mitternacht fällt. Ist das der Fall, so geht die Rule davon aus, dass die Übernahme der Werte schief gegangen ist und bricht ab.
Ist die Startzeit nach Mitternacht, prüft die Rule, ob die Startzeit schon überschritten wurde. Ist das der Fall, so soll der Zyklus vermutlich am nächsten Tag gestartet werden, also werden 24 Stunden aufaddiert.

Nun wird der Timer initialisiert. Danach ist die Rule fertig.

Ist der Startzeitpunkt erreicht, so wird der Code im Timerblock ausgeführt:
Zunächst werden alle eingeschalteten Regner abgeschaltet.
Nun wird der Schrittzähler erhöht.
Anschließend wird geprüft, ob der Schrittzähler die Listenlänge bereits überschritten hat. Ist das der Fall, so wurde gerade der letzte Regner abgeschaltet. Die Rule löscht den Zeiger auf den Timer und schaltet die Automatik ab. Danach ist der Codeblock abgearbeitet.

Fall das Ende der Liste noch nicht überschritten wurde muss die gewünschte Dauer ausgelesen werden.
Falls die Dauer 0 ist, ruft sich der Timer nach 10 Millisekunden erneut auf, um auf den nächsten Regner zu wechseln.
Ist die Dauer größer als 0, so wird der aktuelle Regner gestartet und der Timer ruft sich zur nächsten Schaltzeit auf.

Der Code funktioniert unabhängig von der Anzahl der Regner, wichtig ist nur, dass alle Regner in der einen Gruppe sind und die Dauer Items in der anderen Gruppe sind.

EDIT: Ich hab noch ein paar Fehler gefunden...
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

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

Re: Rule mit while loop und variablen Items

Beitrag von udo1toni »

Ach so... Dein ursprünglicher Code hätte alle Regner auf einen Schlag aktiviert. createTimer legt den hinterlegten Code an und ist damit beendet, der Rule Code macht unmittelbar mit der nächsten Anweisung weiter.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Maggi
Beiträge: 27
Registriert: 22. Okt 2019 20:09
Wohnort: Hanau

Re: Rule mit while loop und variablen Items

Beitrag von Maggi »

Ich habe deinen Code so genommen. Musste nur eine Kleinigkeit ändern, weil es von meiner Openhab Version scheinbar so nicht verarbeitet werden konnte. Ansonsten macht die Regel genau was sie soll.
Hier sind viele neue Befehlszeilen drin, die ich von meinen anderen Regeln noch nicht kannte. Daher habe ich jetzt wieder ein Beispiel mehr für weitere Phantasien :-)

Danke dafür.

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

Re: Rule mit while loop und variablen Items

Beitrag von udo1toni »

Immer gerne. Falls Du irgendwelche konkreten Fragen zu Befehlen hast, immer her damit, ich versuche immer, das einigermaßen inline zu dokumentieren, aber oftmals ist es dann doch nicht detailliert genug.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Antworten