Ankündigung

Einklappen
Keine Ankündigung bisher.

Gruppe geschlossen - Status ändern

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Gruppe geschlossen - Status ändern

    Guten Abend,

    ich habe seit neuestem den Homematic IP Schaltaktor für Markenschalter mit Signalleuchte - HmIP-BSL .

    Diese habe ich eingebunden im openhab, kann ihn schalten und auch die Farben richtig ansteuern. Wenn ich die Farben per "Test-Switch" über eine Rule steuere funktioniert es auch gut. Aber im Praktischen Ansatz finde ich irgendwie nicht die richtige Bedingung.

    Was soll geschehen?: Wir haben an jedem Fenster / Tür einen Türkontakt (im EG 5 Stück) Insofern die Fenster geöffnet werden, soll der untere Schalter "rot" leuchten und wenn die Fenster geschlossen wurden, wieder das Licht ausgehen. Der Schalter befindet sich an der Ausgangstür und man soll auf "einen Blick" sehen ob wirklich alle Fenster geschlossen sind wenn man geht.

    Wenn ein Fenster geöffnet wird funktioniert die Rule schonmal:

    Code:
    rule "Farbtest Flur Status auf"
    when Member of GruppeEGKontakte changed to OPEN
    then Flur_EG_Status_Farbe_unten.sendCommand("RED")
         Flur_EG_Status_Dimmer_unten.sendCommand(99)
    end
    Aber um das Licht wieder auszuschalten, finde ich keinen richtigen Trigger. Leider funktioniert mein Versuch:

    Code:
    rule "Farbtest Flur Status zu"
    when Item GruppeEGKontakte changed to CLOSED
    then Flur_EG_Status_Farbe_unten.sendCommand(OFF)
         Flur_EG_Status_Dimmer_unten.sendCommand(0)
    end
    nicht mit dem vorgegebenen Trigger (im Log finde ich nach dem schliessen des Fensters auch kein Update des Group Status.

    Wie kann ich das also lösen? (der untere Code funktioniert, wenn es von einem Switch getriggert wird)

    #2
    ich habe meinen Fehler gefunden!

    Die Gruppe war "falsch" deklariert. Diese hat anscheinend zwar für die reine "Gruppierung" gereicht, aber nicht richtig zum Status prüfen (das Symbol hatte sich auch nicht nach geöffnet und geschlossen geändert, sondern war dauerhaft grau)

    meine Gruppen definition mit:

    Code:
    Group GruppeEGKontakte
    war zu wenig.
    Es muss sein:
    Code:
    Group:Contact:OR(OPEN, CLOSED) GruppeEGKontakte
    Dann aktualisiert sich auch in der GUI der allgemeine Status der Gruppe auch.
    Jetzt funktioniert der Trigger auf:

    Code:
    rule "Farbtest Flur Status zu"
    when Item GruppeEGKontakte [B]received update[/B] CLOSED
    then Flur_EG_Status_Farbe_unten.sendCommand(OFF)
         Flur_EG_Status_Dimmer_unten.sendCommand(0)
    end

    Kommentar


      #3
      Also, die Rule hat einen Haken. das Problem ist, dass die Rule mehrfach ausgeführt wird, wenn ein einzelnen Kontakt betätigt wird, und zwar einmal pro Kontakt. Besser ist die Rule so:
      Code:
      rule "Farbtest Flur Status"
      when
          Member of GruppeEGKontakte changed
      then
          if(GruppeEGKontakte.members.filter[i|i.state != CLOSED].size > 0) {
              Flur_EG_Status_Farbe_unten.sendCommand(ON)
              Flur_EG_Status_Dimmer_unten.sendCommand(50)
          } else {
              Flur_EG_Status_Farbe_unten.sendCommand(OFF)
              Flur_EG_Status_Dimmer_unten.sendCommand(0)
          }
      end
      Die Rule zählt die Anzahl der Items, deren Zustand nicht CLOSED ist. Ist diese Zahl größer als 0, wird das Licht eingeschaltet, sonst wird es ausgeschaltet. Ob die werte so richtig sind (also die 50...) weißt natürlich nur Du.
      Diese Rule wird exakt einmal ausgeführt, wenn sich der Zustand eines Items in der Gruppe ändert.
      Es spielt nun auch keine Rolle mehr, wie die Gruppe definiert ist.

      Kommentar


        #4
        Zitat von udo1toni Beitrag anzeigen
        Besser ist die Rule so:
        Code:
        rule "Farbtest Flur Status"
        when
        Member of GruppeEGKontakte changed
        then
        if(GruppeEGKontakte.members.filter[i|i.state != CLOSED].size > 0) {
        Flur_EG_Status_Farbe_unten.sendCommand(ON)
        Flur_EG_Status_Dimmer_unten.sendCommand(50)
        } else {
        Flur_EG_Status_Farbe_unten.sendCommand(OFF)
        Flur_EG_Status_Dimmer_unten.sendCommand(0)
        }
        end
        Die Rule zählt die Anzahl der Items, deren Zustand nicht CLOSED ist.
        Kann es sein dass hier mit der if-Abfrage "if(GruppeEGKontakte.members.filter[i|i.state != CLOSED].size > 0) {" etwas nicht stimmt?
        Bei mir führt es immer in den if-Zweig, egal ob ich das Fenster auf oder zu mache.

        Code:
        rule "Fenster Benachrichtigung2"
        when
            Member of gKontakte changed
        then
            if(gKontakte.members.filter[i|i.state != CLOSED].size > 0){
                var Number n1 = gKontakte.members.filter[i|i.state != CLOSED].size // nur für den Test ob es auch zählt.
                logInfo("Fenster Benachrichtigung2","Zeit gestartet!", n1)
                Fenstertimer1 = createTimer(now.plusMinutes(30)) 
                 [ 
                  sendPushoverMessage(
                     pushoverBuilder("Fenster/Tür seit 30 Minuten geöffnet!")
                   )      
                ]
            } else {
                 logInfo("Fenster Benachrichtigung2","Zeit gestoppt!")
                Fenstertimer1 = null
            }
        end
        Das n1 müsste mir ja die Anzahl zurückgeben, oder? aber hier erhalte ich keinen Wert.

        Gruß Tom

        Kommentar


          #5
          Ich sehe da jetzt keinen Fehler.

          Ja, n1 sollte eine Anzahl liefern. Allerdings hast Du in der logInfo- Anweisung die {} vergessen. Der Timer wird, einmal gestartet, auf jeden Fall ausgeführt, weil das Löschen des Zeigers den Timer nicht löscht. Das geht anders:
          Code:
          var Timer tFenster = null
          
          rule "Fenster Benachrichtigung2"
          when
              Member of gKontakte changed
          then
              var Number n1 = gKontakte.members.filter[i|i.state != CLOSED].size // nur für den Test ob es auch zählt.
              logInfo("windowcontacts","Anzahl nicht geschlossener Fenster: {}", n1)
              if(n1 > 0 && tFenster === null){
                  logInfo("windowcontacts","Timer gestartet!")
                  tFenster = createTimer(now.plusMinutes(30))
                   [
                    sendPushoverMessage(
                       pushoverBuilder("Fenster/Tür seit 30 Minuten geöffnet!")
                     )
                    tFenster = null
                  ]
              } else if(n1 == 0){
                   logInfo("windowcontacts","Timer gestoppt!")
                   tFenster?.cancel
                   tFenster = null
              }
          end
          Zuletzt geändert von udo1toni; 22.03.2021, 19:46.

          Kommentar


            #6
            Zitat von udo1toni Beitrag anzeigen
            Ichsehe da jetzt keinen Fehler.
            Ich habe meinen Fehler gefunden, ich habe in der Gruppe gKontakte ein Item das OFF/ON meldet (händischer Schalter für Fenster offen).
            Daher muss meine IF-Bedingung so lauten:

            Code:
            if(gKontakte.members.filter[i|i.state == OPEN].size > 0 || gKontakte.members.filter[i|i.state == ON].size > 0){

            Kommentar


              #7

              Kommentar


                #8
                Zitat von udo1toni Beitrag anzeigen
                Code:
                vat Timer tFenster = null
                
                rule "Fenster Benachrichtigung2"
                when
                Member of gKontakte changed
                then
                var Number n1 = gKontakte.members.filter[i|i.state != CLOSED].size // nur für den Test ob es auch zählt.
                logInfo("windowcontacts","Anzahl nicht geschlossener Fenster: {}", n1)
                if(n1 > 0 && tFenster === null){
                logInfo("windowcontacts","Timer gestartet!")
                tFenster = createTimer(now.plusMinutes(30))
                [
                sendPushoverMessage(
                pushoverBuilder("Fenster/Tür seit 30 Minuten geöffnet!")
                )
                tFenster = null
                ]
                } else {
                logInfo("windowcontacts","Timer gestoppt!")
                tFenster?.cancel
                tFenster = null
                }
                end
                Habe heute festgestellt dass in dem Code noch ein Fehler steckt.
                Wenn 1 Fenster geöffnet wird und dann ein zweites Fenster geöffnet wird, wird die Zeit gestoppt, da tFenster nicht null ist. Somit läuft die Rule in den Else-Zweig.
                Code:
                if(n1 > 0 && tFenster === null){
                daher muss der else-Zweig so aussehen damit es funktioniert:

                Code:
                } else if (n1 == 0) {

                Kommentar


                  #9
                  Ja, vollkommen korrekt... Vorne ist auch noch ein Tippfehler drin... Ich habe die Rule oben angepasst, falls jemand das später findet...

                  Kommentar


                    #10
                    Hallo,

                    Ich habe hier noch eine Frage, ich würde die Rule gerne so abändern dass ich für die einzelnen Fensterkontakte unterschiedliche Zeiten zur Benachrichtigung definieren kann.
                    Wie kann ich das am besten realisieren?
                    Geht das am einfachsten mit einer sogenannten Hashmap?

                    Wenn JA, jemand eine Idee wie?

                    Code:
                    var Timer tFenster = null
                    
                    rule "Fenster Benachrichtigung2"
                    when
                        Member of gKontakte changed
                    then
                    
                    if (NotificationFenster.state == ON)
                    {
                        var Number n1 = gKontakte.members.filter[i|i.state == OPEN].size + gKontakte.members.filter[i|i.state == ON].size
                        logInfo("windowcontacts","Anzahl nicht geschlossener Fenster: {}", n1)
                        if(n1 > 0 && tFenster === null) {
                            logInfo("windowcontacts","Timer gestartet!")
                            tFenster = createTimer(now.plusMinutes([COLOR=#c0392b]30[/COLOR])) 
                             [ 
                              sendPushoverMessage(
                                 pushoverBuilder("Fenster/Tür seit [COLOR=#c0392b]30[/COLOR] Minuten geöffnet!")
                                .withTitle("Information")
                                .withPriority(1)
                                .withSound("gamelan")
                                )    
                                tFenster = null  
                            ]
                        } else if (n1 == 0) {
                             logInfo("windowcontacts","Zeit gestoppt")
                             tFenster?.cancel
                            tFenster = null
                        }
                    }
                    end

                    Kommentar


                      #11
                      Ja, eine Hashmap ist eine der Möglichkeiten dafür, Werte innerhalb einer Rule zu differenzieren. Aber gerade in diesem Fall frage ich mich, wie Du Dir das vorstellst. Die Rule meldet ja einfach ein geöffnetes Fenster/Tür, eine halbe Stunde nachdem das erste Fenster/Tür geöffnet wurde. Wenn Du individuell unterschiedliche Meldungen haben willst, musst Du letztlich für jeden Kontakt einen eigenen Timer vorsehen

                      Kommentar


                        #12
                        Zitat von udo1toni Beitrag anzeigen
                        Ja, eine Hashmap ist eine der Möglichkeiten dafür, Werte innerhalb einer Rule zu differenzieren. Aber gerade in diesem Fall frage ich mich, wie Du Dir das vorstellst. Die Rule meldet ja einfach ein geöffnetes Fenster/Tür, eine halbe Stunde nachdem das erste Fenster/Tür geöffnet wurde. Wenn Du individuell unterschiedliche Meldungen haben willst, musst Du letztlich für jeden Kontakt einen eigenen Timer vorsehen
                        Ja, das habe ich auch schon gemerkt, dass ich das so mit dieser Rule nicht hinbekomme. Ich möchte das auch nicht unbedingt über zig Timer machen, sondern mir den Zeitstempel speichern wann sich der Kontakt verändert hat und dann dementsprechend darauf reagieren. Hab da schon eine Idee.
                        Falls ich dazu dann noch Hilfe brauche würde ich einen neuen Thread aufmachen.

                        Kommentar


                          #13
                          Ich bin mir jetzt nicht zu 100% sicher, aber evtl. gibt es (Persistence für die betreffenden Items mal vorausgesetzt) die Eigenschaft changedSince. Dann könnte man eine Rule zyklisch laufen lassen, die für alle Fensterkontakte, die den Zustand OPEN melden, prüft, ob deren Zustand schon länger als 30 Minuten gleich ist. Es böte sich an, eine solche Rule z.B. alle 10 Minuten laufen zu lassen. Alle Fenster, die länger als 30 Minuten aber kürzer als 40 Minuten offen sind, werden dann gemeldet (sonst werden die gleichen Fenster alle 10 Minuten gemeldet). Das sähe dann grob so aus:

                          Code:
                          rule "Test open Windows"
                          when
                              Time cron "35 5/10 * * * ?" // alle 10 Minuten (von xx:x5:35 ab)
                          then
                              val String Liste = ""
                              gKontakte.members.filter[h|h.state == OPEN].forEach[i|
                                  if(i.changedSince(now.minusMinutes(40)) && !(i.changedSince(now.minusMinutes(30))))
                                      Liste = Liste + i.name + ", "
                              ]
                              if(Liste != "") {
                                  Liste = Liste.subString(0,Liste.length-2) // letztes Komma entfernen
                                  // send Message
                              }
                          end
                          Zuletzt geändert von udo1toni; 18.04.2021, 17:57.

                          Kommentar


                            #14
                            Zitat von udo1toni Beitrag anzeigen

                            Code:
                            rule "Test open Windows"
                            when
                            Time cron "35 5/10 * * * ?" // alle 10 Minuten (von xx:x5:35 ab)
                            then
                            val String Liste = ""
                            gKontakte.members.filter[h|h.state == OPEN].forEach[i|
                            if(i.changedSince(now.minusMinutes(40)) && !(i.changedSince(now.minusMinutes(30))))
                            Liste = Liste + i.name + ", "
                            ]
                            if(Liste != "") {
                            Liste = Liste.subString(0,Liste.length-2) // letztes Komma entfernen
                            // send Message
                            }
                            end
                            So bin nun endlich mal zum Testen gekommen, aber leider erhalte ich bei der Rule folgenden Fehler:

                            2021-05-07 17:38:55.968 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'temp3.rules', using it anyway:
                            Assignment to final variable
                            Constant condition is always false.
                            Assignment to final variable
                            2021-05-07 17:38:56.051 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'temp3.rules'
                            Bin auch dabei eine andere Rule zu testen, die gefällt mir ganz gut und funktioniert soweit, nur habe ich ein Fenster bei dem ich über einen Switch signalisiere dass dieses offen ist. D.h. ich bekomme hier nicht "OPEN" und "CLOSED" sondern "ON" und "OFF" gemeldet.

                            Wie muss ich diesen Abschnitt aus der Rule dafür anpassen? Sehe gerade dass ich diese Anpassung bei deiner Rule auch benötige.

                            Code:
                            gKontakte.members.filter[ i | i.state.toString() == 'OPEN'].forEach[i|
                            ...
                            ...
                            ]
                            Hier die komplette Rule:

                            Code:
                            // Die ursprüngliche Rule ist von hier -> https://www.forwardme.de/2019/10/03/offene-fenster-nie-wieder-vergessen-dank-openhab/
                            
                            var String logPrefix = 'Fensterüberwachung: '
                            var boolean log = true   
                            var boolean useBot = false
                            var String meldeText = ''  
                            var Number fensterOffenWarnungKueche = 40  
                            var Number fensterOffenWarnungKG = 40 
                               
                            rule "Fenster Benachrichtigung55"
                            when
                                 Time cron "0 0/1 * * * ?" // Alle 1 Minute
                            then
                                // Check ob Variablen passen, ansonsten defaultwert setzen
                                if ((NotificationFenster.state != OFF) && (NotificationFenster.state != ON)) {
                                    NotificationFenster.sendCommand(OFF)
                                    logInfo('rules', logPrefix + 'Setze Default-Wert für NotificationFenster=Aus')
                                }
                                if (fensterOffenWarnungTemperatur.state == NULL) {
                                    fensterOffenWarnungTemperatur.postUpdate(15)
                                    logInfo('rules', logPrefix + 'Setze Default-Wert für fensterOffenWarnungTemperatur=15')
                                }
                                if (fensterOffenWarnungMinuten.state == NULL) {
                                    fensterOffenWarnungMinuten.postUpdate(15)
                                    logInfo('rules', logPrefix + 'Setze Default-Wert für fensterOffenWarnungMinuten=15')
                                }
                            
                            
                                useBot = false
                                // Ist Benachrichtigung über offene Fenster aktiviert?
                                if (NotificationFenster.state == ON) {
                                    var Number n1 = gKontakte.members.filter[i|i.state == OPEN].size + gKontakte.members.filter[i|i.state == ON].size
                            
                                    if (n1 > 0) 
                                    {
                                        meldeText = ''   
                                        // zuerst schauen wir, ob Fenster noch in die Liste rein müssen, wenn noch nicht enthalten
                                        //gKontakte.members.filter[i|i.state.toString() == 'OPEN' + i.state.toString() == 'ON'].forEach[i| 
                                        gKontakte.members.filter[ i | i.state.toString() == 'OPEN'].forEach[i|
                                            var lastUpdate = i.lastUpdate("mapdb").toDateTime;
                                            // Ermitteln, wie lange in Sekunden das Fenster nun offen ist
                                            var long offenInMinuten = (now.getMillis() - lastUpdate.getMillis())/(1000*60);
                                            if (log) logInfo('rules', 'letztes Update von ' + i.name + ' (Status: ' + i.state.toString() + '): ' + lastUpdate + ' - offen seit Minuten: ' + offenInMinuten.toString())
                                            
                                            if ((offenInMinuten >= (fensterOffenWarnungKueche)) && (i.name == "EG_Kueche_Fenster" )) {
                                                meldeText+=i.name.toString() + ' seit ' + offenInMinuten + ' Minuten, '
                                                if (log) logInfo('rules', 'Test geklappt')
                                            }
                                            else if ((offenInMinuten >= (fensterOffenWarnungMinuten.state as DecimalType)) && (i.name != "EG_Kueche_Fenster" )) {
                                                meldeText+=i.name.toString() + ' seit ' + offenInMinuten + ' Minuten, '
                                            }
                            
                                            if ((offenInMinuten == (fensterOffenWarnungKueche)) && (i.name == "EG_Kueche_Fenster" )) {
                                                // Nun per Pushover warnen
                                                useBot = true                
                                            }
                                            else if ((offenInMinuten >= (fensterOffenWarnungMinuten.state as DecimalType)) && (i.name != "EG_Kueche_Fenster" )) {
                                                // Nun per Pushover warnen
                                                useBot = true 
                                            }
                                        ]
                                        if (meldeText != '')
                                        {
                                            // Meldetext erzeugen
                                            meldeText = 'Es sind Fenster/Türen offen: ' + meldeText.replaceAll('KG_','Kellergeschoß_').replaceAll('EG_','Erdgeschoß ').replaceAll('OG_','Obergeschoß ').replaceAll('_',' ') + ' bitte schließen!'
                            
                                            if (log) logInfo('rules', logPrefix + 'Meldung über offene Fenster wird erfolgen...')
                            
                                            if (useBot) {
                                               //  sendPushoverMessage(
                                               //     pushoverBuilder(meldeText)
                                               //     .withDevice("TomHandy")
                                               //     .withTitle("Information")
                                               //     .withPriority(1)             
                                               // ) 
                                               
                                                logInfo('rules', logPrefix + 'Meldung über offene Fenster wird gesendet...')
                                                if (log) logInfo('rules', logPrefix + meldeText)
                                            }
                                        }
                            
                                    }
                                    else 
                                    {
                                        if (log) logInfo('rules', logPrefix + 'Es sind keine Fenster/Türen offen!')
                                    }
                                }
                            end[COLOR=#d4d4d4] [/COLOR]

                            Kommentar


                              #15
                              Ja, Typo, es muss natürlich var statt val heißen. val -> Konstante, nicht veränderbar. var -> Variable, veränderbar.

                              Kommentar

                              Lädt...
                              X