Problem mit einem Timer in einer Rule

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

Problem mit einem Timer in einer Rule

Beitrag von violine21 »

Hallo und schöne Ostern!

Ich habe hier eine Rule, die scheinbar macht, was sie soll, trotzdem einen Fehler erzeugt.

Code: Alles auswählen

var Timer t_Komfortfunktionen = null

Code: Alles auswählen

//Wenn der Hausverbrauch größer ist als die Panelleistung, werden alle Komfortverbraucher
//ausgeschaltet und für eine Zeit x am Einschalten gehindert.
    if(Hausverbrauch.state as Number > AC_Powery.state as Number)
        {FHZ_Sperre.postUpdate(1)
        }

    if(AC_Powery.state as Number > Hausverbrauch.state as Number)
        {t_Komfortfunktionen?.cancel
        t_Komfortfunktionen = createTimer(now.plusSeconds(30), [ |FHZ_Sperre.postUpdate(0) ]
        )       
        }
Ich habe hier ein paar elektrische FHZ, die nur einschalten sollen, wenn ich genug Photovoltaik-Leistung habe.
Ich hatte das zuerst ohne den Timer 't_Komfortfunktionen', was dazu führte, das die angeschlossenen Shellies gelegentlich sehr häufig schalteten.
Jetzt wollte ich das Wiedereinschalten zeitlich verzögern, wenn wieder genug Sonnenenergie vorhanden ist.
Der Timer in der Rule erzeugt einen Fehler:

Code: Alles auswählen

2020-04-12 12:45:25.202 [ERROR] [org.quartz.core.ErrorLogger         ] - Job (DEFAULT.Timer 16103 2020-04-12T12:45:25.178+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
  <XFeatureCallImplCustom>.postUpdate(<XNumberLiteralImpl>)} ] threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
	at org.quartz.core.JobRunShell.run(JobRunShell.java:213) [bundleFile:?]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [bundleFile:?]
Ich habe die Schreibweise nun mehrfach geändert, finde aber den Wald vor lauter Bäumen nicht. Vielleicht entdeckt jemand meinen Fehler?
Wenn alles ordentlich funktioniert, würde ich daraus dann ein if - else - Konstrukt schreiben.

VG André

Darkwin101
Beiträge: 424
Registriert: 6. Mär 2019 11:19
Answers: 14

Re: Problem mit einem Timer in einer Rule

Beitrag von Darkwin101 »

{t_Komfortfunktionen?.cancel
t_Komfortfunktionen = createTimer(now.plusSeconds(30)) [ | FHZ_Sperre.postUpdate(0) ]
}

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

Re: Problem mit einem Timer in einer Rule

Beitrag von udo1toni »

Grundsätzlich ist am Code eigentlich nichts auszusetzen, die Formatierung ist vielleicht etwas gewöhnungsbedürftig, aber das sollte nicht zu Problemen führen.
Allerdings müsste der Ausdruck Hausverbrauch.state as Number > AC_Powery.state as Number genauso wie der gegenteilige Ausdruck eigentlich angemeckert werden. Schreib die beiden Werte in Klammern, also eher so:

Code: Alles auswählen

// Wenn der Hausverbrauch größer ist als die Panelleistung, werden alle Komfortverbraucher
// ausgeschaltet und für eine Zeit x am Einschalten gehindert.
if((Hausverbrauch.state as Number) > (AC_Powery.state as Number)) {
    FHZ_Sperre.postUpdate(1)
}
if((AC_Powery.state as Number) > (Hausverbrauch.state as Number)){
    t_Komfortfunktionen?.cancel
    t_Komfortfunktionen = createTimer(now.plusSeconds(30), [ |
        FHZ_Sperre.postUpdate(0)
    ])       
}
Besser wäre es natürlich, vorher zu prüfen, ob auch wirklich gültige Zahlen in beiden Status drin stehen, ein Number Item kann auch NULL im Status haben (auch wenn vorher schon mal eine Zahl drin war... Man kann das sogar mit NumberItem.postUpdate(NULL) erzwingen).
openHAB4.3.5 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

Re: Problem mit einem Timer in einer Rule

Beitrag von violine21 »

Hallo,

ich krieg den Fehler einfach nicht weg. Egal, wie ich es schreibe.
die Formatierung ist vielleicht etwas gewöhnungsbedürftig, aber das sollte nicht zu Problemen führen.
Dadurch kann ich es besser lesen :oops: Wenn es keinen Fehler erzeugt, ist mir das eine gute Hilfe.

Hier mal die gesamte Rule:

Code: Alles auswählen

rule "Komfortfunktionen Aus"
when
    Item Hausverbrauch changed or
    Item AC_Powery changed or
    Item Varta_SOC changed
then

    //Wenn der Hausverbrauch größer ist als die Panelleistung, werden alle Komfortverbraucher
    //ausgeschaltet und für eine Zeit x am Einschalten gehindert.
    if((Hausverbrauch.state as Number) > (AC_Powery.state as Number))
        {FHZ_Sperre.postUpdate(1)
        }

    if((AC_Powery.state as Number) > (Hausverbrauch.state as Number))
        {logInfo("Photovoltaik", "Timer Start")
        t_Komfortfunktionen?.cancel
        t_Komfortfunktionen = createTimer(now.plusSeconds(30), [ | FHZ_Sperre.postUpdate(0) ])
        }


    if((FHZ_Sperre.state == 1) && (Varta_SOC.state < 40))
        {Status_Komfortfunktonen.sendCommand("gesperrt, Verbrauch > Solarleistung und Batterie < 40%")
        }
    if((FHZ_Sperre.state == 1) && (Varta_SOC.state >= 40))
        {Status_Komfortfunktonen.sendCommand("gesperrt, Verbrauch > Solarleistung zzgl. Sperrzeit")
        }
    if((FHZ_Sperre.state == 0) && (Varta_SOC.state < 40))
        {Status_Komfortfunktonen.sendCommand("gesperrt, Batterie < 40%")
        }
    if((FHZ_Sperre.state == 0) && (Varta_SOC.state >= 40))
        {Status_Komfortfunktonen.sendCommand("freigegeben")
        }
end  
Kann es sein, das der Timer zu oft gecancelt und wieder gestartet wird? Die Trigger-Items sind teilweise "etwas" unruhig.
Hier mal ein log-Auszug:

Code: Alles auswählen

2020-04-12 16:28:59.250 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'energieverbraucher.rules'
2020-04-12 16:29:02.076 [INFO ] [.smarthome.model.script.Photovoltaik] - Timer Start
2020-04-12 16:29:03.954 [INFO ] [.smarthome.model.script.Photovoltaik] - Timer Start
2020-04-12 16:29:03.993 [INFO ] [.smarthome.model.script.Photovoltaik] - Timer Start
2020-04-12 16:29:15.541 [INFO ] [.smarthome.model.script.Photovoltaik] - Timer Start
2020-04-12 16:29:20.176 [INFO ] [.smarthome.model.script.Photovoltaik] - Timer Start
2020-04-12 16:29:20.385 [INFO ] [.smarthome.model.script.Photovoltaik] - Timer Start
Das ist schon heftig, was da zum Teil abgeht.
Wäre es besser, den Timer mit 'reschedule' zu betreiben?

Vielen Dank!

Darkwin101
Beiträge: 424
Registriert: 6. Mär 2019 11:19
Answers: 14

Re: Problem mit einem Timer in einer Rule

Beitrag von Darkwin101 »

Vielleicht wäre es besser mit einer Hysterese zu arbeiten 1-5 % sodass sich das ganze auch beruhigen kann.

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

Re: Problem mit einem Timer in einer Rule

Beitrag von udo1toni »

Das Löschen des Timers sollte eigentlich kein Problem darstellen. Ich würde aber ein paar Dinge ändern. Zum einen gehst Du imemr davon aus, dass alle Werte gültig sind. Zum zweiten wird der Timer immer gestartet, wenn die Rule triggert, auch wenn das gar nicht nötig ist. Das gleiche gilt für die auszugebende Meldung. Auch verwendest Du sendCommand, obwohl die Meldung vermutlich nicht über ein Binding herausgegeben wird, sondern ziemlich sicher nur auf die UI soll. Es wäre also sinnvoller, postUpdate zu nutzen.

Mein Version der Rule (ungetestet...):

Code: Alles auswählen

// Globale Variablen zu Beginn der Datei definieren
var Timer t_Komfortfunktionen = null

rule "Komfortfunktionen Aus oder An"
when
    Item Hausverbrauch changed or
    Item AC_Powery changed or
    Item Varta_SOC changed
then

    //Wenn der Hausverbrauch größer ist als die Panelleistung, werden alle Komfortverbraucher
    //ausgeschaltet und für eine Zeit x am Einschalten gehindert.

    val Number nVerbrauch = if(Hausverbrauch.state instanceof Number) (Hausverbrauch.state as Number) else 0
    val Number     nPower = if(AC_Powery.state instanceof Number) (AC_Powery.state as Number) else 0
    val Number    nCharge = if(Varta_SOC.state instanceof Number) (Varta_SOC.state as Number) else 0
    val Boolean   bSperre = if(FHZ_Sperre.state instanceof Number) (if((FHZ_Sperre.state as Number) == 0) false else true) else false
    var String strMeldung = ""

    if(nVerbrauch > nPower) {
        t_Komfortfunktionen?.cancel
        t_Komfortfunktionen = null
        if(!nSperre)
            FHZ_Sperre.postUpdate(1)
    } else if (nVerbrauch < nPower && bSperre && t_Komfortfunktionen === null) {
        logInfo("Photovoltaik", "Timer Start")
        t_Komfortfunktionen = createTimer(now.plusSeconds(30), [ | 
            FHZ_Sperre.postUpdate(0) 
            t_Komfortfunktionen = null
        ])
    }
    if(bSperre) {
        if(nCharge < 40) {
            strMeldung = "gesperrt, Verbrauch > Solarleistung und Batterie < 40%"
        } else {
            strMeldung = "gesperrt, Verbrauch > Solarleistung zzgl. Sperrzeit"
        }
    } else {
        if(nCharge < 40) {
            strMeldung = "gesperrt, Batterie < 40%"
        } else {
            strMeldung = "freigegeben"
        }
    }
    if (Status_Komfortfunktonen.state != strMeldung) Status_Komfortfunktonen.postUpdate(strMeldung)
end
Es böte sich an, FHZ_Sperre nicht als Number, sondern als Contact oder Switch zu definieren, falls es keine zwingenden Gründe für Number gibt.

Im ersten Block werden alle Items in Konstanten überführt. Falls ein Item keinen gültigen Wert liefert, wird 0 als Default genommen. Im Fall der Sperre ist ein Boolean Typ wesentlich effizienter, da aber der Ausgangswert eine Zahl ist, muss man auch hier Maßnahmen ergreifen - deshalb der doppelte ternäre Operator. Wäre FHZ_Sperre als Switch definiert, sähe die Zuweisung so aus:

Code: Alles auswählen

    val Boolean   bSperre = if(FHZ_Sperre.state == ON) true else false
Im zweiten Block wird FHZ_Sperre gesteuert (mit Timer), allerdings nur unter der Voraussetzung, dass dies auch nötig ist. das heißt zum einen, dass der Timer abgebrochen wird, falls der Verbrauch über der Produktion liegt. Falls die Sperre nicht aktiv ist, wird sie aktiviert. Liegt der Verbrauch unter der Produktion und die Sperre ist aktiv und der Timer läuft noch nicht, wird der Timer angelegt.
Der Meldungsblock schreibt die Meldung zuerst in eine String Variable. Zum Schluss wird geprüft, ob das Item einen abweichenden Status hat. Nur dann wird der neue Wert geschrieben.

Ich hoffe mal, ich habe damit alles berücksichtigt :)
openHAB4.3.5 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

Re: Problem mit einem Timer in einer Rule

Beitrag von violine21 »

Hallo Udo,
besten Dank für Deine "Projektunterstützung"!
Bevor ich mich an den Code stürze, ein paar Antworten:
udo1toni hat geschrieben: 13. Apr 2020 07:48 Zum zweiten wird der Timer immer gestartet, wenn die Rule triggert, auch wenn das gar nicht nötig ist. Das gleiche gilt für die auszugebende Meldung.
Das ist aus meiner Sicht ein großes Thema. Ich habe mal ein paar log-Infos mitschreiben lassen. In ihrer Gesamtheit sind die Items dann
sehr "nervös", was zu einem häufigen Triggern führt. Das ist schon heftig, was da in der zeitlichen Abfolge abgeht.
So ist das nun aber mal mit der Sonne 8-)
Komischerweise funktioniert die Rule trotz der Fehlermeldungen, was mich nicht wirklich zufrieden stellt :shock:
udo1toni hat geschrieben: 13. Apr 2020 07:48 Auch verwendest Du sendCommand, obwohl die Meldung vermutlich nicht über ein Binding herausgegeben wird, sondern ziemlich sicher nur auf die UI soll. Es wäre also sinnvoller, postUpdate zu nutzen.
Ja, ich nutze das Item auf einer Sitemap und in weiteren Rules. Allerdings nur innerhalb des Bindings.
udo1toni hat geschrieben: 13. Apr 2020 07:48 Es böte sich an, FHZ_Sperre nicht als Number, sondern als Contact oder Switch zu definieren, falls es keine zwingenden Gründe für Number gibt.
Hier habe ich ein Number werwendet, da das Item in der Zukunft noch ander Zustände "transportieren" soll.
Da bin ich mit Switch auf 2 Zustände begrenzt.
udo1toni hat geschrieben: 13. Apr 2020 07:48 Ich hoffe mal, ich habe damit alles berücksichtigt :)
Jetzt werde ich mich an das Verstehen des Codes stürzen und hoffe, das vom Feiertag noch was übrig bleibt ;)


Mal ne andere Frage:
Wie siehts bei euch mit Corona aus? Bist Du auf Home-Office gesetzt?

Viele Grüße
André

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

Re: Problem mit einem Timer in einer Rule

Beitrag von udo1toni »

Ich bin inoffiziell systemrelevant :) was heißt, dass ich auch mit Ausgangssperre noch zum Dienst darf (Wobei wir ja noch gar keine Ausgangssperre haben).
Teile meiner Arbeit könnte ich aber inzwischen auch von zuhause erledigen - da haben wir in den letzten vier Wochen extrem nachgerüstet, allerdings vieles davon mit heißer Nadel gestrickt. Wir hatten vor drei Jahren eine Bombenentschärfung (3. September 2017, Ffm) und damals schon angemerkt, dass wir viel zu schlecht auf solche Situationen vorbereitet sind. Nur war es damals halt eine "einmalige" Angelegenheit, die "mit Sicherheit" "nie wieder" auftreten würde... :)

Ich grinse immer noch, auch wenn die aktuelle Pandemie eigentlich keinen Anlass dazu gibt.

Da ich in Schicht arbeite, hat sich unser Dienstplan auch geändert, weil unser Team für diese Situation zu klein ist (auch sowas, was wir schon im Vorfeld angemerkt haben...)
Es gibt halt doch ein paar Dinge, die man besser mit gesundem Menschenverstand betrachtet, statt mit BWLer Augen...
openHAB4.3.5 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

Re: Problem mit einem Timer in einer Rule

Beitrag von violine21 »

Hallo Udo,
ich habe Deinen Code getestet.
Es ist deutlich ruhiger geworden in der Rule. Vielen Dank!
Bisher scheint es zu funktionieren, die Sonne spielt auch mit :)
Im ersten Block werden alle Items in Konstanten überführt.
Das habe ich schon öfters gesehen. Welchen Grund hat das? Vereinfachte Schreibweise? Wie in diesem speziellen Fall, einfache Schreibweise und
Typkontrolle in einem Rutsch?

Ich bin inoffiziell systemrelevant :) was heißt, dass ich auch mit Ausgangssperre noch zum Dienst darf
So einen "Passierschein" habe ich auch, arbeite in der Lebensmittelindustrie.

Irgendwie wird um das Thema Home-Office ein recht großer Hype gemacht. Die Politiker vergessen, das es auch noch Menschen gibt,
die in der Produktion arbeiten.
Ausserdem ist unsere IT-Infrastruktur garnicht dafür ausgelegt, das auf einmal soviel Leute von zu Hause arbeiten und dabei auch noch
ein gut ausgebautes Netz benötigen, von den Firmen ganz zu schweigen.
Neulich sagte Herr Seehofer, das er bei der Bundespolizei auch Home-Office angeordnet hat. Da dachte ich, werden die Verbrecher zum Polizist
nach Hause kommen und sich in Gewahrsam nehmen lassen :D
Genau wie der Schnellschuss mit dieser Ortungs-App. Als wenn jeder auch das passende Handy hat :?

Was mir gut gefällt, auf den Strassen ist es deutlich ruhiger geworden. Mein Arbeitsweg kann ich sehr entspannt zurück legen ohne viel Verkehr.

Interessant wird es erst, wenn alles wieder hochgefahren wird. Welche von den getroffenen Massnahmen wird wohl klamm heimlich in die
Normalität übergehen?

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

Re: Problem mit einem Timer in einer Rule

Beitrag von udo1toni »

violine21 hat geschrieben: 13. Apr 2020 11:56 Es ist deutlich ruhiger geworden in der Rule. Vielen Dank!
Bisher scheint es zu funktionieren, die Sonne spielt auch mit :)
Prima!
violine21 hat geschrieben: 13. Apr 2020 11:56
Im ersten Block werden alle Items in Konstanten überführt.
Das habe ich schon öfters gesehen. Welchen Grund hat das? Vereinfachte Schreibweise? Wie in diesem speziellen Fall, einfache Schreibweise und
Typkontrolle in einem Rutsch?
Ob man Konstanten oder Variablen nimmt, ist eher akademisch. Konstanten können nach der Definition nicht geändert werden, dafür brauchen sie etwas weniger Platz im Speicher, wenn ich es richtig im Kopf habe. Ich versuche immer, zu Konstanten zu greifen, wenn die Werte nicht geändert werden müssen. Wie man an der Rule sieht, heißt das nicht, dass der Wert nicht fallweise gesetzt werden kann, es darf halt nur einmal innerhalb der Rule bzw. innerhalb der Ebene passieren.
Die Typkontrolle ohne Variable/Konstante wäre in diesem Fall komplizierter, man müsste immer den kompletten Ausdruck verwenden, also jeweils zweimal in Bezug auf Verbrauch und Ertrag und gar viermal in Bezug auf den Ladestand.
In Bezug auf die Sperre sieht es ähnlich aus, da die Abfrage des aktuellen Stands häufiger gebraucht wird (das ist Teil der "Beruhigung").
violine21 hat geschrieben: 13. Apr 2020 11:56 Irgendwie wird um das Thema Home-Office ein recht großer Hype gemacht. Die Politiker vergessen, das es auch noch Menschen gibt,
die in der Produktion arbeiten.
Und in der Distribution :) Ich denke, das wurde schon erkannt, man weiß nur nicht, wie man das Dilemma lösen soll.
violine21 hat geschrieben: 13. Apr 2020 11:56 Ausserdem ist unsere IT-Infrastruktur garnicht dafür ausgelegt, das auf einmal soviel Leute von zu Hause arbeiten und dabei auch noch
ein gut ausgebautes Netz benötigen, von den Firmen ganz zu schweigen.
Ich hoffe, dass man schnell erkennt, wie wichtig die digitale Infrastruktur ist, um in Zukunft besser (schneller) auf solche Ereignisse reagieren zu können, mit weniger Einschnitten. Auch, dass es keine gute Idee ist, die Infrastruktur durch individuelle Breitbandverbindungen zu beanspruchen. VoD wurde ja quasi als Allheilmittel gegen Langeweile gepriesen, ohne zu verstehen, dass nicht an jedem Internetknoten in Deutschland Exabit/s umgesetzt werden können.
violine21 hat geschrieben: 13. Apr 2020 11:56 Neulich sagte Herr Seehofer, das er bei der Bundespolizei auch Home-Office angeordnet hat. Da dachte ich, werden die Verbrecher zum Polizist
nach Hause kommen und sich in Gewahrsam nehmen lassen :D
Na ja, auch die haben genug Bürokram zu erledigen :)
violine21 hat geschrieben: 13. Apr 2020 11:56 Genau wie der Schnellschuss mit dieser Ortungs-App. Als wenn jeder auch das passende Handy hat :?
Ganz zu schweigen von den rechtlichen Problemen. Und wir sollten schon noch darauf achten, nach der Krise wieder die Grundrechte der Bürger (z.B. Unverletzlichkeit der Privatsphäre, umfassender Datenschutz) zu achten. ;)
violine21 hat geschrieben: 13. Apr 2020 11:56 Was mir gut gefällt, auf den Strassen ist es deutlich ruhiger geworden. Mein Arbeitsweg kann ich sehr entspannt zurück legen ohne viel Verkehr.
Same here :) wobei ich trotzdem schon in einem kleinen Stau gestanden habe, der wie so oft komplett unnötig war. Kein Unfall, kein Garnichts, nach einem Kilometer Stop-and-Go plötzlich Vollgas und trotzdem kein Auto mehr vor mir...
violine21 hat geschrieben: 13. Apr 2020 11:56 Interessant wird es erst, wenn alles wieder hochgefahren wird. Welche von den getroffenen Massnahmen wird wohl klamm heimlich in die
Normalität übergehen?
Wenn es super läuft, erkennen die Betriebe, bei denen Home Office ohne großen Aufwand funktioniert, dass sie damit durchaus viel einsparen können. Und die Mitarbeiter, dass sie dabei auch gewinnen können. Noch besser (ok, Traum...) wäre, wenn sich die Erkenntnis durchsetzen würde, dass man wichtige Tätigkeiten auch adäquat entlohnen sollte. Und das beziehe ich auf andere, ich werde bereits gut bezahlt :)
openHAB4.3.5 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Antworten