Seite 1 von 6

Timer Ablauf

Verfasst: 3. Dez 2021 11:31
von shuo
Hallo zusammen,

Ich möchte mein Auto bis zu einem bestimmten Wert laden. Das ganze habe ich relativ komfortabel mit folgender Abfrage realisiert:

Code: Alles auswählen

rule "set charing target"
when
    Item RenaultZEServices_Zoe_Charging_Target changed or  
    Item RenaultZEServices_Zoe_Charging changed or
    Item RenaultZEServices_Zoe_ChargeLevel changed

then

       if(RenaultZEServices_Zoe_Charging.state == "Charging"){
        if(RenaultZEServices_Zoe_ChargeLevel.state >= RenaultZEServices_Zoe_Charging_Target.state){
            KebaSwitch.sendCommand(OFF)
            logInfo("RemainingCharingTarget", "Zoe set charging target achieved. Switching off at : " + RenaultZEServices_Zoe_Charging_Target.state)
        }else return

    }
end
Da RenaultZEServices_Zoe_Charging_Target und RenaultZEServices_Zoe_Charging statisch sind, möchte ich nun alle 5 min über eine andere Rule RenaultZEServices_Zoe_ChargeLevel updaten.

Wie könnte ich das denn machen? Einmal könnte ich es mit einem "Timer" lösen. Aber wie dann die nächsten Male? Also wiederhole den Timer solange das Item ein bestimten Wert hat?

Viele Dank vorab

Re: Timer Ablauf

Verfasst: 3. Dez 2021 13:34
von peter-pan
Evtl.mit einem Cron Trigger ?

Code: Alles auswählen

Time cron "0 0/5 * * * ? *"

Re: Timer Ablauf

Verfasst: 3. Dez 2021 13:42
von shuo
Naja, ein Cron-job wollte ich nicht einbauen, da es ja Ereignisgesteuert sein sollte. Ich wüsste nicht wie das mit dem Cron-Job gehen sollte

Re: Timer Ablauf

Verfasst: 3. Dez 2021 15:38
von peter-pan
Das verstehe ich jetzt nicht ganz. Der Cron Trigger läuft alle 5 Minuten und der Ablauf (then) bleibt doch gleich

Code: Alles auswählen

rule "set charing target"
when
 Time cron "0 0/5 * * * ? *"   
then
       if(RenaultZEServices_Zoe_Charging.state == "Charging"){
        if(RenaultZEServices_Zoe_ChargeLevel.state >= RenaultZEServices_Zoe_Charging_Target.state){
            KebaSwitch.sendCommand(OFF)
            logInfo("RemainingCharingTarget", "Zoe set charging target achieved. Switching off at : " + RenaultZEServices_Zoe_Charging_Target.state)
        }else return;
    }
end
Ich hab auch noch einen Semikolon hinter den "return" gemacht.

Re: Timer Ablauf

Verfasst: 3. Dez 2021 16:11
von shuo
Ah. Ich hatte an einen Unix-Cronjob gedacht.

Das ist natürlich eine Lösung. Habe sie eben probiert. Funktioniert auch. Der Nachteil ist halt, dass die alle 5 min getriggert zeitgesteuert getriggert wird. Ich hatte irgendwo mal gelesen das openHab Eventgesteuert ist und das man solche zeitgesteuerten Trigger vermeiden sollte. Ich weiß allerdings nicht mehr warum:)

Re: Timer Ablauf

Verfasst: 3. Dez 2021 17:34
von peter-pan
shuo hat geschrieben: 3. Dez 2021 16:11 Ich hatte irgendwo mal gelesen das openHab Eventgesteuert ist und das man solche zeitgesteuerten Trigger vermeiden sollte.
...da fällt mir jetzt spontan nichts dazu ein. Aber vielleicht hat wer anders ( @udo1toni ;) ) eine Idee :D

Re: Timer Ablauf

Verfasst: 3. Dez 2021 17:40
von udo1toni
Ich verstehe jetzt nicht so ganz, was Du da updaten willst. Liefert das Binding nicht automatisch aktuelle Werte für RenaultZEServices_Zoe_ChargeLevel?

Grundsätzlich, was die Timer betrifft: Du kannst einen Timer starten und aus dem Timer heraus erneut einplanen Grundgerüst:

Code: Alles auswählen

var Timer tMyTimer = null // globale Variable, zuoberst in der *.rules Datei anlegen

rule "timer starten"
when
    //irgendein Trigger, z.B. Lagevorgang gestartet
then
    if(tMyTimer === null) { // nur falls der Timer noch nicht existiert
        tMyTimer = createTimer(now.plusSeconds(1), [|  // Timer flott starten
            // die Berechnung, welche zyklisch erfolgen soll
            if(Bedingung) { // Abbruchbedingung
                tMyTimer = null
                // und was sonst noch zu erledigen ist, z.B. Ladevorgang abbrechen
            } else
                tMyTimer.reschedule(now.plusMinutes(5)) // Timercode in 5 Minuten erneut ausführen
        ])
    }
end
Der Witz an diesem Code ist, dass Du die Zeitspanne zwischen zwei Timerdurchläufen dynamisch steuern kannst. Wenn Du z.B. weißt, dass der Istpegel 20% ist und der Sollpegel 80% ist, und dass der Ladevorgang für die 60% Minimum 2 Stunden braucht, kannst Du den Timer entsprechend länger laufen lassen. Das kann vor allem interessant sein, wenn gleichzeitig die Ladekurve aktiv gesteuert werden soll (Ladeleistung abhängig vom Delta).

Re: Timer Ablauf

Verfasst: 3. Dez 2021 21:35
von shuo
Hi Udo,
udo1toni hat geschrieben: 3. Dez 2021 17:40 Ich verstehe jetzt nicht so ganz, was Du da updaten willst. Liefert das Binding nicht automatisch aktuelle Werte für RenaultZEServices_Zoe_ChargeLevel?
Leider nein. Es gibt hier kein Binding. Ich habe das über ein Pyton - Skript realisiert. Anfangs hatte ich einen CronJob eingerichtet, der ständig die Werte abfragt und über die Rest-Schnittstelle an die Iteam übergibt. Renault leider verweigert bei zuvielen Abfragen die Serverabfrage. Daher möchte ich die Serverabfragen auf ein Minimum beschränken. Sonst werde ich wieder gesperrt.

Was ich an Deinem Vorschlag noch nicht ganz verstanden habe: Der Trigger, der die Rule startet, wird einmal gesetzt. Das heißt das Item steht dann dauerhaft auf "laden".

Ich würde ja nie wieder in die Rule reinkommen um den Timer-Status abzufragen. Ich muss halt in dem Timer den Status der Werte manuell triggern.

Re: Timer Ablauf

Verfasst: 4. Dez 2021 06:41
von udo1toni
Die Rule erstellt einen Timer und ist danach beendet. Die Rule führt den Code nicht aus!

Ich breche den Code zum besseren Verständnis mal auf:
Dieser Teil wird in der Rule tatsächlich ausgeführt:

Code: Alles auswählen

var Timer tMyTimer = null // globale Variable, zuoberst in der *.rules Datei anlegen

rule "timer starten"
when
    //irgendein Trigger, z.B. Lagevorgang gestartet
then
    if(tMyTimer === null) { // nur falls der Timer noch nicht existiert
        tMyTimer = createTimer(now.plusSeconds(1), [])
    }
end
Die Zuweisung tMyTimer = createTimer(now.plusSeconds(1), []) legt im Scheduler einen Eintrag an. Der geplante Zeitpunkt ist "eine Sekunde von jetzt an". Der zu diesem Zeitpunkt auszuführende Codeblock steht als zweiter Parameter in den eckigen Klammern.
tMyTimer bekommt einen Zeiger auf den Scheduler Eintrag. Somit kann die Rule Engine gezielt auf diesen Scheduler Eintrag zugreifen.
Danach ist die Rule zuende.

Dieser Teil wird im Scheduler gespeichert:

Code: Alles auswählen

// die Berechnung, welche zyklisch erfolgen soll
if(Bedingung) { // Abbruchbedingung
    tMyTimer = null
    // und was sonst noch zu erledigen ist, z.B. Ladevorgang abbrechen
} else
    tMyTimer.reschedule(now.plusMinutes(5)) // Timercode in 5 Minuten erneut ausführen
Dieser Code wird ausgeführt, wenn der Timer abläuft.
Beim ersten Mal läuft der Timer nach einer Sekunde ab (könnte man natürlich auch schon erst nach 5 Minuten machen... ganz nach Belieben).
Die Zeile tMyTimer.reschedule(now.plusMinutes(5)) nutzt nun den Zeiger auf den Scheduler-Eintrag um den Eintrag erneut in der Zukunft einzuplanen, in diesem Fall halt nach 5 Minuten.
shuo hat geschrieben: 3. Dez 2021 21:35 Renault leider verweigert bei zuvielen Abfragen die Serverabfrage. Daher möchte ich die Serverabfragen auf ein Minimum beschränken. Sonst werde ich wieder gesperrt.
Was nur beweist, dass die Cloud böse ist. :) Ladeüberwachung ist kein Missbrauch, und wenn Renault nicht in der Lage ist, die Datenanfragen zu bewältigen, sollten sie den Job denjenigen Leuten überlassen, die Ahnung davon haben.

Re: Timer Ablauf

Verfasst: 4. Dez 2021 14:09
von shuo
Super Udo, vielen Dank für die Erklärung. Das muss ich gleich ausprobieren. Mir war das mit der Rule Engine und dem Scheduler nicht bekannt, bzw. bewusst.