OH3, Shelly 2.5 Grenzwertüberschreitung der Leistungsaufnahme soll Aktion auslösen

Geflasht oder ungeflasht ...

Moderator: seppy

Antworten
Benutzeravatar
kannznichkaufen
Beiträge: 38
Registriert: 11. Mär 2021 16:44
Wohnort: Wiege des Ruhrbergbaus
Kontaktdaten:

OH3, Shelly 2.5 Grenzwertüberschreitung der Leistungsaufnahme soll Aktion auslösen

Beitrag von kannznichkaufen »

OH3.

Anwendungsfall:
Nach dem jüngsten Hochwasser habe ich eine Tauchpumpe in einem Sickerschacht installiert.
Die Pumpe schaltet sich über einen Schwimmerschalter ein, sobald der Pegel ansteigt.
Ich möchte gerne benachrichtigt werden, wenn dieser Fall eintritt. Da an der Stelle, von der aus die Pumpe mit Strom versorgt wird, keine Verbindung zum KNX-Bus besteht, habe ich sie über einen Shelly 2.5 angeschlossen, der dauerhaft eingeschaltet ist.

Plan:
Die Shelly-Firmware bietet zwar keine Möglichkeit, bei Über-/Unterschreitung eines Schwellwertes eine Nachricht zu versenden, aber sie kann immerhin den Strom messen, der über das Relais fliesst.
Ich dachte mir, ich lege ein Item "Leistungsaufnahme" an, das ich mit dem Channel "meter2#currentWatts" des Shelly2.5-Things verbinde und lasse eine Rule bei jeder Veränderung des Wertes triggern.

Die Rule müsste den aktuellen Wert mit dem Schwellwert vergleichen und sich den vorherigen Wert merken, um zu unterscheiden, ob die Schwelle von unten oder von oben überquert wurde. Wenn der vorherige Wert unter und der aktuelle Wert über der Schwelle liegt, soll bspw. eine Mail versendet uind eine Status-LED im Haus aktiviert werden.
Wenn der vorherige Wert bereits über der Schwelle lag, braucht nicht getan werden.
Wenn der vorherige Wert über und der aktuelle Wert unter der Schwelle liegt, kann eine Mail zur Entwarnung versendet und die Status-LED wieder abgeschaltet werden.

Für die Benachrichtigung per Mail wäre vermutlich auch ein Timer sinnvoll, der den Fall abfängt, dass sich die Pumpe in kürzerer Zeit mehrfach ein- und ausschaltet.

Problem:
Ich habe noch keinen rechten Plan.

Kann mir jemand auf die Sprünge helfen, wie ich den meter2#currentWatts-Channel syntaktisch richtig auswerte?
Mit Timern habe ich bis auf eine Timer, der innerhalb einer Rule einfach vor dem nächsten Befehl eine Zeit abwartet, noch keine Erfahrung. Was ist sinnvoller?
- Die Rule von der Veränderung der gemessenen Leistung triggern lassen und ja nachdem, ob sich die Lage verändert hat, den Timer starten oder weiterlaufen lassen.
- Die Rule zyklisch ausführen und überprüfen lassen, ob sich die Lage verändert hat.

In beiden Fällen wird so wie ich das verstehe, jeweils eine neue Instanz der selben Rule gestartet. Kann die neue Instanz der Rule auf die Variablen zugreifen, in denen die vorherige Instanz die ermittelten Zustände gespeichert hat? Oder muss ich ein Hilfsitem anlegen, in dem die aktuelle Instanz der Rule den aktuellen Wert zum Abruf durch die Folgeinstanz ablegt?

Besten Dank für Rat und herzliche Grüße
Michael
openHAB 3.01 im Docker Container auf Unraid 6.9.1

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

Re: OH3, Shelly 2.5 Grenzwertüberschreitung der Leistungsaufnahme soll Aktion auslösen

Beitrag von udo1toni »

kannznichkaufen hat geschrieben: 3. Aug 2021 00:04 Ich dachte mir, ich lege ein Item "Leistungsaufnahme" an, das ich mit dem Channel "meter2#currentWatts" des Shelly2.5-Things verbinde und lasse eine Rule bei jeder Veränderung des Wertes triggern.
Ja, genau so geht das.
kannznichkaufen hat geschrieben: 3. Aug 2021 00:04 In beiden Fällen wird so wie ich das verstehe, jeweils eine neue Instanz der selben Rule gestartet.
Nope. Das war so in openHAB2 (und openHAB1). Dort gab es einen Thread Pool (default 5 + 2 Threads) der von allen Rules gemeinsam genutzt wurde.
In openHAB3 ist es jedoch meines Wissens so, dass es für jede Rule exakt einen Thread gibt, exklusiv. Das heißt aber auch, dass jede Rule immer nur exakt einmal (zeitgleich) läuft.

Also: Du verknüpfst den Channel currentWatts mit einem Number Item.
Danach steht Dir in openHAB der Wert zur Auswertung zur Verfügung.
Die nächste Frage wäre, was Du mit dem Timer erreichen willst - eine Begrenzung der Anzahl der Meldungen, oder auch eine Prüfung auf Mindestlaufzeit?

Code: Alles auswählen

var Long lWasserAlarm = null

rule "Wasser Alarm"
when
    Item Leistungsaufnahme changed
then
    if(!(Leistungsaufnahme.state instanceof Number))       // ungültiger Messwert?
        return;

    if((Leistungsaufnahme.state as Number).floatValue < 1) // Pumpe aus? (Wert sicher kleiner
        return;                                            // als Leistungsaufnahme der Pumpe)

    if(lWasserAlarm === null || lWasserAlarm < now.toInstant.toEpochMilli - 3600000) {
        lWasserAlarm = now.toInstant.toEpochMilli          // Zeitstempel erfassen
        // Benachrichtigung über laufende Pumpe
    }
end
In diesem Beispiel braucht es gar keinen Timer.

Die Rule triggert bei jeder Wertänderung der Leistungsaufnahme.
Ist der gemessene Wert ungültig, bricht die Rule ab.
Ist der gemessene Wert unterhalb des Leerlaufstroms (oder halt einem beliebig niedrigem Grenzwert) bricht die Ruleab.

Ist der Zeitstemepl in der globalen Variablen lWasserAlarm nicht initialisiert oder enthält einen Zeitstempel, der mehr als eine Stunde (3.600.000 Millisekunden) in der Vergangenheit liegt, wird die Meldung ausgegeben (hier nur als Kommentar, kommt ja darauf an, wie Du benachrichtigt werden willst).

Du kannst auch ein Item statt der globalen Variablen verwenden, das hat dann den Vorteil, dass Du den Zeitpunkt persistieren kannst. Auf der anderen Seite werden die Formeln komplexer, was eigentlich unnötig ist - wie oft startet man openHAB kurz nach dem ein Alarm ausgelöst wurde (und stört sich dann am zu schnellen nächsten Alarm...)?
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Benutzeravatar
kannznichkaufen
Beiträge: 38
Registriert: 11. Mär 2021 16:44
Wohnort: Wiege des Ruhrbergbaus
Kontaktdaten:

Re: OH3, Shelly 2.5 Grenzwertüberschreitung der Leistungsaufnahme soll Aktion auslösen

Beitrag von kannznichkaufen »

Danke Dir!

Mein Gedanke mit dem Timer zielte nur zum Teil darauf, eine zu häufige Benachrichtigung zu unterdrücken.
Die Dauer der Pumpenlaufzeit und die Häufigkeit des Wiedereinschaltens lassen ja Rückschlüsse darauf zu, wie sich der Grundwasserpegel entwickelt und ob weitere Maßnahmen erforderlich werden, um ein Ansteigen bis in den Keller zu vermeiden oder zumindest hinauszuzögern.
Das spricht dafür, ein persistiertes Item zu benutzen. Ich kann aber auch einfach das Item "Leistungsaufnahme" mit dem Wert in Watt persisitieren. Die resultierende Kurve gibt hinreichend Aufschluss. Hauptsache, ich kann nach der ersten Benachrichtigung die gespeicherten Ein- und Ausschaltvorgänge bzw. die Laufzeiten und Ruhepausen zwischen den Ein-/Aus-Zeitpaaren beobachten.
Ich hatte noch keine Gelegenheit, die neu installierte, gegenüber der vorherigen deutlich leistungsstärkere Pumpe unter Starkregenbedingungen zu beobachten. Ich rechne damit, dass sie zu Beginn einer Stark- oder Dauerregenphase in dem gemauerten Brunnenschacht zunächst ausreicht, den Wasserspiegel innerhalb einiger Minuten soweit zu reduzieren, dass der Schwimmerschalter vorübergehend wieder abschaltet und der Schacht sich dann mehr oder weniger schnell wieder füllt. Die Anteil der Laufzeit dürfte sich dann gegenüber dem der Ruhezeit nach und nach vergrößern. Je nachdem, was ich dann beim Blick in den Schacht sehe, kann es vielleicht noch etwas helfen, die Pumpe in eine größere Tiefe ablassen und andere Maßnahmen treffen, zusätzliche Pumpen einzusetzen oder Sachen in Sicherheit zu bringen.

Weil ich Einfachheit mit robuster und zuverlässig verbinde, scheint mir Dein Vorschlag mit der Variablen jedenfalls sehr gut.

Was mir noch nicht klar ist:
Du hast die Variable "lWasserAlarm" genannt. Ist das vorangestellte "l" eine von Dir geschätze Konvention (im Sinne das Long-Variablen immer mit l beginnen, damit der Variable ihr Typ anzusehen ist) oder folgt das einer Syntaxvorgabe?

Wenn ich die Rule über die grafische Oberfläche anlege, ist der Teil "when Leistungsaufnahme changed" bereits dort erledigt.
Kann ich die Deklaration einer globalen Variablen dann in einem Script vom Typ dsl.rule vornehmen?
Den Code des "then"-Blocks würde ich dann in dasselbe Script übernehmen?

Herzliche Grüße
Michael
openHAB 3.01 im Docker Container auf Unraid 6.9.1

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

Re: OH3, Shelly 2.5 Grenzwertüberschreitung der Leistungsaufnahme soll Aktion auslösen

Beitrag von udo1toni »

kannznichkaufen hat geschrieben: 6. Aug 2021 00:58 Du hast die Variable "lWasserAlarm" genannt. Ist das vorangestellte "l" eine von Dir geschätze Konvention (im Sinne das Long-Variablen immer mit l beginnen, damit der Variable ihr Typ anzusehen ist) oder folgt das einer Syntaxvorgabe?
Ersteres :) Man kann die Namen von Variablen und Konstanten frei wählen, die Bedingungen sind einzig: es darf kein Schlüsselwort verwendet werden und erlaubte Zeichen sind die Zeichen [a-z,A-Z] für das erste Zeichen und [a-z,A-Z,0-9,_] für die restlichen Zeichen. Groß/Kleinschreibung wird unterschieden (so wie bei Items und Things auch). Es ist nicht ratsam, eine Variable exakt wie ein Item zu benennen, da die Rules DSL die beiden Typen dann nicht sicher unterscheiden kann. ebenso isst es nicht ratsam, die Groß/Kleinschreibung als Unterscheidungsmerkmal zu nutzen, zu großes Risiko, da zu verwechseln...
kannznichkaufen hat geschrieben: 6. Aug 2021 00:58 Wenn ich die Rule über die grafische Oberfläche anlege, ist der Teil "when Leistungsaufnahme changed" bereits dort erledigt.
Kann ich die Deklaration einer globalen Variablen dann in einem Script vom Typ dsl.rule vornehmen?
Den Code des "then"-Blocks würde ich dann in dasselbe Script übernehmen?
Ja, das würde funktionieren, wenn da nicht das Detail mit der globalen Variablen wäre. Die UI Rules unterstützen keine globalen Variablen. Man kann Variablen lokal definieren und mit Umwegen den Wert aus dem vorigen Lauf reimportieren, ist aber umständlich (und ich habe das selbst noch nicht ausprobiert).
Wie oben erwähnt, kannst Du auch ein Item zum Speichern verwenden. Leider wird die Rule dadurch komplizierter. Für die Aufgabe, die Fördermenge abzuschätzen, könnte man ein Number Item verwenden, welches bei eingeschalteter Pumpe eine 1 enthält und bei ausgeschalteter Pumpe eine 0. Dieses Item persistierst Du, und zwar exakt jede Minute. Dann kannst Du z.B. mit der Funktion

Code: Alles auswählen

ed = Item.sumSince(now.minusMinutes(60))/60
die Einschaltdauer (in %) über die letzte Stunde ausgeben (das geht prinzipiell auch genauer, indem man die Speicherhäufigkeit erhöht und die Bemessung entsprechen ändert, also z.B. alle 10 Sekunden, dann steht eine 1 eben nur für 10 Sekunden Einschaltdauer, dann also mit minusMinutes(10) ODER Teiler 360. Allerdings wird das vermutlich vor allem viele Daten und eventuell auch Last erzeugen, ohne dass damit die Aussagekraft entscheidend verbessert wird. Als Nebenprodukt kannst Du die Einschaltdauer auch als Grafik darstellen. Das geht natürlich auch über die Leistungsaufnahme, die Einschaltdauer lässt sich so aber nicht so einfach feststellen.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Antworten