script mit timer und gruppen

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
goerdi
Beiträge: 110
Registriert: 21. Dez 2019 23:44

script mit timer und gruppen

Beitrag von goerdi »

Hallo !

Ich will ein script mit einem Timer basteln (hab ich schon) allerdings bisher nur mit dem Trigger von einem Item.
Jetzt möchte ich das Ganze nur eben das mit If Member of <group> jetzt ist für mich die Frage .. wird wenn mehrer Items nacheinander Triggern und die Zeit von ersten nicht abgelaufen ist, wird da für jeden Trigger ein neuer Timer gestartet ?
ALs Beispiel:
ich wollte eine Gruppe von fenstern überwachen wenn sie zu lange auf sind... alle fenster sind in einer Gruppe.
Der Timer steht auf 5 Miniten.
Fenster 1 wird geöffnet und nach 3 Minuten Fenster 2 ..
Kriege ich dann für jedes Fenster mit entsprechendem Triggering Item eine Action ?

Gruss Gerd

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

Re: script mit timer und gruppen

Beitrag von udo1toni »

Ganz klare Antwort: Kommt auf Deinen Code an.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

goerdi
Beiträge: 110
Registriert: 21. Dez 2019 23:44

Re: script mit timer und gruppen

Beitrag von goerdi »

Hi !

Dachte ich mir schon.... wie müsste sowas etwa aussehen ?

Gruss Gerd

int5749
Beiträge: 1161
Registriert: 4. Nov 2019 22:08
Answers: 9

Re: script mit timer und gruppen

Beitrag von int5749 »

goerdi hat geschrieben: 30. Jan 2023 08:52 Hi !

Dachte ich mir schon.... wie müsste sowas etwa aussehen ?

Gruss Gerd
Poste doch mal Deinen bestehenden Code, ohne ist dies eine Glaskugel und passt evtl. nicht mit Deinem Ansatz.
openHAB 4.1.0 Release mit openHABian in einem Debian Bookworm (LXC) unter Proxmox 8.1.3

goerdi
Beiträge: 110
Registriert: 21. Dez 2019 23:44

Re: script mit timer und gruppen

Beitrag von goerdi »

hi !

also im Versuch bin ich aus Zeitgründen noch nicht weit fortgeschritten...
Aber ich denke das lediglich die Änderung des Triggers in einer laufenden rule nicht zielführend ist (zumal ich ja noch eine sepzifizierte Meldung möchte welches der Übeltäter ist und u.U. 1 Timer auch nicht reicht weil es können ja mehrere parallel offen sein.
das hier benutze ich und es funktioniert (aber halt nur 1 item)

Code: Alles auswählen

rule "Gefrierschranktuere Status"
when                                          
  Item TK_TUERE changed                        
then          
var Timer WindowTimer = null
Thread::sleep(3000)

  if(TK_TUERE.state != CLOSED) {

        WindowTimer = createTimer(now.plusMinutes(5), [|              
//        telegramAction.sendTelegram(612117303L, "Gefrierschranktüre zu lange offen!" )
        sendBroadcastNotification("Gefrierschranktüre 5 min offen!")
        WindowTimer = null
        hilfsVariable = 1
      ])                                                             
  } else {
      if (TK_TUERE.state == CLOSED) {
        if(WindowTimer !== null) {                                     
          WindowTimer.cancel                                      
          WindowTimer = null
        }
         if (hilfsVariable == 1) {
//          telegramAction.sendTelegram(612117303L, "Gefrierschranktüre wurde geschlossen!" )
          sendBroadcastNotification("Gefrierschranktüre wurde geschlossen!")
          hilfsVariable = null
        }
      }  
    }
end
Gruss Gerd

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

Re: script mit timer und gruppen

Beitrag von udo1toni »

Der Code funktioniert ziemlich sicher nicht (oder jedenfalls nicht so, wie Du Dir das vorstellst). Die Meldung wird ausgegeben werden, auch wenn die Tür längst geschlossen wurde. Der Grund hierfür: Du speicherst den Zeiger auf den Eintrag im Scheduler in einer lokalen Variable. Diese wird bei jedem Aufruf der Rule neu initialisiert, das heißt, Du legst schon mehrere Timer an, wenn Du die Tür auf-zu-auf-zu-auf machst.
Korrekte Lösung für einen Timer:

Code: Alles auswählen

// Globale Variablen vor der ersten Rule in der Datei definieren!
var Timer WindowTimer = null // Timer Variable muss global definiert werden!

rule "Gefrierschranktuere Status"
when
    Item TK_TUERE changed
then
    if(TK_TUERE.state != CLOSED) {                                                // Tür ist offen
        WindowTimer?.cancel                                                       // Timer entfernen, falls einer vorhanden ist
        WindowTimer = createTimer(now.plusMinutes(5), [|
            val telegramAction = "telegram:telegramBot:<uid>"                     // die Action muss zunächst initialisiert werden <uid> noch anpassen!
            telegramAction.sendTelegram("Gefrierschranktüre zu lange offen!")     // sendTelegram kennt nur einen Parameter!
            sendBroadcastNotification("Gefrierschranktüre 5 min offen!")
        ])
    else {                                                                        // Tür ist geschlossen
        if(WindowTimer?.hasTerminated) {                                          // Timer ist abgelaufen und Code wurde ausgeführt
            val telegramAction = "telegram:telegramBot:<uid>"                     // siehe oben. Keinesfalls global definieren!
            telegramAction.sendTelegram("Gefrierschranktüre wurde geschlossen!" )
            sendBroadcastNotification("Gefrierschranktüre wurde geschlossen!")
        }
        WindowTimer?.cancel                                                       // Timer entfernen, falls einer vorhanden ist
        WindowTimer = null                                                        // optional Aufräumen
    }
end
Die Rule triggert, wenn sich der Status des Items ändert.
Ist der Status nicht CLOSED, wird ein eventuell vorhandener Timer entfernt und ein neuer Timer angelegt. Danach ist die Rule beendet.

Ist der Status CLOSED, prüft die Rule, ob der Timer abgelaufen ist (dazu braucht es keine Hilfsvariable, aber wenn, dann müsste diese ebenfalls global definiert sein). Ist der Timer abgelaufen, wird die Abschlussmeldung generiert.
Egal ob der Timer abgelaufen ist oder nicht wird der Timer anschließend entfernt, falls noch vorhanden. Das ? bedeutet, dass die Methode .cancel nur aufgerufen wird, falls WindowTimer !== null ist (!== ist etwas anderes als !=)

Läuft der Timer ab, wird die Meldung ausgegeben.

Um das Ganze zu generalisieren brauchst Du einiges drum herum. Es geht los mit einer Hashmap, mit der Du auf die zu generierenden Meldungen zugreifen kannst. Weiterhin brauchst Du ein Array, in dem die Timer erzeugt werden. Je nach Anforderung kann es sein, dass Du noch zusätzliche Hashmaps brauchst, um z.B. die Timerdauer individuell setzen zu können.
In dem Zusammenhang könnte es auch interessant sein, die Außentemperatur zu berücksichtigen :)
Eventuell willst Du die Meldungen auch auf anderem Weg generieren, z.B. eine Liste aller geöffneten Fenster (und seit wieviel Minuten sie geöffnet sind, pro Fenster) statt Einzelmeldungen pro Fenster.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

goerdi
Beiträge: 110
Registriert: 21. Dez 2019 23:44

Re: script mit timer und gruppen

Beitrag von goerdi »

Hi !

also ich kann dir versichern dass es aktuell (in dieser Konstallation) so läuft... wenn die Türe aufgeht dauerts 5 min , dann krige ich ne popup meldung... und wenn sie wieder zu ist dann auch ..
aber dass da Unschärfen drin sind will ich ja nicht bestreiten..
Meine Frage zielt aber auf eine Lösung fuer eine Gruppe ab . Ein liste ist eher semi gut... weil da muss man ja ständig reinschauen.
Diese Woche hatte meine bessere Hälft "vergessen" das fenster in schlafzimmer zu schliessen... ich hab nur durch Zufall reingeschaut und gesehen das im Zimmer 7 Grad sind..... da hätte ich schon gerne ne Meldung....
Aber evtl ist das über die Zimmertemperatur einfacher zu realisieren..

Gruss Gerd

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

Re: script mit timer und gruppen

Beitrag von udo1toni »

Ja, keine Frage, wenn die Tür 5 Minuten auf ist gibt es eine Meldung. Aber was passiert, wenn die Tür nur 4 Minuten auf ist?

Die Quick-'n'-dirty Lösung lautet natürlich, für jeden Fensterkontakt (bzw. zumindest für jedes Zimmer) eine Rule anzulegen und für jede dieser Rules auch eine separate globale Timer Variable zu erzeugen. Glaub mir, lokal funktioniert es nicht.
Da es sich um Textdateien handelt, ist der Aufwand für diese Variante nicht mal sonderlich hoch, im großen und Ganzen kopierst Du die Rule und änderst lediglich die Items, die Timervariable und eventuell die Meldetexte. Und tatsächlich ist an dieser Lösung nichts auszusetzen, außer halt, dass es nicht sonderlich smart ist.

Die "schöne" Lösung läuft über Gruppen, Du legst also eine Gruppe mit allen Fensterkontakten an, die Rule triggert auf Member of GroupItem changed und kümmert sich dann innerhalb der Rule darum, alles passend zuzuordnen. Dafür muss aber drum herum einiges vorbereitet sein, z.B. müssen die Items so gestaltet sein, dass Du ein eindeutiges Merkmal hast, welches im Idealfall auch gut in der Rule verwendet werden kann. Im Allgemeinen wird man die Itemnamen so gestalten, dass die Raumnamen darin abgebildet sind, in der Form, dass alle Raumnamen eindeutig sind, also z.B. fenster_Wohnzimmer_1, fenster_Wohnzimmer_2, fenster_Flur, fenster_BadEG, fenster BadOG usw.
Nun muss ich in einer Rule nur den Itemnamen am _ separieren und habe den zweiten Teilstring als eindeutiges Identifikationsmerkmal. Mehr noch, falls ein Raum mehrere Fenster hat (hier das Wohnzimmer) kann ich gezielt alle Items dieses Raums selektieren und schauen, wieviele Fenster gerade offen sind. Einen laufenden Timer für den Raum beende ich dann nur, wenn die Anzahl der offenen Fenster 0 ist. Ist die Zahl größer als 0 muss ich nur prüfen, ob der Timer dieses Raums schon läuft und ihn gegebenenfalls anlegen und starten.
Aber wie gesagt braucht es halt ein wenig Beiwerk. Je nach gewünschter Komplexität lohnt sich das erst ab einer gewissen Anzahl Fenster, und auch dann muss man immer in Hinterkopf behalten, es geht nur darum, es "schön" zu lösen, die Variante mit mehreren Rules funktioniert genauso und hat erst mal keine funktionalen Defizite.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

goerdi
Beiträge: 110
Registriert: 21. Dez 2019 23:44

Re: script mit timer und gruppen

Beitrag von goerdi »

Wenn sie nur 4 Minuten auf ist ? dann kommt auch keine Meldung....

Gruss Gerd

int5749
Beiträge: 1161
Registriert: 4. Nov 2019 22:08
Answers: 9

Re: script mit timer und gruppen

Beitrag von int5749 »

goerdi hat geschrieben: 3. Feb 2023 08:30 Wenn sie nur 4 Minuten auf ist ? dann kommt auch keine Meldung....

Gruss Gerd
Ja, das glaube ich (fast) Aber Du nutzt die Timer-Action etwas falsch.

Wie Udo schon sagte, sollte ein Timer global definiert werden. Lokal kann ee funktionieren, tut es aber meistens nicht wie gewünscht.

Im Detail
Du überschreibst den Timer-Handle bei jedem mal, was dazu führt das dieser nicht mehr zu steuern ist.
Ja, es kommt keine Meldung, da Du u.a. mit einem Hilfsitem arbeitest und nur dann eine Meldung ausgibst webb die Tür schon zu lange geöffnet war.
Aber wenn nun zwischendurch die Türe mehrfach geöffnet würde, könnte dies anders aussehen.

Daher: Es ist nicht ganz sauber programmiert und kann bei längerer Nutzung zu Problemen führen ;-)

Besser ist es daher sauber zu steuern und wenn möglich auf "unnötige" Zusatzitems zu verzichten. <= Hier hat Udo ja schon ein schönes Beispiel gegeben.
openHAB 4.1.0 Release mit openHABian in einem Debian Bookworm (LXC) unter Proxmox 8.1.3

Antworten