Wenn Du in der OFF-Phase des Automatik Betriebs auf Dauerbetrieb wechselst, wird das Rührwerk erst mit Erreichen der nächsten ON-Phase wieder gestartet, dann aber nicht mehr abgeschaltet.
Der andere Fall (Automatikbetrieb wird beendet während Dauerbetrieb aktiv ist), ist eigentlich logisch korrekt, Dauerbetrieb ist aktiv -> also Rührwerk an.
Ist aber natürlich dennoch ein fehlerhaftes Verhalten, weil durch die Art der Abfrage der Timer dann neu angelegt wird...
Ich denke, wir müssen noch mal einen Schritt zurück gehen und die exakte (gewünschte) Funktionsweise der Schalter definieren:
Dauerbetrieb: Schaltet mit Vorrang ein, unabhängig von der Position des Schalters Automatik.
Alternativ: Dauerbetrieb schaltet nur während des Automatik Betriebs das Rührwerk dauerhaft ein, ist Automatik aus, bleibt auch das Rührwerk aus.
Dann wäre der Automatik Schalter eher ein "Hauptschalter" für das Rührwerk, und der Schalter Dauerbetrieb würde lediglich zwischen Dauer-Ein und Automatik wechseln.
Als Korrektur der Funktion fehlt eigentlich nur eine Zeile, allerdings muss dadurch eine weitere Zeile angepasst werden

Deshalb noch mal die vollständige Rule, mit ausführlicher Dokumentation:
Code: Alles auswählen
// globale Variablen müssen zu Beginn der Datei definiert werden!
var Timer tRuehrwerk = null // Zeiger auf Timer
var Integer nRuehrwerkOn = 1 // Länge der Einschaltphase in Minuten
var Integer nRuehrwerkOff = 2 // Länge der Ausschaltphase in Minuten
rule "Rührwerk Automatik"
when
Item Ruehrwerkautomatik changed or // Automatik wurde ein- oder ausgeschaltet
Item Ruehrwerkdauerbetrieb changed // Dauerbetrieb wurde ein- oder ausgeschaltet
then
tRuehrwerk?.cancel // Timer canceln
// if(Ruehrwerkautomatik.state == OFF) { // Falls Automatik aus (Automatik = Hauptschalter)
if(Ruehrwerkautomatik.state == OFF && Ruehrwerkdauerbetrieb.state != ON) { // Falls Automatik aus und Dauer nicht an (Dauerbetrieb unabhängig von Automatik)
SpsDgk1RelayOutput.sendCommand(OFF) // schalte Rührwerk aus
return; // und beende die Rule
}
tRuehrwerk = createTimer(now, [| // Timer anlegen und sofort ausführen
var soll = OFF // definiere Fariable für Sollzustand, default OFF
if(SpsDgk1RelayOutput.state != ON) soll = ON // Falls Motor aus, soll = ON
if(Ruehrwerkdauerbetrieb.state == ON) soll = ON // Falls Dauerbetrieb, soll = ON
val zeit = if(soll == ON) nRuehrwerkOn else nRuehrwerkOff // setze Zeit abhängig von soll
if(SpsDgk1RelayOutput.state != soll) // Falls Motorzustand von soll abweicht
SpsDgk1RelayOutput.sendCommand(soll.toString) // Schalte Motor auf Sollzustand
tRuehrwerk.reschedule(now.plusMinutes(zeit)) // Plane Timerausführung erneut
])
end
Die Rule wird nun jedes Mal gestartet, wenn einer der beiden Schalter betätigt wird. Dadurch muss nun leider statt
newState der Status der beiden Items direkt verwendet werden.
Falls der Automatik Schalter als Hauptschalter dienen soll, müsstest Du den Teil
&& Ruehrwerkdauerbetrieb.state != ON entfernen (ich habe das im Code durch die auskommentierte zusätzliche Zeile dokumentiert)
Es gäbe übrigens noch eine weitere Möglichkeit, nämlich nur ein Item für den Schalter zu verwenden (Typ z.B. String, es ginge aber auch Number). In der UI bekommst Du dann drei Schaltflächen, Aus, An, Auto. Die Rule wird dadurch sogar etwas einfacher:
Code: Alles auswählen
// globale Variablen müssen zu Beginn der Datei definiert werden!
var Timer tRuehrwerk = null // Zeiger auf Timer
var Integer nRuehrwerkOn = 1 // Länge der Einschaltphase in Minuten
var Integer nRuehrwerkOff = 2 // Länge der Ausschaltphase in Minuten
rule "Rührwerk Steuerung"
when
Item RuehrwerkSteuerung changed
then
tRuehrwerk?.cancel // Timer canceln
switch(newState.toString) { // Item liefert State
case "AUS" : { // Zustand ist Aus
if(SpsDgk1RelayOutput.state != OFF) // falls nicht aus
SpsDgk1RelayOutput.sendCommand(OFF) // ausschalten
}
case "AN" : { // Zustand ist An
if(SpsDgk1RelayOutput.state != ON) // falls nicht an
SpsDgk1RelayOutput.sendCommand(ON) // anschalten
}
case "AUTO" : { // Zustand ist Auto
tRuehrwerk = createTimer(now, [| // timer anlegen und sofort ausführen
if(SpsDgk1RelayOutput.state != ON) { // falls nicht an
SpsDgk1RelayOutput.sendCommand(ON) // anschalten und
tRuehrwerk.reschedule(now.plusMinutes(nRuehrwerkOn)) // Timer nach An-Phase erneut ausführen
} else { // ansonsten
SpsDgk1RelayOutput.sendCommand(OFF) // ausschalten und
tRuehrwerk.reschedule(now.plusMinutes(nRuehrwerkOff)) // Timer nach Aus-Phase erneut ausführen
}
])
}
}
end
Du brauchst als Ersatz für die beiden alten Items ein neues Item RuehrwerkSteuerung, welches (hier so umgesetzt) vom Typ String ist. In der UI definierst Du Schaltflächen für die drei Betriebsmodi AUS, AN und AUTO, z.B. In einer Sitemap:
Code: Alles auswählen
Switch item=RuehrwerkSteuerung label="Rührwerk[]" mappings=["AUS"="Aus","AN"="An","AUTO"="Auto"]
In der Main UI geht das auch mit verschiedenen Widgets, dort sieht die Konfiguration natürlich etwas anders aus.