Time cron in Rule durch Setpoint Variable beeinflussen

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Quautiputzli
Beiträge: 364
Registriert: 29. Okt 2020 19:53
Answers: 2

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von Quautiputzli »

Ja, das hätte ich letzen Winter schon angreifen können, aber das System wie es jetzt ist läuft einfach so gut, so dass ich es dann doch gelassen habe.
Servus

Quautiputzli
Beiträge: 364
Registriert: 29. Okt 2020 19:53
Answers: 2

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von Quautiputzli »

Hallo,
da ich nun auf OH4 bin, habe ich das auch ausprobiert, mit folgender rule:

Code: Alles auswählen

rule "Ramona_Start"

when
    Time is Ramona_Start timeOnly
then
    sendNotification("????????????????@t-online.de", "erste  Ausloesungung", "time", "Info")
end
Leider scheint es nur zu funktionieren wenn auch das heutige Datum eingegeben wird. Der Ausdruck "timeOnly" scheint also ignoriert zu werden. Stimmt hier die Schreibweise?
Zuletzt geändert von Quautiputzli am 7. Nov 2024 12:48, insgesamt 1-mal geändert.
Servus

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

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von udo1toni »

Ja, die Schreibweise sollte korrekt sein. Ansonsten müsste es auch eine Fehlermeldung in openhab.log geben, wenn Du die Rules-Datei speicherst.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Quautiputzli
Beiträge: 364
Registriert: 29. Okt 2020 19:53
Answers: 2

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von Quautiputzli »

Jetzt funktioniert es doch. Ich habe das timeOnly mal rausgelöscht, gespeichert, laufen lassen, und dann wieder reingeschrieben und gespeichert, und nun geht es.
Servus

Quautiputzli
Beiträge: 364
Registriert: 29. Okt 2020 19:53
Answers: 2

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von Quautiputzli »

Jetzt will ich als nächstes, wenn die erste Aktion zu der eingestellten Zeit gestartet wurde mit z.B. 5 Minuten Verzögerung eine weitere starten.
Mach ich das dann am besten mit einem Timer in der rule, oder eine extra rule bei der man im Trigger diesen Offset von 5 Minuten addiert oder so ähnlich?
Servus

Quautiputzli
Beiträge: 364
Registriert: 29. Okt 2020 19:53
Answers: 2

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von Quautiputzli »

Außerdem möchte ich das auf einzelne Wochentage begrenzen.
Wie bekomme ich denn den Wochentag als Zahl?
Ich habe mit:

Code: Alles auswählen

ZonedDateTime.now.getDayOfWeek()

den Wochentag als Wort ausgelesen, aber ich denke für Vergleiche wäre es als Zahl einfacher. Ich habe "Value" angehängt, aber das geht wohl nicht, Weder mit noch ohne "." dazwischen, also so:

Code: Alles auswählen

ZonedDateTime.now.getDayOfWeekValue()
Servus

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

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von udo1toni »

Wenn die zweite Aktion abhängig von der ersten Aktion ist, wäre meine bevorzugte Variante eine State Machine mit Timer. Das kannst Du Dir wie ein mechanisches Programmschaltwerk aus einer Waschmaschine vorstellen, nur in Programmcode. Unterm Strich ist es ein Timer, der mehrfach ausgeführt wird.

Code: Alles auswählen

var Timer tAblauf = null
var Integer iAblauf = 0

rule "Ablauf starten"
when
    Time is Startzeit timeOnly
then
    tAblauf?.cancel
    iAblauf = 0
    tAblauf = createTimer(now.plusSeconds(1), [|
        iAblauf ++ // Zähler um 1 erhöhen
        var Integer iSeconds = 0 // Variable für Pausenlänge definieren
        switch(iAblauf) { // welcher Schritt?
            case 1  : {
                // mach was in Schritt 1
                iSeconds = 5 * 60 // nächster Schritt in 5 Minuten
            }
            case 2  : {
                // mach was in Schritt 2
                iSeconds = 35 // nächster Schritt in 35 Sekunden
            }
            case 3  : {
                // mach was in Schritt 3
                return; // letzter Schritt, also kein weiterer Durchlauf
            }
            default : { // ungültiger Wert -> da ist was schief gelaufen
                return; // Abbruch
            }
        }
        tAblauf.reschedule(now.plusSeconds(iSeconds)) // Timer erneut ausführen
    ])
end
Man kann beliebig viele Schritte definieren, mit variablem Abstand zwischen den einzelnen Schritten. Falls es definiert nur zwei Schritte sein sollen, kann man natürlich auch auf einen Gutteil des Codes verzichten:

Code: Alles auswählen

rule "Ablauf starten"
when
    Time is Startzeit timeOnly
then
    // MAch was in Schritt 1
    createTimer(now.plusMinutes(5), [| // nach 5 Minuten
        // mach was in Schritt 2
    ])
end
Da die Startzeit ja nur einmal täglich ist, kann man relativ sicher auf das Gedöns zum deinitialisieren des Timers verzichten ;) und auch der ganze Zählmechanismus kann entfallen. Aber wo zwei Schritte gebraucht werden, werden auch drei Schritte gebraucht (oder so ähnlich), deshalb wollte ich lieber die allgemeinere Lösung zuerst beschreiben.
Durch das plusSeconds(1) zu Beginn läuft der erste Befehl natürlich eine Sekunde zu spät los, man könnte stattdessen auch plusNanos(10000000) für zehn Millisekunden Verzögerung verwenden (das ist sehr weit innerhalb der ohnehin vorhandenen Variabilität), das sieht nur so komisch aus... Mit Joda Time stand plusMillis() direkt zur Verfügung, mit JavaTime gibt es das nicht mehr direkt, sondern nur noch auf Umwegen:

Code: Alles auswählen

now.plus(10,java.time.temporal.ChronoUnit.MILLIS)
was zwar einfacher zu erfassen ist, aber weil ChronoUnit nicht zu den Standard Imports gehört, ist das auch nicht schön...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Quautiputzli
Beiträge: 364
Registriert: 29. Okt 2020 19:53
Answers: 2

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von Quautiputzli »

Hallo Udo, und Vielen Dank.

Du musst hellseherische Fähigkeiten haben. Ich brauche nämlich tatsächlich 4 Schritte. Und eine 1 Sekunde hin oder her spielt hier keine Rolle. Ich brauche das eher im Minutenbereich.

Sehe ich das richtig, dass der Timer die ganze Zeit so weiterläuft, bis die Rule am nächsten Tag wieder getriggert wird?
Servus

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

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von udo1toni »

Quautiputzli hat geschrieben: 7. Nov 2024 15:48 Sehe ich das richtig, dass der Timer die ganze Zeit so weiterläuft, bis die Rule am nächsten Tag wieder getriggert wird?
Nein. Der Timer wird jeweils neu gestartet und läuft nur, bis der Code ausgeführt wird. Wenn der letzte Schritt ausgeführt wurde, wird die reschedule Methode nicht mehr aufgerufen und der Timer ist beendet.
Einzig der Zeiger auf den Timer ist potenziell noch vorhanden, was aber keine Rolle spielt. Die Rule muss ohnehin sicherstellen, dass der Timer-Code nicht mehrfach ausgeführt wird (tAblauf?.cancel), weil ein Anwender ja auf die Idee kommen könnte, den Timer Startpunkt zu ändern, nachdem die Sequenz bereits gestartet, aber noch nicht beendet wurde.
Falls im Gegenteil sichergestellt werden muss, dass unter allen Umständen die Sequenz vollständig abläuft, könnte man die Rule anders gestalten:

Code: Alles auswählen

var Timer tAblauf = null
var Integer iAblauf = 0

rule "Ablauf starten"
when
    Time is Startzeit timeOnly
then
    if(tAblauf !== null)
        return;
    iAblauf = 0
    tAblauf = createTimer(now.plusSeconds(1), [|
        iAblauf ++ // Zähler um 1 erhöhen
        var Integer iSeconds = 0 // Variable für Pausenlänge definieren
        switch(iAblauf) { // welcher Schritt?
            case 1  : {
                // mach was in Schritt 1
                iSeconds = 5 * 60 // nächster Schritt in 5 Minuten
            }
            case 2  : {
                // mach was in Schritt 2
                iSeconds = 35 // nächster Schritt in 35 Sekunden
            }
            case 3  : {
                // mach was in Schritt 3
                tAblauf = null
                return; // letzter Schritt, also kein weiterer Durchlauf
            }
            default : { // ungültiger Wert -> da ist was schief gelaufen
                tAblauf = null
                return; // Abbruch
            }
        }
        tAblauf.reschedule(now.plusSeconds(iSeconds)) // Timer erneut ausführen
    ])
end
Nun wird der Timer nur gestartet, wenn er nicht bereits ausgeführt wird (bzw. der Zeiger nicht null ist). Zum Abschluss der Sequenz muss deshalb unbedingt der Zeiger geleert werden, sonst wird die Sequenz nicht mehr gestartet. Diese Variante birgt auch die Gefahr, dass bei einem Fehler der Zeiger nicht geleert wird und in der Folge müsste mindestens die rules-Datei neu eingelesen werden um den Zeiger zu leeren, was aber (bei laufender Sequenz) ebenfalls Fehler nach sich ziehen wird. Da muss man also immer abwägen, was weniger gefährlich ist :)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Quautiputzli
Beiträge: 364
Registriert: 29. Okt 2020 19:53
Answers: 2

Re: Time cron in Rule durch Setpoint Variable beeinflussen

Beitrag von Quautiputzli »

Jetzt habe ich nochmal eine Frage zu dem Item "Startzeit". Das ist ja vom Typ dateTime.

Nun habe ich festgestellt, dass das Item nach einem restart des pi "leer" ist. Wird das nicht persestiert, und sollte wieder die letzte Zeit enthalten? Oder geht das bei DateTime nicht. Das Item ist ja nicht mit einem Channel verlinkt. Ist das ein Problem?

Ich habe hier noch mehrere Items, jedoch vom Typ switch, die nachdem restart wieder den vorherigen Wert haben. Am Persistence Service habe ich keine speziellen Einstellungen gemacht. Hier die Datei "mapdb.persist":

Code: Alles auswählen

Strategies {

//        everyMinute : "0 * * * * ?"
//        everyHour : "0 0 * * * ?"
//        everyDay  : "0 0 0 * * ?"
        default = everyChange
}

Items {
	gMapdb* : strategy = everyChange, restoreOnStartup
}
Servus

Antworten