regel nagative werte

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

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

Re: regel nagative werte

Beitrag von udo1toni »

Der Punkt ist, openHAB ist ein eventgesteuertes System.
Der Time cron Trigger "0 0 19-23,0-8 * * ? *" führt die Rule einmal pro Stunde aus, und zwar von 19 Uhr bis 8 Uhr, jeweils zur vollen Stunde.
Dieser Trigger macht also nicht das, was Du möchtest. Du musst nun in der Rule zusätzlich noch den aktuellen Status des Items abfragen, um das es eigentlich geht.
Wesentlich sinnvoller ist eine Rule, welche auf Wertänderung des Items reagiert und dann innerhalb der Rule entscheidet, ob die
Rahmenbedingung - aktueller Zeitpunkt innerhalb eines bestimmtem Zeitraums - erfüllt ist.
Die Begrenzung des Zeitraums führst Du außerdem jetzt ein, davon war aber oben die ganze Zeit gar keine Rede :) dort hast Du als Trigger

Code: Alles auswählen

Time cron "0/1 * * * * ?"
angegeben, was im Übrigen gleichbedeutend mit

Code: Alles auswählen

Time cron "* * * * * ?"
ist, also jede Sekunde einmal ausführen. Solche Rules belasten das System meist erheblich mehr, als gezielt auf die Wertänderung zu reagieren, selbst wenn diese auch in Zeiträumen geschieht, die Du mit dem Time cron Ausdruck nachträglich "ausblenden" könntest.

In den allermeisten Fällen werden Rules mit Time cron geschrieben, die dann einfach zyklisch bestimmte Dinge tun, obwohl das gar nicht notwendig ist.

Handelt es sich bei dem Wechselrichter um ein Batteriesystem, oder warum willst Du die Regel nur laufen lassen, wenn es mutmaßlich nur wenig bis gar kein Sonnenlicht gibt?
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

steinadler
Beiträge: 69
Registriert: 29. Apr 2020 19:15
Answers: 0

Re: regel nagative werte

Beitrag von steinadler »

hi
ganz kurz...
1.der soyosource 1000 hängt an einem akku(LiFePo4-ca 9.6 KW), wird bespeisst von ca 1,5 KW solar(Point)
2.desweiteren nocheinmal ca 1,3 Kw solar an 2,4 Kw(LiFePo4) an einem anderen WR(SUN1000)
die zweite anlage speisst den ganzen tag(auf ca 330 W gestellt) ins hausnetz(mein verbrauch)
die erste anlage speisst 2 pumpen(toilette,brunnen) meine WaMa, Geschirrspüler(an extra WR, aber mit an dem akku)) und halt die nachteinspeisung
deshalb sollte die zweite batterie immer schön voll sein
als der soyosource rauskam, hatte schon jemand eine NullWatt einspeisung gebastelt( KlausLI-zu finden in GitHub)
als mein WR kam(soyosource) war natürlich andere hardware verbaut, KlausLi funktionierte nicht mehr
somit habe ich mich hingesetzt und in c++ einen eigenen sketch geschrieben(immer stückchenweise, mit lehrbuch-da ich blutiger anfänger bin)
nun geht der sketch
jetzt wollte ich noch das inopenhab mit einbringen(nachteinspeisung und einen slider-denke nicht das ich die mikrowelle und induktionsherd hinbekomme-ein und ausschalten(trägheit der anlage))
also slider(mit festen wert einstellen) mit schalter zum zuschalten,(fertig mit kochen,zweite anlage aus, wartet auf nachteinspeisung)
da nur stümper bin, habe ich mich an allen langsam rangetastet(für den sketch ca 5 monate, traurig gelle)
um zu testet habe ich zB in der regel in openhab einen 1sec tackt gewählt,(da brauch ich nicht warten, bis sich Item ändert)
im flur kullert der raspi rum, mit OH, an der wand hängt ein tablet, zum steuern(OH mit solaranzeige von 2 victron laderegler,alarmanlage lichtsteuerung,wasservorrat(wasserfass mit hallsensor), und so weiter...
nun soll halt meine solaranlage dazukommen
dazu lese ich den digitalen zähler aus,schicke das an OH, soll dort begrenzt und zuschalbar sein(slider)
so, das ist die ganze geschicht im schnelldurchlauf

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

Re: regel nagative werte

Beitrag von udo1toni »

Klingt danach, als hättest Du ein gewachsenes System, welches aber durch die allmähliche Entwicklung hochkomplex ist - so komplex, dass es fast unmöglich wird, da noch durchzusteigen...
steinadler hat geschrieben: 31. Jul 2023 13:48 da nur stümper bin, habe ich mich an allen langsam rangetastet(für den sketch ca 5 monate, traurig gelle)
Warum? Du wirst ja nicht die ganzen fünf Monate täglich acht Stunden ausschließlich diesen Sketch entwickelt haben :)
Ich habe den Umstieg von openHAB1.8 auf openHAB2.4 (bzw. eben die vorherigen Versionen) über zwei Jahre vor mir hergeschoben. Der Umstieg auf openHAB3.3 verlief ähnlich. Erst jetzt, mit openHAB4 war der Umstieg meines Produktivsystems schon knapp zwei Wochen nach Veröffentlichung der stable 4.0.0 (da war dann allerdings schon das erste Bugfix raus :lol: ) - Und ich habe nicht mal ein außerordentlich großes openHAB System, ich hatte nur immer irgendwas anderes zu erledigen.
Das nur dazu, ob ein benötigter Zeitraum für die Umsetzung eines Projekts irgendetwas über die Befähigung der umsetzenden Person aussagt. (~fishing for compliments~ ;) )

Und gerade wenn Du vorher keinen Schimmer von der Materie hattest, ist es doch um so toller, dass Du es selbst geschafft hast, eine individuelle Schnittstelle für Deinen WR zu entwickeln.

So, zurück zur Aufgabe...
Vorweg: Ich habe selbst eine PV Anlage (9,88 kWp) mit Einspeisung ins Netz, aber leider keinen Akku - ein 5kWh Modell hätte damals über 6000 € gekostet und ich hätte nicht mal einen gescheiten Stellplatz dafür gehabt. Ich weiß also nur sehr wenig über die verschiedenen zu berücksichtigenden Aspekte wie Lebensdauer, Amortisation, laufenden Kosten usw.

Letztlich ist es dem Akku egal, welche Geräte von ihm gespeist werden. Die Nulleinspeisung muss ja so laufen, dass Du zu jeder Zeit Deinen aktuellen Verbrauch so anpasst, dass er möglichst auf dem Niveau liegt, was die Solaranlage gerade liefert. Dabei gibt es Geräte, die man nicht einfach so ein- und ausschalten kann - sei es der Geschirrspüler oder die Waschmaschine, sei es ein PC. Und dafür baut man dann halt Akkus ein, die die Produktionsschwankungen möglichst gut ausgleichen.

Erst wenn der Akku fast voll ist, muss man schauen, einen weiteren Verbraucher zuzuschalten, der dann allerdings bei Produktionsabfall entweder direkt wieder ausgeschaltet werden können muss oder eben den Akku eine Zeit lang zusätzlich belasten darf.
Auf der anderen Seite, also wenn der Akku fast leer ist, müssen solche flexiblen Verbraucher abgeschaltet werden, damit man nicht unnötig Strom aus dem Netz bezieht.

Eine sinnvolle Steuerung (wenn ich so etwas umsetzen wollte), würde also ein paar Dinge berücksichtigen:
1. Akkuladung
2. wie schnell wird der Akku geladen/entladen
3. Wie groß soll die Reserve im Akku sein (alle Verbraucher, die dauerhaft versorgt werden sollen über die "Dunkelphase" bringen)
4. Welche Geräte können bei Bedarf zu- und abgeschaltet werden
4.a. Wie hoch ist die benötigte Energiemenge des Geräts für einen Durchlauf, also wie viel Energie wird dieses Gerät auf jeden Fall benötigen, bevor es wieder abgeschaltet werden kann. Je größer die benötigte Energiemenge, desto später im Ladeverlauf wird dieses Gerät gestartet, um das Gerät notfalls über den Akku zu betreiben.

Weiterhin muss die Nulleinspeisung unbedingt nicht unmittelbar von openHAB geregelt werden. openHAB ist kein Regelsystem, es ist ein Steuersystem. openHAB kann also gezielt Geräte ein- und ausschalten, um den Arbeitspunkt der Nulleinspeisung zu verschieben, es kann selbst aber keine Nulleinspeisung realisieren.
Die Nulleinspeisung muss vom Wechselrichter des Akkus realisiert werden, der dafür dann entsprechende Messeinrichtungen braucht (gewöhnlich Messwandler direkt hinter dem Stromzähler)
Alles andere ist ineffizientes Gebastel, man kann damit eventuell auch Einsparungen erzielen, wird aber immer wieder ungenutzte Energie "liegen lassen" oder unnötig Strom aus dem Netz beziehen.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

steinadler
Beiträge: 69
Registriert: 29. Apr 2020 19:15
Answers: 0

Re: regel nagative werte

Beitrag von steinadler »

kann einer bitte mal drüberfliegen, obes es so geht(besser habe ich das nicht hinbekommen)...

Code: Alles auswählen

rule "Zeit- Regel"    
when
   //Time cron "0/1 * * * * ?"            //Zum Testen
    Time cron "0 0 19-23,0-8 * * ?"   // Regel wird täglich von 19 Uhr bis 9 Uhr(0-8) ausgeführt
then
                                   
    if (Uhrschalter.state != ON)      // prüfe, ob der uhrschalter bereits auf "ON" ist
    
    {
        Uhrschalter.sendCommand(ON)   // uhrschalter auf "ON"     
    }
end

rule "Schalter ausschalten"
when
    Time cron "0 0 9-18 * * ?"    // Regel wird täglich von 9 Uhr bis 18 Uhr 
then
    if (Uhrschalter.state != OFF)  // prüfe, ob der uhrschalter bereits auf "OFF" ist
     {
        Uhrschalter.sendCommand(OFF)  // uhrschalter auf "OFF"
     }
end    
----------------------------------------------------------------------------------------------------------------------------------------
rule "WechselrichterSoyosorce"
when
   
  Item VerbrauchTest changed 
  
   then
   
     val status = Uhrschalter.state.toString()           // Status des Schalters abfragen
     if (status == "ON") {                                       // Wenn der Schalter an ist, dann...


      if(!(newState instanceof Number))              // keine Zahl?
        return;                 
       }
  
    var zahl = (newState as Number).floatValue     //weise zu
    if (zahl < 1) {                                                //entscheide
     zahl = 10;
   } else if (zahl > 550) {                                   //entscheide
     zahl = 500;
   }
 
 
 val mqttActions = getActions("mqtt","mqtt:broker:neuer")
     mqttActions.publishMQTT("Leistung", zahl.toString)                            //schreibe in Leistung
  
end  
danke...

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

Re: regel nagative werte

Beitrag von udo1toni »

Wieder direkt die Frage: Wozu der Uhrschalter? Warum prüfst du stündlich den Zustand? Warum über zwei Rules?

.sendCommand() sendet einen Befehl. .postUpdate() setzt einen Status. Ich gehe davon aus, dass Du das Item Uhrschalter eingebaut hast, um darüber die Rule quasi zu deaktivieren oder zu aktivieren. Aber ob das in der gewählten Form tatsächlich sinnvoll ist?
Besser, in einer Rule:

Code: Alles auswählen

rule "Uhrschalter setzen"    
when
    Time cron "0 0 * * * ?"   // Regel stündlich ausführen
then
    var soll = ON                               // Default Sollwert ON
    if(now.getHour > 8 && now.getHour < 19)     // falls aktuelle Zeit 09:00:00 Uhr bis 18:59:59 Uhr
        soll = OFF                              // Ändere Sollwert auf OFF

    if(Uhrschalter.state != soll)               // falls Uhrschalter Status von soll abweicht
        Uhrschalter.postUpdate(soll.toString)   // Setze Uhrschalter auf Sollwert
end
Falls Du noch openHAB2 einsetzt, musst Du getHour durch getHourOfDay ersetzen, ansonsten bleibt die Rule gleich.
Beim Senden des Status kann es auch ohne das .toString funktionieren, auf der sicheren Seite sind wir aber mit dem .toString, so funktioniert es auf jeden Fall korrekt. :)

Die "eigentliche" Rule:

Code: Alles auswählen

rule "Wechselrichter Soyosorce"
when
    Item VerbrauchTest changed 
then
    if(Uhrschalter.state != ON)                               // Rule nicht aktiv?
        return;                                               // dann raus!

    if(!(newState instanceof Number))                         // keine Zahl?
        return;                                               // dann raus!

    var zahl = (newState as Number).floatValue                // weise zu
    if(zahl < 1)                                              // Wert kleiner 1?
       zahl = 10                                              // dann setze Wert 10
    if(zahl > 550)                                            // Wert größer 550?
       zahl = 500                                             // dann setze Wert 500

    val mqttActions = getActions("mqtt","mqtt:broker:neuer")
    mqttActions.publishMQTT("Leistung", zahl.toString)        // schreibe in Leistung
end  
Bitte keine Semikola, wo keine hingehören! (Konkret ausschließlich nach dem Schlüsselwort return, sonst nirgends. Nie.

Du hast Die Abfrage von Uhrschalter falsch eingebaut, letztlich hätte der Uhrschalter bei Deiner Version dafür gesorgt, dass nur zwischen 19 und 9 Uhr geprüft wird, ob ein gültiger Zahlenwert vorliegt und falls das nicht der Fall wäre dann die Rule abgebrochen. Auf jeden Fall würde aber der auf Werte zwischen 1 und 550 begrenzte Zahlenwert in das Topic Leistung geschrieben, wenn Uhrschalter auf OFF würde die Rule ohne vorliegenden gültigen Wert halt eine nullPointer Exception werfen.

Die Version hier bricht nun ab, wenn Uhrschalter nicht auf ON steht. Da der Wert kein zweites Mal gebraucht wird, ist es unsinnig, ihn zuerst in eine Variable zu speichern. Auch besteht kein Anlass, den Wert zuerst in einen String zu wandeln, openHAB kann sehr gut mit Status umgehen.

Falls die Rule weiterläuft (d.h. Uhrschalter steht auf ON), wird nun geprüft, ob ein gültiger Zahlenwert vorliegt. Ist das nicht der Fall, bricht die Rule ab.

Läuft die Rule immer noch, so wird der Zahlenwert als Float Zahl in der Variablen zahl gespeichert.

Nun folgt ein Vergleich mit den beiden Grenzwerten. Ist zahl kleiner als 1, so wird der Wert 10 gesetzt, ist zahl größer als 550, wird 500 gesetzt (Ich frage mich immer noch, warum Du auf andere Werte prüfst als Du schließlich setzt... sinnvoller wäre, auf < 10 zu prüfen und falls das zutrifft auf 10 zu setzen, sowie auf > 500 zu prüfen und gegebenenfalls 500 zu setzen.
Hier mit else zu arbeiten ist nicht sinnvoll, es trifft ohnehin nur maximal eine der beiden Bedingungen zu.

Und warum nutzt Du publishMQTT?
Viel sinnvoller wäre, einen Channel zu definieren und den Wert an den Channel zu senden. Falls das Gerät selbst auf den Befehl antwortet, so kann man die Antwort mutmaßlich im selben Channel empfangen und an das selbe Item als Status übergeben - zwei Fliegen mit einer Klappe.
Liefert der Channel keine Rückmeldung und der Channel ist writeOnly, so hast Du zumindest im Item immer die zuletzt gesendete Leistung und kannst diese direkt in der UI zur Anzeige nutzen, Du bekommst außerdem Persistence frei Haus und kannst später genau nachvollziehen, wie der Verlauf der Leistung über den Tag, die Woche, das Jahr war.
Außerdem ersparst Du Dir die Definition der Action (eine Stelle zusätzlich in der Konfiguration, die Du anpassen musst, wenn Du mal was an der Bridge anpasst).
Es gibt sehr gute Gründe, in Rules die mqtt Action einzusetzen, hier jedoch definitiv nicht. :)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Taifun2300
Beiträge: 19
Registriert: 27. Dez 2022 09:19
Answers: 0

Re: regel nagative werte

Beitrag von Taifun2300 »

Hallo,

Bin gerade über die ausführliche Erklärung warum man „cron“ nicht benutzen sollte gestoßen und gerade ein wenig verunsichert. Die Aufgabenstellung ist im prinzip die Gleiche :roll: Speichersystem das tagsüber geladen wird und in der Nacht einspeisen soll. Damit die Batterien nicht Schaden nehmen gibt es ein dreistufiges System.

1.) Die Verbraucher sind via Lastausgang (Victron) und Lastrelais zugeschaltet. Der würde bei Minimumspannung abschalten
2.) FHEM Server der mit einem kleinen Puffer diese Abschaltung vorher vornehmen soll als komfortablerer Wächter.
3.) Openhab als Steuerinstrument um z.B. dafür zur Sorgen, dass die Abschaltautomtik, dynamisch angepasst wird um eine regelmässige Vollladung zu gewährleisten.

Dazu läuft (vermeindlich?) alle 5 Minuten ein Script, das in der Rule wie folgt eingetragen ist:
cronExpression: "* 0/5 * * * ? *"
(Bei der Ruleerstellung zusammen geklickt)

In Crontab selbst würde ich den Eintrag übrigens so einstellen */5 * * * * ….

Jetzt hoffe ich, dass das auch so funktioniert, oder läuft das auch jede Sekunde ?

Sorry, dich heute schon zum zweiten Mal zu belästigen
LG
openHAB 4.0.3 im Docker auf Debian 11, Anbindung an Raspmatic, Hue, FHEM, Fritzbox, Buderus KM200, Worx, Bilnk, Alexa

steinadler
Beiträge: 69
Registriert: 29. Apr 2020 19:15
Answers: 0

Re: regel nagative werte

Beitrag von steinadler »

danke, das hilft mir ersteinmal sehr viel weiter...
sehr gut , für deine erklärungen am rand

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

Re: regel nagative werte

Beitrag von udo1toni »

Taifun2300 hat geschrieben: 2. Aug 2023 19:45 Sorry, dich heute schon zum zweiten Mal zu belästigen
Kein Ding.

Ganz wichtig zu wissen: openHAB verwendet Quartz Cron, nicht das "gewöhnliche" Cron.
Crontab kann nur minutengenau triggern.
In Quartz Cron gibt es hingegen sekundengenaue Trigger.
Da die Trigger ansonsten weitgehend gleich geschrieben werden, ist Quartz Cron also um ein Feld gegenüber Crontab verschoben.

Code: Alles auswählen

"* 0/5 * * * ? *"
 ^  ^  ^ ^ ^ ^ ^
 |  |  | | | | Jahr (optional)
 |  |  | | | Wochentag
 |  |  | | Monat (im Jahr)
 |  |  | Tag (im Monat)
 |  |  Stunde
 |  Minute 
 Sekunde 
 
Das heißt also: In jedem Jahr (kann auch komplett entfallen) an jedem Tag zu jeder Stunde jeweils in den Minuten, die durch 5 ohne Rest teilbar sind sekündlich, also z.B. im Sekundenabstand von 05:05:00 bis 05:05:59, dann wieder von 05:10:00 bis 05:10:59 und so weiter.

Als Besonderheit muss bei Quartz cron zwingend exakt ein Fragezeichen gesetzt werden, und zwar entweder im Tag oder im Wochentag. Man kann demnach eine Rule nicht gezielt nur an jedem Freitag, den 13. triggern lassen :)

Du solltest an die erste Stelle des Cron Ausdrucks lieber eine Zahl zwischen 0 und 59 schreiben, in dieser Sekunde der Minute wird die Rule dann ausgeführt (kann man prima nutzen um zu vermeiden, dass es zu "Massenausführungen" von zyklisch laufenden Rules kommt).

Besser wäre aber in jedem Fall, die Rules so zu gestalten, dass sie eben nicht zyklisch ausgeführt werden müssen, sondern stattdessen wertgesteuert laufen. Je nach Wert kann das auch bedeuteten, dass eine Rule wesentlich häufiger ausgeführt wird, aber auch da gibt es gute Möglichkeiten, eine zu häufige Ausführung von Rules zu verhindern (z.B. prüft man zu Beginn, ob ein Timer läuft. Ist das nicht der Fall, so startet man den Timer und führt den Rest der Rule aus. Im Timer wird dann lediglich der Timer wieder beseitigt - voilà, hat man eine Frequenzbegrenzung, die zudem auch noch variabel anpassbar ist. Damit wird eine Steuerung tendenziell wesentlich agiler, ohne aber überempfindlich zu sein.

Z.B. Heizung: Gegeben Soll- und Isttemperatur sowie Schaltaktor für die Heizung. Die Heizung soll heizen, bis die Solltemperatur erreicht wurde, wenn sie gestartet wurde aber mindestens 5 Minuten. sie soll mit Heizen beginnen, wenn die Solltemperatur um 0,5 °C unterschritten wurde, aber frühestens 5 Minuten nach dem letzten Ausschaltvorgang.

Einfache Variante: alle 5 Minuten die Abweichung von Soll und Ist prüfen und gegebenenfalls schalten.
Besser: Bei Änderung von Soll oder Ist die Abweichung prüfen, falls Timer noch läuft warten, bis der Timer abgelaufen ist (im Zweifel kommt dann eh noch eine Wertänderung rein) Somit wird die Heizung unmittelbar schalten, wenn der letzte Schaltvorgang mehr als 5 Minuten her ist, die Steuerung ist also reaktionsfreudiger geworden. Im Zweifel führt das zu weniger Überschwingern (wobei natürlich eine PI-Regelung sinnvoller wäre, aber auch ungleich komplexer, wenn man nicht ordentlich Grundlagenwissen zu dem Thema hat...)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Taifun2300
Beiträge: 19
Registriert: 27. Dez 2022 09:19
Answers: 0

Re: regel nagative werte

Beitrag von Taifun2300 »

Ok, vielen Dank für deine Erklärung.

Das bedeutet, um es sinnvoller zu gestalten, muss ich die einzelnen Abfragen in dem zyklischen Skript jeweils als einzelne Rules hinterlegen mit dem jeweiligen Wert als Event. Wobei es z.B. beim Stromverbrauch mit 3 Nachkommastellen, eine Timerlösung sein sollte, wie auch bei den anderen Prüfungen ....
Und ich muss meine jeweiligen "Item-Referenzwerte" in die Rulebedingungen aufnehmen.

Vorteil wäre auch, das jede Prüfung für sich läuft, und damit auch azyklisch zu den anderen.

Gut, damit habe ich eine neue Aufgabe unter der Rubrik "Lerne Openhab besser kennen" :D

LG
openHAB 4.0.3 im Docker auf Debian 11, Anbindung an Raspmatic, Hue, FHEM, Fritzbox, Buderus KM200, Worx, Bilnk, Alexa

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

Re: regel nagative werte

Beitrag von udo1toni »

So pauschal kann man das nicht sagen. Es gibt halt Werte, die extrem häufig aktualisiert werden - z.B. mein EVU Zähler liefert jede Sekunde einen Wert, der in openHAB über mqtt ankommt. Die diversen Steckdosen mit Tasmota liefern aber nur alle fünf Minuten einen Messwert.
Andererseits benötige ich keine Weiterverarbeitung des Stromzählerwertes, also auch keine Rule für diesen Wert.
Dafür liefert aber der Solarwechselrichter ebenfalls Messwerte, und diese fasse ich über eine Rule zusammen (Aktuelle Leistung, Tagesertrag, Jahresertrag, Gesamtertrag). Hier möchte ich aber immer den aktuellen Wert sehen, also feuert die Rule bei jeder Wertänderung eines der beteiligten Items (dass die Werte sich gewöhnlich zeitgleich ändern - sie kommen ja über die gleiche Schnittstelle ins System - spielt keine Rolle, ab Version 3 hat jede Rule einen Thread für sich, kann also nie mehrfach gleichzeitig aufgerufen werden) - Der Wechselrichter liefert aber nur alle 30 Sekunden einen Messwert, also kein Problem, denn die Rule selbst braucht nicht mal 5 ms um ihre Arbeit zu erledigen.

Die Anzahl der Nachkommastellen spielt übrigens keine Rolle, es geht einzig um eine Wertänderung, wie groß oder klein diese ausfällt ist egal.

Die Frage ist also immer auch um was für Messwerte es sich handelt, wie Du sie weiterverarbeitest, wie oft die Status der betroffenen Items aktualisiert werden, welche Items voneinander abhängen...

Und dann sollte man auch nicht außer Acht lassen, dass es oftmals großes Einsparpotential bei mehrfach auftretenden Aufgaben gibt.
Z.B. habe ich neun RTR (RaumthermostatRegler) die per knx angebunden sind. Ich kann für jeden dieser RTR die Betriebsart setzen (Komfort, Nachtabsenkung usw.) und jeder dieser RTR liefert seinerseits bei jeder Umschaltung auch eine Information über die aktuelle Betriebsart. Leider passen diese beiden Werte so gar nicht zueinander - die Rückmeldung erfolgt bitweise in einem Byte, wobei dort noch zusätzliche Daten geliefert werden, die Steurung geschieht über die Zahlen 1 bis 4.
Ich benötige also eine Rule, die RTR_In und RTR_Out dergestalt miteinander verbindet, dass bei bestimmten aktiven Bits in RTR_In der passende Wert in RTR_Out geschrieben wird, nur für neun Itempaare. Nun könnte ich eine Rule anlegen, die das zyklisch prüft und alle Items setzt (totaler Quatsch...), neun Rules, die sich jeweils um ein Itempaar kümmern, oder ich schreibe eine Rule, die nur wenige Zeilen mehr Code enthält, sich aber um alle neun Itempaare kümmert, ohne bei jedem Durchlauf alle Itempaare anzufassen.

Zyklische Abfrage für alle Items in einer Rule:

Code: Alles auswählen

rule "Betriebsarten RTR zyklisch"  // 95 Zeilen Code, 1440 Zyklen pro Tag
 when
    Time cron "5 * * * * ?" // minütlich zur 5. Sekunde
 then
    // Initialisieren und RTR1
    var Integer newMode = 2
    var Integer oldMode = 0
    var mode = (RTR1_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR1_Out.state instanceof Number) oldMode = (RTR1_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR1_Out.postUpdate(newMode)
    // RTR2
    newMode = 2
    oldMode = 0
    mode = (RTR2_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR2_Out.state instanceof Number) oldMode = (RTR2_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR2_Out.postUpdate(newMode)
    // RTR3
    newMode = 2
    oldMode = 0
    mode = (RTR3_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR3_Out.state instanceof Number) oldMode = (RTR3_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR3_Out.postUpdate(newMode)
    // RTR4
    newMode = 2
    oldMode = 0
    mode = (RTR4_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR4_Out.state instanceof Number) oldMode = (RTR4_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR4_Out.postUpdate(newMode)
    // RTR5
    newMode = 2
    oldMode = 0
    mode = (RTR5_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR5_Out.state instanceof Number) oldMode = (RTR5_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR5_Out.postUpdate(newMode)
    // RTR6
    newMode = 2
    oldMode = 0
    mode = (RTR6_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR6_Out.state instanceof Number) oldMode = (RTR6_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR6_Out.postUpdate(newMode)
    // RTR7
    newMode = 2
    oldMode = 0
    mode = (RTR7_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR7_Out.state instanceof Number) oldMode = (RTR7_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR7_Out.postUpdate(newMode)
    // RTR8
    newMode = 2
    oldMode = 0
    mode = (RTR8_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR8_Out.state instanceof Number) oldMode = (RTR8_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR8_Out.postUpdate(newMode)
    // RTR9
    newMode = 2
    oldMode = 0
    mode = (RTR9_In as DecimalType).toBigDecimal.toBigInteger
    if(mode.testBit(0) newMode = 1
    else if(mode.testBit(2)) newMode = 3
    else if(mode.testBit(3)) newMode = 4
    if(RTR9_Out.state instanceof Number) oldMode = (RTR9_Out.state as Number).intValue
    if(oldMode != newMode)
        RTR9_Out.postUpdate(newMode)
end
Zyklische Abfrage für alle Items in einr Rule, optimiert:

Code: Alles auswählen

rule "Betriebsarten RTR zyklisch" // 18 Zeilen Code, 1440 Zyklen pro Tag
 when
    Time cron "5 * * * * ?" // minütlich zur 5. Sekunde
 then
    gRTR_In.members.forEach[ rtrIn |
        var Integer newMode = 2
        val mode = (rtrIn.state as DecimalType).toBigDecimal.toBigInteger
        switch (mode) {
            case mode1.testBit(0) : newMode = 1
            case mode1.testBit(2) : newMode = 3
            case mode1.testBit(3) : newMode = 4
        }
        var Integer oldMode = 0
        val rtrOut = gRTR_Out.members.filter[ f | f.name.startsWith(rtrIn.name) ].head
        if(rtrOut.state instanceof Number) oldMode = (rtrOut.state as Number).intValue
        if(oldMode != newMode) rtrOut.postUpdate(newMode)
    ]
end
Eine Rule pro Itempaar - könnte man ebenfalls zyklisch laufen lassen, aber wozu? (nur eine Rule abgebildet):

Code: Alles auswählen

rule "Betriebsart RTR1"  // 9 x 15 Zeilen Code, Ausführung nach Bedarf
 when
    Item RTR1_In changed
 then
    var Integer newMode = 2
    val mode = (newState as DecimalType).toBigDecimal.toBigInteger
    switch (mode) {
        case mode.testBit(0) : newMode = 1
        case mode.testBit(2) : newMode = 3
        case mode.testBit(3) : newMode = 4
    }
    var Integer oldMode = 0
    if(RTR1_Out.state instanceof Number) oldMode = (RTR1_Out.state as Number).intValue
    if(oldMode != newMode) RTR1_Out.postUpdate(newMode)
end
Eine Rule für alle:

Code: Alles auswählen

rule "Betriebsarten RTR" // 17 Zeilen Code, Ausführung nach Bedarf
 when
    Member of gRTR_In changed
 then
    var Integer newMode = 2
    val mode = (triggeringItem.state as DecimalType).toBigDecimal.toBigInteger
    val iName = triggeringItem.name.split("_").get(0).toString
    switch (mode) {
        case mode.testBit(0) : newMode = 1
        case mode.testBit(2) : newMode = 3
        case mode.testBit(3) : newMode = 4
    }
    var myItem = gRTR_Out.members.filter[ f | f.name.startsWith(iName) ].head
    var Integer oldMode = 0
    if(myItem.state instanceof Number) oldMode = (myItem.state as Number).intValue
    if(oldMode != newMode) myItem.postUpdate(newMode)
end
Die ersten beiden Rules sind funktional identisch, die laufen einmal pro Minute, das heißt, wenn ich zur 6. Sekunde die Betriebsart wechsle, habe ich 59 Sekunden eine falsche Anzeige in openHAB. Andererseits werden diese Rules einmal pro Minute ausgeführt, die Betriebsart wechselt aber nur für einen Teil der RTR überhaupt, und dann höchstens vier Mal am Tag (manuelle Bedienung nicht mitgezählt, die kommt so gut wie nie vor)
Die getrennten Rules pro RTR sind ok, aber sie nehmen doch eine ganze Menge Raum ein (knapp 150 Zeilen Code mit jeweils einer Leerzeile zwischen den Rules).
Erst die letzte Variante nutzt das Potential der DSL einigermaßen aus. :)

Die zyklische Variante habe ich nie in Betracht gezogen :), aber die Variante mit Einzelrules hatte ich lange im Einsatz, bis die Möglichkeit des Member Triggers eingeführt wurde...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten