Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Absinthe
Beiträge: 78
Registriert: 16. Jan 2022 13:30

Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von Absinthe »

Hallo Forum,

ich denke aktuell darüber nach wie ich eine Nachricht erhalten könnte, wenn z.B. ein Switch über 12 Stunden z.B. "ON" ist oder ein Sensorwert z.B. >80 % über einen längeren Zeitraum überschritten wird.

Der Teil mit der Nachricht/Benachrichtung ist nicht das Problem ;) Allerdings finde ich gerade keine gute Lösung, um die etlichen Switche und Sensoren zu überwachen...

Erste Idee zu den Switchen wäre: Jedem Switch (das sind leider einige) ein Item mit Expiration Timer, welches beim Anschalten mit getiggert und beim Ausschalten eliminiert würde, zuzuordnen. --> Nicht schön, unübersichtlich und sehr aufwendig...

Zweite Idee wäre: Die zu überwachenden Switche einer Gruppe zu zuzuordnen. Leider bekomme ich dann nur eine Nachricht der Gruppe, nicht aber des Items, welches auslöst...

Leider habe ich noch keine Idee, wie ich das "ohne" massig Expiration Timer lösen könnte...

Zum Thema Sensorwert, dass, wenn ein Sensorenwert über einen Zeitraum über definierten Wert liegt, eine Benachrichtigung ausgelöst wird habe ich noch keine Idee...

Hat sowas von euch jemand schon ausprobiert und eine gute Lösung zur Hand? Bin für jeden Tipp dankbar ;)

Schöne Grüße
OpenHAB 4.1.1
in einem Docker-Container
auf einer Synology DS1515+

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

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von udo1toni »

Wenn der Zustand persistiert ist, kannst Du mit der Persistence herausfinden, wann der Zustand zuletzt geändert wurde.
Nun musst Du leider in einen sauren Apfel beißen, weil Du dies zyklisch prüfen musst.

Gehen wir einfach davon aus, dass die betreffenden Switch Items alle in der Gruppe gSense12hOn versammelt sind.
Nun sollte eine Rule ausreichen:

Code: Alles auswählen

rule "sense 12h ON"
when
    Time cron "17 * * * * ?" // minütlich bei Sekunde 17
then
    gSense12hOn.members.filter[k|k.state==ON].forEach[i|
        if(!(i.changedSince(now.minusHours(12))))
            logInfo("sense12h","Item {} ist seit mindestens 12 Stunden im Zustand ON!",i.name)
    ]
end
Es reicht, die eingeschalteten Items zu prüfen, deshalb der Filter.

Ähnlich funktioniert das Ganze für Wertüberschreitungen innerhalb einer Zeitspanne:

Code: Alles auswählen

rule "sense over 80"
when
    Time cron "18 * * * * ?" // minütlich bei Sekunde 19
then
    gSenseOver80.members.filter[k|k.state instanceof Number].filter[h|(h.state as Number).floatValue >= 80].forEach[i|
        if((i.minimumSince(now.minusHours(12)) as Number).floatValue >= 80)
            logInfo("senseover80","Item {} ist seit mindestens 12 Stunden über dem Schwellwert 80",i.name)
    ]
end
Der aktuelle Wert muss über 80 sein, sonst ist es nicht sinnvoll, auf ein Minimum über 80 zu prüfen. der Filter instanceof Number ist nicht zwingend notwendig, verhindert aber zumindest für Items, die gerade keinen Wert liefern, dass die Rule hängen bleibt.
Ich bin mir nicht sicher, was passiert, wenn ein Item innerhalb der Zeitspanne ungültige Werte geliefert hat, das müsste man mal prüfen.

Wie gesagt, die zu schluckende Kröte ist hier, dass die Rule zyklisch prüfen muss, ob der Zustand sich innerhalb der Zeitspanne geändert hat, dafür reichen aber wenige Zeilen Code :)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Absinthe
Beiträge: 78
Registriert: 16. Jan 2022 13:30

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von Absinthe »

Hallo udo1toni,

erst einmal und mal wieder - Vielen Dank!

Ich hab nun viel probiert... aber ich bekomme die schöne schlanke Lösung von dir einfach nicht zum Laufen...

Ich hatte dieses als .rules direkt im OH versucht als auch im Rules-Editor in OH... Leider kein Erfolg...

Die Fehlermeldung im Log ist leider auch wenig hilfreich...

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: Test_Test_Switch_1
      command: ON
    type: core.ItemCommandTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-2
          Group_Licht.members.filter[k|k.state==OFF].forEach[i|
        if(!(i.changedSince(now.minusSeconds(1)))
                      val mailActions = getActions("mail","mail:smtp:Test_SMTP")
                      val pushoverActions = getActions("pushover", "pushover:pushover-account:Test")
                      val String strMessage = "Testnachricht")
                      val success = mailActions.sendMail("mail@test.de", "openHab - Test", strMessage)
                      pushoverActions.sendPriorityMessage(strMessage,"Test",0)         
                      ]
    type: script.ScriptAction
Die Fehlermeldung im Log ist auch nur
2022-11-26 15:17:11.534 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Test_14' failed:
Eine Idee, woran dies liegen könnte?

-----

Zur Vollständigkeit: Wenn ich die Regel 1:1 als .Rules anlege erhalte ich auch eine Fehlermeldung.
2022-11-26 15:05:35.041 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'test_15.rules'
2022-11-26 15:05:35.167 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'test_15.rules' has errors, therefore ignoring it: [7,13]: missing ')' at 'logInfo'
OpenHAB 4.1.1
in einem Docker-Container
auf einer Synology DS1515+

Benutzeravatar
peter-pan
Beiträge: 2564
Registriert: 28. Nov 2018 12:03
Answers: 25
Wohnort: Schwäbisch Gmünd

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von peter-pan »

Code: Alles auswählen

if(!(i.changedSince(now.minusHours(12)))
es sieht so aus, als ob eine Klammer fehlt, wie es die Fehlermeldung sagt. Es ist aber etwas irritierend, da auf "logInfo" hingewiesen wird. Es ist nämlich in der Zeile davor - oder besser gesagt an der Stelle davor.

die Zeile sollte also so lauten:

Code: Alles auswählen

if(!(i.changedSince(now.minusHours(12))))
Ich hoffe das ist richtig !!
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.1.1 openhabian

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

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von udo1toni »

Die eine Klammer an der falschen Stelle ist schon mal ein guter Hinweis, aber es gibt noch einen weiteren Fehler, das hängt mit dem Erweitern des Codes zusammen. Die bedingte Verzeigung gilt immer und ausschließlich für den den nächsten Befehl. Trifft die Bedingung zu, wird der Befehl ausgeführt, ist die Bedingung nicht erfüllt, wird der Befehl übersprungen. Möchte man mehrere Befehle hintereinander bedingt ausführen, so muss dieser Code mittels {} zusammengefasst werden.
Weiterhin handelt es sich innerhalb der bedingten Verzweigung um einen anderen Kontext, alles, was in diesem Kontext passiert, hat außerhalb keine Wirkung. Das heißt, die lokale Konstante mailActions ist überhaupt nicht gültig, wenn sie verwendet wird.
Der Code sollte also eher so aussehen:

Code: Alles auswählen

Group_Licht.members.filter[k|k.state==OFF].forEach[i|
    if(!(i.changedSince(now.minusSeconds(1)))) {
        val mailActions = getActions("mail","mail:smtp:Test_SMTP")
        val pushoverActions = getActions("pushover", "pushover:pushover-account:Test")
        val String strMessage = "Testnachricht"
        val success = mailActions.sendMail("mail@test.de", "openHab - Test", strMessage)
        pushoverActions.sendPriorityMessage(strMessage,"Test",0)
    }
]
Natürlich wäre es sinnvoller, wenn es um mehrere Items geht, diese zunächst alle "einzusammeln" und anschließend nur eine Meldung zu generieren, in der alle Items gelistet sind, die "über die Zeit" sind.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Benutzeravatar
peter-pan
Beiträge: 2564
Registriert: 28. Nov 2018 12:03
Answers: 25
Wohnort: Schwäbisch Gmünd

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von peter-pan »

udo1toni hat geschrieben: 18. Nov 2022 20:44 Code: Alles auswählen

rule "sense 12h ON"
when
Time cron "17 * * * * ?" // minütlich bei Sekunde 17
then
gSense12hOn.members.filter[k|k.state==ON].forEach[i|
if(!(i.changedSince(now.minusHours(12)))
logInfo("sense12h","Item {} ist seit mindestens 12 Stunden im Zustand ON!",i.name)
]
end
...Sorry, ich dachte bei
Absinthe hat geschrieben: 26. Nov 2022 15:24 die schöne schlanke Lösung von dir
an das obige Script
Deshalb hab ich auf die Brackets der einzeiligen If-Bedingung nicht weiter geachtet :)
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.1.1 openhabian

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

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von udo1toni »

Oh, da hab ich mich oben auch verzählt... bis drei geht immer noch, aber vier...? (ich korrigiere das mal oben)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Absinthe
Beiträge: 78
Registriert: 16. Jan 2022 13:30

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von Absinthe »

VIELEN DANK!

Hast Du einen Tipp für mich, wo ich gewisse Grundlagen mit aneignen kann, wie z.B. das mit { } für mehrere Aktionen innerhalb der Schleife?

Jetzt hast Du mir den nächsten "Floh ins Ohr gesetzt"...
udo1toni hat geschrieben: 27. Nov 2022 02:41 [...]
Natürlich wäre es sinnvoller, wenn es um mehrere Items geht, diese zunächst alle "einzusammeln" und anschließend nur eine Meldung zu generieren, in der alle Items gelistet sind, die "über die Zeit" sind.
Da habe ich mal in einem bisherigen Projekt gespickt.

Code: Alles auswählen

var String strAlarmItem = ""                                                   

  Group_Licht.members.filter[k|k.state==OFF].forEach[i|
        if(strAlarmItem != ""){                                                             
          	 strAlarmItem  = strAlarmItem + ", "                                            
        	strAlarmItem  = strAlarmItem + triggeringItem.label  
        	}  
        if(!(i.changedSince(now.minusSeconds(1)))){
                      val mailActions = getActions("mail","mail:smtp:Mail_SMTP")
                      val pushoverActions = getActions("pushover", "pushover:pushover-account:Test")
                      val String strMessage = "Licht ist seit über 1 Sekunde an. Gemeldet hat:" + strAlarmItem + ". Status vom: "+newDateTimeType().format("%1$td.%1$tm.%1$ty %1$tH:%1$tM")
                      val success = mailActions.sendMail("mail@mail.de", "openHab - Hinweis", strMessage)
                      pushoverActions.sendPriorityMessage(strMessage,"openHab - Hinweis",0)         
                      }
                      ]
Dennoch bekomme ich es leider nicht zum Laufen :(
OpenHAB 4.1.1
in einem Docker-Container
auf einer Synology DS1515+

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

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von udo1toni »

Die Frage ist, was Du nun genau ausgeben willst. Deine Rule macht momentan Folgendes:
  1. Die Member der Gruppe Group_Licht werden nach den Items gefiltert, die gerade aus(!) sind.
  2. Für jedes dieser Elemente wird geprüft, ob die lokale Variable strAlarmItem nicht leer ist. Nur wenn dies der Fall ist (also nie...) wird ein Komma angehängt und das Label eingetragen.
  3. Anschließend wird für das aktuelle Item geprüft, ob es seit über einer Sekunde keine Änderung erfahren hat. Ist das der Fall werden die Nachrichten generiert, mit einer leeren Variablen strAlarmItem (siehe 2.).
Du generierst also weiterhin für jedes Item eine Nachricht, allerdings nur für die ausgeschalteten Items und da auch nur ohne eine Information welches Item es denn nun ist.

Nicht erschrecken, die Rule sieht kompliziert aus...

Code: Alles auswählen

val StringBuilder message = new StringBuilder()

val myList = Group_Licht.members.filter[light|light.state==ON && !light.changedSince(now.minusSeconds(1))]

if(myList.size == 0)
    return;

if(myList.size == 1)
    message.append("Das Licht ")
else
    message.append("Die Lichter ")

myList.forEach[light, element |
    if(element > 0) {
        if(element < myList.size - 1)
            message.append(", ")
        else 
            message.append(" und ")
    }
    message.append(light.label)
]

if(myList.size == 1)
    message.append(" ist ")
else
    message.append(" sind ")

message.append("seit mehr als einer Sekunde eingeschaltet. Nachricht von ")
message.append(newDateTimeType().format("%1$td.%1$tm.%1$ty %1$tH:%1$tM"))
message.append(" Uhr.")

val mailActions = getActions("mail","mail:smtp:Mail_SMTP")
val pushoverActions = getActions("pushover", "pushover:pushover-account:Test")
val success = mailActions.sendMail("mail@mail.de", "openHab - Hinweis", message.toString)
pushoverActions.sendPriorityMessage(message.toString,"openHab - Hinweis",0)
Was passiert:
  1. Ein lokales Objekt vom Typ StringBuilder wird angelegt. Das funktioniert ähnlich wie mit strMessage = strMessage + "mein Text", sieht aber etwas hübscher aus :) Das Auge codet ja mit...
  2. ein Lokales Objekt myList wird generiert. Es enthält alle Items der Gruppe Group_Licht, für die gilt, dass sie eingeschaltet sind und ihren Status seit mehr als einer Sekunde nicht geändert haben.
  3. Sollte diese Liste leer sein (size = 0) ist die Rule fertig und kann abgebrochen werden.
  4. befindet sich ein Element in der Liste, so muss der Text in der Einzahl verfasst werden, wir beginnen den Satz mit "Das Licht ". Ist mehr als ein Element in der Liste, so müssen wir in der Mehrzahl sprechen, also "Die Lichter "
  5. Die Liste wird durchlaufen. Dabei wird für jedes Element geprüft, ob es sich nicht um das erste Element handelt. Ist das der Fall, muss geprüft werden, ob es sich nicht um das letzte Element handelt. Ist das der Fall, so muss im Satz ein Komma folgen, ansonsten (letztes Element) das Wort " und ".
  6. Nun folgt das Label.
  7. Weiter mit Punkt 5 bis zum letzten Element der Liste
  8. Wie in Punkt 4 wieder die Unterscheidung Einzahl <-> Mehrzahl, diesmal entweder " ist " oder " sind "
  9. Satz beenden und noch die Info über den aktuellen Zeitpunkt ergänzen.
  10. Meldung ausgeben.
Wie gesagt geht das natürlich auch ohne StringBuilder, ich bin mir nicht sicher, wie das die Performance beeinflusst, die Funktion ist aber nett, weil so gut lesbar.

Ganz wichtig ist natürlich, dass die Ausgabe der Meldung außerhalb der Schleife passiert.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Absinthe
Beiträge: 78
Registriert: 16. Jan 2022 13:30

Re: Meldung wenn Sensorenwert oder Switch über Zeitraum X Stunden über Wert liegt?

Beitrag von Absinthe »

Mal wieder vielen, vielen Dank! Mega Lösung!

@udo1toni: Hast Du einen guten Tipp, wo und wie ich in die Programmierung einsteigen könnte, um das etwas besser zu lernen und von der Basis her zu verstehen?

Kleiner Nachtrag noch zur Lösung:

Code: Alles auswählen

message.append(newDateTimeType().format("%1$td.%1$tm.%1$ty %1$tH:%1$tM"))
hat bei mir einen Fehler ausgelöst. Ich hab dieses auf:

Code: Alles auswählen

        message.append(new DateTimeType().format("%1$td.%1$tm.%1$ty %1$tH:%1$tM"))
abgeändert damit es funktioniert.

Grüße
OpenHAB 4.1.1
in einem Docker-Container
auf einer Synology DS1515+

Antworten