Seite 1 von 1

Gruppe aus Strings

Verfasst: 29. Aug 2019 14:57
von nikolaus-online
Hey liebe Leute,

seit ein paar Wochen setze ich jetzt openhab 2 auf einem Raspberry Pi 3 ein und bin von Tag zu Tag begeisterter. Nun bin ich auf ein Problem gestoßen, für das ich bislang noch keine einfache Lösung gefunden habe. Evtl. kann mir ja einer von euch dabei helfen:

Aufgabenstellung:
Ich habe an meinen Fenstern und Türen im Untergeschoss Kontaktschalter von Gigaset Elements installiert. Deren Öffnungszustand wird über ein einfaches Skript auf dem openhab-Server alle zehn Sekunden via mqtt ermittelt und in einen String (pro Fenster/Tür) geschrieben. Klappt auch super. Im String landet je nach Zustand der Wert "close" (Fenster/Tür zu), "open" (Fenster/Tür geöffnet) oder "tilt" (Fenster auf Kipp). So weit, so prima. Nun möchte ich gerne, wenn ich das Haus verlasse, eine Nachricht bekommen, falls noch Fenster geöffnet sind. Nun könnte ich natürlich eine Regel aufstellen, die so aussieht:

Code: Alles auswählen

rule "Fenster/Tür geöffnet?"
when
    Item 	Member of GSElements_TuF changed to "open" or
    		Member of GSElements_TuF changed to "tilt"
then
    if ((fenster1.state == "open") || (fenster1.state == "tilt")) {
      // Schalter setzen für Fenster 1 = ALARM
    }
    ... und so weiter für alle Fenster und Türen...
end
und dann nur noch abfragen, ob ein Fenster-Schalter gesetzt ist.

GSElements_TuF ist in diesem Fall eine Gruppe, die die Strings enthält.

Ich frage mich aber, ob das nicht auch eleganter geht. Für Switch oder Contact-Items geht das ja über ein Group-Item, dessen Zustand sich mit dem letzten Mitglied der Gruppe ändert. Geht das mit Strings auch irgendwie? Hat jemand eine Idee dazu?

Danke für eure Vorschläge!

Liebe Grüße,

Nikolaus

Re: Gruppe aus Strings

Verfasst: 29. Aug 2019 18:58
von udo1toni
Also, als erstes mal eine Bemerkung zu den drei Status: Es wäre besser, die Standard Status für Fenster zu nehmen:
OPEN, CLOSED und AJAR. Wenn Du diese Strings verwendest (und auch bitte nur Großbuchstaben verwendest), wird ein verknüpftes Icon window automatisch die korrekte Anzeige bringen, eben geöffnet, geschlossen oder gekippt.

Was Du mit "script... mqtt..." meinst, verstehe ich nicht so ganz, aber da dieser Teil wohl funktioniert, soll das hier keine Rolle spielen. Nur so viel: openHAB beherrscht mqtt eigentlich gut genug, um selbst auf per mqtt gelieferte topics zu reagieren. Aber vielleicht sendet ja Dein Script die Zustände per mqtt an openHAB? :)

Egal. Deine Rule soll unter zwei Bedingungen eine Nachricht verschicken:
  1. Du verlässt das Haus
  2. Niemand ist zuhause und der Zustand eines Fensterkontakts ändert sich
Entsprechend brauchst Du also ein Item, welches das Verlassen das Hauses meldet - ich nenne das Item jetzt mal Anwesenheit.

Code: Alles auswählen

rule "fensterzustand melden"
when
    Item Anwesenheit changed to OFF or       // Haus wird gerade verlassen
    Member of GSElements_TuF changed         // Zustand eines Kontakts hat sich geändert
then
    if(Anwesenheit.state == OFF && GSElements_TuF.members.filter[ i | i.state.toString != "CLOSED" ].size > 0) { // niemand zuhause und mindestens ein Kontakt meldet nicht "CLOSED"
        var String strList = ""                             // Variable initialisieren
        GSElements_TuF.members.filter[ i | i.state.toString != "CLOSED" ].forEach[ k | strList = strList + k.name + ", "] // Liste mit Elementen füllen
        sendNotification("Es ist noch mindestens ein Fenster unverschlossen: " + strList) // Meldung senden.
    }
end
Das sendNotification soll hier stellvertretend für beliebige Nachrichten stehen. Die ausgegebene Meldung schreibt alle Itemnamen hin, die sollten also passend gewählt sein. Wenn das nicht so einfach ist, z.B. weil man im Namen noch andere Dinge untergebracht hat, kann man auch nur einen Teil des Itemnamens verwenden. Dazu verwendet man dann split() und get(). Stell Dir vor, alle Namen folgen der Konvention Kontakt_Geschoss_Raum_Fensternummer, dann kann der String so zusammengesetzt werden:

Code: Alles auswählen

GSElements_TuF.members.filter[ i | i.state != "CLOSED" ].forEach[ k | strList = strList + k.name.split("_").get(1) + " " +
k.name.split("_").get(2) + " " + k.name.split("_").get(3) + ", "]
weil das Wort "Kontakt" hier unnötig ist.

Im If kannst Du auch sehen, dass Du leicht die Menge der Items einer bestimmten Sorte ausgeben kannst. Hier eine andere Rule:

Code: Alles auswählen

rule "genaue Information über alle Fenster"
when
    Member of GSElements_TuF changed
then
    var String strClosed = ""
    var String strOpen = ""
    var String strAjar = ""
    var Number nClosed = GSElements_TuF.members.filter[i | i.state == "CLOSED"].size
    var Number nOpen = GSElements_TuF.members.filter[i | i.state == "OPEN"].size
    var Number nAjar = GSElements_TuF.members.filter[i | i.state == "AJAR"].size
    GSElements_TuF.members.filter[i | i.state == "CLOSED"].forEach[k | strClosed = strClosed + k.name + ", "]
    GSElements_TuF.members.filter[i | i.state == "OPEN"].forEach[k | strOpen = strOpen + k.name + ", "]
    GSElements_TuF.members.filter[i | i.state == "AJAR"].forEach[k | strAjar = strAjar + k.name + ", "]
    logInfo("fensterinfo","{} Fenster geschlossen: {}",nClosed,strClosed)
    logInfo("fensterinfo","{} Fenster geöffnet: {}",nOpen,strOpen)
    logInfo("fensterinfo","{} Fenster geskippt: {}",nAjar,strAjar)
end

Re: Gruppe aus Strings

Verfasst: 1. Sep 2019 20:55
von nikolaus-online
Danke für die ausführliche Antwort! Ich werde mich gleich mal dran setzen.

Das mit dem Skript war etwas idiotisch formuliert. Es läuft halt eine Anwendung, die den Status der Fenster in Intervallen abfragt und an den MQTT-Broker übergibt. Für die Gigaset-Kontakte gibt es leider kein "offizielles Binding". Läuft aber soweit ziemlich gut.

Ich versuche mal mein Glück und melde mich wieder! 8-)

Re: Gruppe aus Strings

Verfasst: 1. Sep 2019 21:37
von nikolaus-online
Nochmals besten Dank! Funktioniert alles perfekt! :D

Re: Gruppe aus Strings

Verfasst: 2. Sep 2019 04:28
von udo1toni
Super. Da Du die Nachrichten, die auf mqtt gepostet werden, nicht direkt beeinflussen kannst, könntest Du das über ein Mapping machen. mqtt erlaubt es, einen TransformationService anzugeben, in diesem Fall also MAP. In der Datei stellst Du Eingangswerte und Ausgangswerte als Paare zusammen, dann klappt es auch mit den Standard Status (wegen des Icons...)