"Gelöst" Rolladenstopp über Leistung

Geflasht oder ungeflasht ...

Moderator: seppy

Antworten
urlauber22
Beiträge: 15
Registriert: 4. Aug 2021 18:15
Answers: 0

"Gelöst" Rolladenstopp über Leistung

Beitrag von urlauber22 »

Hallo,
Ich will mir über eine Regel per Email informieren lassen wenn die Leistung meines Rolladenmotors über 200 W geht.
Dazu habe Ich eine Regel generiert, die auch das Email auslöst, jedoch wird der Wert mit 200 ignoriert.
Es fallen bei einer Rollofahrt 132 W an.
Das Item ist als Number konfiguriert.
Kann mir da jemand weiterhelfen

Code: Alles auswählen

rule "DG Rolladen Erker Mitte"


when

        Item DG_Rolladen_Erker_mitte_Rollensteuerung_0offen_100geschlossen changed 

then

        if (DG_Rolladen_Erker_mitte_Stromverbrauch.state as Number > 200)
 
        return;
Zuletzt geändert von urlauber22 am 3. Apr 2025 18:38, insgesamt 1-mal geändert.

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

Re: Rolladenstopp über Leistung

Beitrag von udo1toni »

Hm, also abgesehen davon, dass die Rule unvollständig ist (es fehlt mindestens noch das end am Schluss) tut die Rule selbst mit end genau gar nichts, übersetzt lautet die Rule:

Falls sich der Zustand des Items DG_Rolladen_Erker_mitte_Rollensteuerung_0offen_100geschlossen geändert hat, prüfe, ob der Wert des Items DG_Rolladen_Erker_mitte_Stromverbrauch 200 überschreitet. Falls das zutrifft, brich die Verarbeitung der Rule ab.
Falls das nicht zutrifft, beende die Rule ebenfalls (weil Ende des Codes erreicht)

Ganz grundsätzliche Frage: handelt es sich um einen riesigen Holzrollladen? Weil: 132 Watt erscheint mir ehrlich gesagt etwas viel für einen Rollladenmotor.

Beim Casting (as Number) sollte der Wert grundsätzlich geklammert werden. Außerdem kann es dazu kommen, dass der Status des Items keine gültige Zahl enthält, dann wird das Ergebnis des Castings null sein (nicht 0, nicht NULL). Ein Vergleich auf größer oder kleiner mit null ist nicht zulässig, es kommt zur nullPointer Exception. Das möchte man unbedingt vermeiden :) entsprechend sollte der Code mindestens so aussehen:

Code: Alles auswählen

rule "DG Rolladen Erker Mitte"
when
    Item DG_Rolladen_Erker_mitte_Rollensteuerung_0offen_100geschlossen changed 
then
    if(!(DG_Rolladen_Erker_mitte_Stromverbrauch.state instanceof Number)) {
        logWarn("shutter","Leistungsmessung liefert keine Zahl! Abbruch der Rule")
        return;
    }
    if((DG_Rolladen_Erker_mitte_Stromverbrauch.state as Number).floatValue > 200) {
        // was soll passieren, wenn Leistung über 200 Watt?
    } else {
        // was soll passieren, wenn Leistung nicht über 200 Watt?
    }
end
Die Einschränkung auf .floatValue ist nicht unbedingt notwendig, stellt aber sicher, dass es sich auf jeden Fall um einen reinen Zahlenwert handelt, auch wenn später mal das Item auf UoM umgestellt werden sollte (Es ist angekündigt, dass in zukünftigen Versionen von openHAB der Datentyp zwingend QuantityType ist, falls der liefernde Channel QuantityType liefert, entsprechend ist es sinnvoll hier Vorsorge zu treffen).
Und natürlich muss man auch keine Meldung ins Log schreiben, ist halt nett, wenn man erfährt, warum die Rule abgebrochen wurde.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

urlauber22
Beiträge: 15
Registriert: 4. Aug 2021 18:15
Answers: 0

Re: Rolladenstopp über Leistung

Beitrag von urlauber22 »

Hallo udo1toni,

Danke für deine Antwort,
Hab mal den ganzen Code eingefügt.

Die Regel funktioniert fast.
Es gehen zwar mehrere Emails raus, aber damit kann ich leben, da es ja selten vorkommen sollte.
Ich kann sie nur mit dem ITEM "DG_Rolladen_Erker_mitte_Stromverbrauch" vernünftig verwenden. da der sich laufend ändert (triggert).
Bei anderen Items spricht sie nicht immer an.

Der Rolladen ist ein ganz normaler kleiner Rollo, über die shelly Anzeige werden tatsächlich 132 W angezeigt.

Ich habe mal den ganzen Code eingefügt.

Code: Alles auswählen

rule "DG Rolladen Erker Mitte"
when
    Item DG_Rolladen_Erker_mitte_Stromverbrauch changed 
then
    if(!(DG_Rolladen_Erker_mitte_Stromverbrauch.state instanceof Number)) {
        logInfo("shutter","Leistungsmessung liefert keine Zahl! Abbruch der Rule")
        return;
    }
    if((DG_Rolladen_Erker_mitte_Stromverbrauch.state as Number).floatValue > 150) {
        // was soll passieren, wenn Leistung über 150 Watt
        // es soll erst eine Meldung rausgehen wenn 150 Watt überschritten werden?
        logInfo("DG Rolladen Erker mitte", "Überlast!!")
             
    val mailActions = getActions("mail","mail:smtp:xxxx")
        mailActions.sendMail("xxx", "Störung Rolladen", "DG Rolladen Erker Mitte  Überlast.")
        
    }
end


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

Re: Rolladenstopp über Leistung

Beitrag von udo1toni »

Ich hab gerade mal nachgeschaut, und tatsächlich ist die Nennlast eines "gewöhnlichen" Rohrmotors z.B. 145 W. Und ich kann die Fahrt der Rollläden gut als Lastspitze im Stromverbrauch des Hauses sehen, weil halt alle Läden auf einen Schlag fahren - hätte ich nicht gedacht.

Trigger der Rule: ja, klar, die sicherste Variante ist tatsächlich, auf das zu messende Item zu triggern und nicht auf irgendwas anderes :)

Durch die Änderung des Triggers kannst Du die Rule vereinfachen (zumindest was die Schreibweise betrifft).
Was die mehrfach-Mails betrifft, so ist es vermutlich das beste, hier mit einem Timeout zu arbeiten.
Sobald Überlast erkannt wird, wird die Nachricht geschickt, gleichzeitig wird ein Flag gesetzt, welches nach Zeit x (am sichersten die normale Laufzeit des Motors plus etwas Karenz) wieder gelöscht wird, so:

Code: Alles auswählen

// globale Variablen müssen zu Beginn der Datei definiert werden (vor der ersten Rule)
var Timer tLastalarm = null // Timer für Überlast Alarm

rule "DG Rolladen Erker Mitte"
when
    Item DG_Rolladen_Erker_mitte_Stromverbrauch changed 
then
    if(!(newState instanceof Number)) {
        logInfo("shutter","Leistungsmessung liefert keine Zahl! Abbruch der Rule")
        return;
    }
    val nWatt = (newState as Number).floatValue
    if(nWatt > 150 && tLastalarm === null) {                                                 // === ist hier korrekt
        logWarn("shutter", "Überlast ({} W) Rollladen Erker Mitte!",newState)
        tLastalarm = createTimer(now.plusMinutes(2),[|tLastalarm = null])                    // Timeout Timer
        val mailActions = getActions("mail","mail:smtp:xxxx")
        mailActions.sendMail("xxx", "Störung Rolladen", "DG Rolladen Erker Mitte Überlast.")
    }
end
Zu Beginn wird eine globale Variable definiert, welche später als Zeiger auf den Timer für den Timeout dient. Diese muss vor der ersten Rule in der rules-Datei definiert werden
In den Rules gibt es diverse implizite Variablen, welche abhängig vom Trigger der Rule zur Verfügung stehen. Z.B. enthält die Variable newState bei jeder Rule, welche durch ein changed oder received update Ereignis getriggert wurde, den aktuellen Status des triggernden Items zum Zeitpunkt des Triggers.
Im Unterschied zu DG_Rolladen_Erker_mitte_Stromverbrauch.state enthält newState also einen statischen Wert, der sich garantiert während der Ausführung der Rule nicht ändert. Natürlich sollte das hier bei dieser Rule keine große Rolle spielen, aber dennoch...
Um die aktuelle Last mit ausgeben zu können, nutze ich eine lokale Konstante (nWatt). klar, man könnte auch den Wert dirkt verwenden, schließlich ist er ja statisch, aber so spart man ein paar Zeichen (und während der Ausführung muss der Wert nur einmalig abgefragt werden - Zugriffe auf lokale Konstanten sollten wesentlich flotter sein als der Zugriff auf Items. Auch hier geht es höchstens um eine ms, aber dennoch...
logWarn() gibt eine Warnmeldung im Log aus. Alle Logbefehle erwarten zwei Strings als Argumente, dabei ist der erste String der Name des Loggers. Auch wenn openHAB Leerzeichen und Sonderzeichen hier verarbeiten kann, ist das keine gute Idee. Über den Loggernamen kann man nämlich das Verhalten des Loggers steuern, hier kann man z.B. die obere Meldung unterdrücken, die untere wird aber weiterhin ausgegeben (ohne den Code zu ändern und damit ohne Neueinlesen der rules-Datei).
Der Loggername sollte keine Leer- oder Sonderzeichen enthalten, er sollte kurz sein und sich am allgemeinen Namensschema von openHAB orientieren, d.h. CamelCaseSchreibweise. Der vollständige Loggername lautet hier übrigens org.openhab.core.model.script.shutter, alle Logger aus DSL Rules haben den vorderen Teil gemein (also bis incl. script.) Entsprechend braucht es auch kein "rule" oder so zur Identifikation.
Die Zeile

Code: Alles auswählen

        tLastalarm = createTimer(now.plusMinutes(2),[|tLastalarm = null])
Legt einen Timer im Scheduler an, der Scheduler führt den im Lambda übergebenen Code zur angegebenen Zeit aus, hier also nach zwei Minuten den Befehl tLastalarm = null. Da diese Variable der Zeiger auf den Timer ist, wird die Variable also beim Start des Timers gesetzt und beim Ablauf wieder geleert, das reicht zur Steuerung aus.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

urlauber22
Beiträge: 15
Registriert: 4. Aug 2021 18:15
Answers: 0

Re: Rolladenstopp über Leistung

Beitrag von urlauber22 »

Das ist ja super, soweit hab ich alles verstanden und ist einleuchtend.
Jetzt habe ich nur noch eine Frage, was machen die 3 === Zeichen?

Code: Alles auswählen

if(nWatt > 150 && tLastalarm === null) {                                                 // === ist hier korrekt
Gruß

EmptySoft
Beiträge: 246
Registriert: 7. Jan 2020 14:45
Answers: 2
Kontaktdaten:

Re: Rolladenstopp über Leistung

Beitrag von EmptySoft »

urlauber22 hat geschrieben: 27. Mär 2025 09:32 Jetzt habe ich nur noch eine Frage, was machen die 3 === Zeichen?

Code: Alles auswählen

if(nWatt > 150 && tLastalarm === null) {                                                 // === ist hier korrekt
bei Prüfung ob der Wert null ist sind === zu verwenden, ansonsten == ob Wert gleich Wert
BYe
Harald

urlauber22
Beiträge: 15
Registriert: 4. Aug 2021 18:15
Answers: 0

Re: Rolladenstopp über Leistung

Beitrag von urlauber22 »

Danke

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

Re: Rolladenstopp über Leistung

Beitrag von udo1toni »

Um das noch etwas auszuführen ;)

= -> Wertzuweisung. a = b -> a nimmt den Wert von b an.
== -> Vergleich auf Gleichheit. a == b -> Wahr, falls a gleich b ist, unwahr, falls a ungleich b ist.
=== -> Vergleich auf Identität. Dieser spezielle Vergleich benötigt noch eine Erläuterung, in der DSL wird dieser Vergleich nur mit null verwendet, also a === null -> wahr, falls a identisch mit null ist.

Dazu muss man wissen, dass null (nicht 0, nicht NULL) ein sehr spezieller Wert ist, nämlich die Abwesenheit jeglichen Wertes.
Eine Variable speichert ihren Wert im RAM des Rechners. Nun ist es aber so, dass eine Speicherzelle im RAM nicht "keinen" Wert annehmen kann. Man könnte auf die Idee kommen, und einen ganz bestimmten Wert als "null" definieren, aber was, wenn genau dies der Wert ist, den die Variable enthalten soll?
Deshalb wird dieses Problem anders gelöst. Jede Variable ist in Wirklichkeit ein Zeiger auf eine Stelle im RAM, an der die eigentlichen Daten gespeichert sind. Wird die Variable geleert, so wird der Zeiger "verstellt", und zwar genau auf eine ganz bestimmte Speicherzelle.
Der Vergleich === prüft tatsächlich, ob die Zeiger der beiden Variablen auf den gleichen Speicherplatz verweisen, womit dann beide Variablen den identischen Wert referenzieren.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten