Nie wieder mit Licht an oder Fenster offen aus dem Haus

Wer kennt das nicht, man geht aus dem Haus und fragt sich, waren wirklich überall auch die Lichter aus? Oder man sitzt in der Arbeit, es beginnt zu regnen und man fragt sich, ob wirklich auch das Fenster im Dachgeschoss zu war? Klar kann man das auch vom Handy aus sehen, wenn die entsprechenden Sensoren vorhanden sind – aber leider schließt sich das Fenster ja auch nicht von alleine…

Um hier auf Nummer sicher zu gehen habe ich hier auch mein Smart Home bemüht. Ziel war es, an den Haus-Ausgängen ein visuelles Signal zu erhalten, wenn irgendwo noch ein Licht an ist oder ein Fenster offen ist.

Konkret soll ein Lichtschalter, der selbst leuchten kann, bei den Eingängen wie folgt eine bestimmte Farbe haben:

Fenster
offen
Fenster
gekippt
Licht anResultat
(Farbe)
Resultat:
( Helligkeit)
neinneinneinnichtsnichts
janeinneinblauhoch
neinjaneinblaugering
neinneinjagelbhell
janeinjarothell
neinjajarotgering
jajajarothell

Einfach gesagt: Ist ein Fenster gekippt, leichtes blau, ist es offen helles blau. Ist nur ein Licht an, dann gelb. Ist Licht noch an und Fenster noch auf: Rot.

Die passende „Hardware“…

Die Visualisierung selbst soll über zwei Homematic IP Schaltaktoren mit Signalleuchte passieren. Diese haben zwei „Dimmer“, mit welchem man das obere und das untere LED-Feld mit einer gewünschten Helligkeit ansteuern kann und die beiden Felder können zudem noch mit einer bestimmten Farbpalette angesteuert werden.

Eingebaut sind bei mir zwei – einer in meinem Ausgang im Keller zur Tiefgarage und einer neben der regulären Haustüre. Zur Ansteuerung des Aktors habe ich hier bereits etwas geschrieben.

Nun zu den Fenstern: Als Sensoren dachte ich zuerst an Fenster-Kontakte. So einen hatte ich auch bereits in meinem Briefkasten-Projekt verbaut. Aber die registrieren leider nur zwei Zustände – offen oder zu. Oft genug kam es auch schon mal vor, dass die Kinder die Terrassentür nur zugeschoben hatten und nicht mit dem Griff geschlossen hatten. Diesen Fall hätten die Sensoren nicht erkannt und die Griffstellung sollte unbedinggt mit berücksichtigt werden.

Dann bin ich auf Homematic IP an den Fenstern Fenstergriff-Sensoren aufmerksam geworden. Diese habe ich nun auch im Einsatz (es gibt auch die Bidcos-Variante, aber die benötigt andere Batterien) und diese Sensoren greifen die Griffstellung ab und erkennen damit nicht nur „offen“ und „geschlossen“ sondern auch den Zustand „gekippt“. Alle relevanten Fenster habe ich dann damit ausgerüstet.

Reichweitenproblem beheben…

Ansonsten habe ich fast nur Homematic bidcos im Einsatz. Ich weiß nicht, ob es daran liegt, aber die Fenstergriff-Sensoren, die im Dachgeschoss verbaut waren, haben die Zentrale nicht mehr erreicht. Der richtige Fenster-Zustand wurde zwar gesendet und kam auch an, aber die Sensoren quitierten mit rotem Blinken stets einen Fehler. Einfach gesagt: Die Reichweite war wohl nicht (gut) genug.

Daher habe ich kurzerhand im ersten Stock noch eine Homematic IP Schaltsteckdose verbaut, welche als Router fungiert und die Signale mit minimaler Verzögerung weiterleitet. Diese Routing-Funktion empfinde ich durchaus als Vorteil gegenüber bidcos. Problem war gelöst – alle Sensoren kommen nun bis zur Zentrale und umgekehrt kommt von der Zentrale auch bei allen Sensoren alles an.

Wie wird es umgesetzt?

Alle derartigen Fenstergriff-Kontakte befinden sich in einer Gruppe. Ändert ein Sensor seinen Wert, dann wird geprüft, wie viele Fenster gekippt und wie viele offen sind. Parallel dazu wird geprüft, welche Lichter, die nicht automatisch von Bewegungsmeldern geschalten werden, an sind.

Auf ein Einstellen der items-Datei verzichte ich an der Stelle – wichtig ist nur, dass alle Fenster der Gruppe „gruppeFensterAlle“ zugeordnet sein.

Rules-Datei für Anzahl offener und gekippter Fenster

rule "Anzahl offener Fenster ermitteln"
when
    Member of gruppeFensterAlle changed
then
    var Integer zaehlerOffen = 0
    var Integer zaehlerGekippt = 0
    var Integer zaehlerOffenOderGekippt = 0
    gruppeFensterAlle.members.forEach[i|
        if ((i.state.toString() == 'OPEN') || (i.state.toString() == 'TILTED')) {
            zaehlerOffenOderGekippt = zaehlerOffenOderGekippt + 1
        }
        if (i.state.toString() == 'OPEN')  {
            zaehlerOffen = zaehlerOffen + 1
        }
        if (i.state.toString() == 'TILTED')  {
            zaehlerGekippt = zaehlerGekippt + 1
        }
    ]
    if (fensterOffen.state != zaehlerOffen) {
        fensterOffen.postUpdate(zaehlerOffen)
    }
    if (fensterGekippt.state != zaehlerGekippt) {
        fensterGekippt.postUpdate(zaehlerGekippt)
    }
    if (fensterOffenOderGekippt.state != zaehlerOffen) {
        fensterOffenOderGekippt.postUpdate(zaehlerOffenOderGekippt)
    }

end

Damit haben wir immer die Anzahl der offenen, offenen oder gekippten bzw. nur gekippten Fenster und können damit weiterarbeiten. Das Gleiche benötigen wir dann noch für die Lichter. Lichter, die unberücksichtigt bleiben sollen, weil sie z.B. rein von Bewegungsmeldern geschalten oder durch Timer selbst wieder ausgeschalten werden, sollen jedoch unberücksichtigt bleiben.

Alle Lichter müssen in der Gruppe „licht“ stecken. Alle, die durch PIR-Sensoren o.ä. geschalten werden, zusätzlich in der Gruppe „lichtPIR“.

Rules-Datei für Anzahl geschaltener Lichter:

var boolean log = false
val String logPrefix = 'Lichtschalter - '

rule "Lichstatus hat sich verändert"
when 
    Member of licht changed
then
    // Sind alle lichter aus? Dann Signalisieren
    var Integer zaehlerLichtAlle = 0
    var Integer zaehlerLichtNurAutomatik = 0

    lichtPIR.members.forEach[i|
        // Bei Dimmer > 0 ansonsten != ON
        var boolean lichtIstAn = false
        if (i.state instanceof Number) {
            if (i.state > 0) {
                lichtIstAn = true
            }
        }
        else {
            if (i.state == ON) {
                lichtIstAn = true
            }
        }
        if (lichtIstAn) {
            zaehlerLichtNurAutomatik = zaehlerLichtNurAutomatik + 1
            if (log) logInfo('rules', logPrefix + 'Licht (mit automatik) gefunden und gezaehlt: ' + i.name.toString())
        }
    ]

    licht.members.forEach[i|
        var boolean lichtIstAn = false
        if (i.state instanceof Number) {
            if (i.state > 0) {
                lichtIstAn = true
            }
        }
        else {
            if (i.state == ON) {
                lichtIstAn = true
            }
        }
        if (lichtIstAn) {
            zaehlerLichtAlle = zaehlerLichtAlle + 1
            if (log) logInfo('rules', logPrefix + 'Licht (mit oder ohne automatik) gefunden und gezaehlt: ' + i.name.toString())
        }
    ]
    
    var Integer zaehlerLichtKeineAutomatik = Integer::parseInt(zaehlerLichtAlle.toString()) - Integer::parseInt(zaehlerLichtNurAutomatik.toString())
    
    // Status updaten
    if (lichtAnKeineAutomatik.state != zaehlerLichtKeineAutomatik) {
        lichtAnKeineAutomatik.postUpdate(zaehlerLichtKeineAutomatik)
    }
    if (lichtAnNurAutomatik.state != zaehlerLichtNurAutomatik) {
        lichtAnNurAutomatik.postUpdate(zaehlerLichtNurAutomatik)
    }
    if (lichtAnAlle.state != zaehlerLichtAlle) {
        lichtAnAlle.postUpdate(zaehlerLichtAlle)
    }
end

Nun haben wir auch die passenden Werte für die Lichter. Im Nachfolgenden wird das dann zusammengeführt.

Rule für das Erkennen von offenen Fenstern und angeschaltenen Licht und Ansteuerung des

var boolean log = false
val String logPrefix = 'Lichtschalter - '

rule "Signal-LEDs schalten am Lichtschalter"
when
    Item lichtAnKeineAutomatik changed or
    Item fensterOffen changed or
    Item fensterGekippt changed
then
    var boolean anzeigeLichtAn = false
    var boolean anzeigeFensterOffen = false
    var boolean anzeigeFensterGekippt = false
    if (log) logInfo('rules', logPrefix + 'Prüfe auf eventuell zu ändernde Lichtschalter-Farbe')
    if (lichtAnKeineAutomatik.state > 0) {
       if (log) logInfo('rules', logPrefix + 'Es sind NICHT alle manuell zu schaltenen Lichter aus')
       anzeigeLichtAn = true
    } else {
        anzeigeLichtAn = false
    }
    if (fensterOffen.state > 0) {
        anzeigeFensterOffen = true
    } else if (fensterGekippt.state > 0) {
        anzeigeFensterGekippt = true
    }

    // Nun alle Status bekannt => Anzeige entsprechend vornehmen
    // Lichter aus aber Fenster gekippt: 20% blau
    // Lichter aus aber Fenster offen:  100% blau
    // Lichter an aber Fenster alle zu: 20% gelb
    // Lichter an und Fenster gekippt: 20% violett
    // Lichter an und Fenster offen: 100% violett

    if (!anzeigeLichtAn && anzeigeFensterGekippt) {
        if (log) logInfo('rules', logPrefix + 'Es sind alle manuell zu schaltenen Lichter aus aber Fenster gekippt')
        farbschalter_unten_helligkeit.postUpdate(20)
        farbschalter_unten_farbe.postUpdate("BLUE")
    } else  if (!anzeigeLichtAn && anzeigeFensterOffen) {
        if (log) logInfo('rules', logPrefix + 'Es sind alle manuell zu schaltenen Lichter aus aber Fenster geöffnet')
        farbschalter_unten_helligkeit.postUpdate(99)
        farbschalter_unten_farbe.postUpdate("BLUE")
    } else  if (anzeigeLichtAn && !anzeigeFensterOffen && !anzeigeFensterGekippt) {
        if (log) logInfo('rules', logPrefix + 'Es sind  manuell zu schaltenen Lichter an und alle Fenster geschlossen')
        farbschalter_unten_helligkeit.postUpdate(20)
        farbschalter_unten_farbe.postUpdate("YELLOW")
    } else  if (anzeigeLichtAn && anzeigeFensterGekippt) {
        if (log) logInfo('rules', logPrefix + 'Es sind  manuell zu schaltenen Lichter an und Fenster gekippt')
        farbschalter_unten_helligkeit.postUpdate(20)
        farbschalter_unten_farbe.postUpdate("RED")
    } else  if (anzeigeLichtAn && anzeigeFensterOffen) {
        if (log) logInfo('rules', logPrefix + 'Es sind manuell zu schaltenen Lichter an und Fenster geöffnet')
        farbschalter_unten_helligkeit.postUpdate(99)
        farbschalter_unten_farbe.postUpdate("RED")
    } else {
        if (log) logInfo('rules', logPrefix + 'Es sind alle manuell zu schaltenen Lichter aus und alle Fenster geschlossen')
        farbschalter_unten_farbe.postUpdate("BLACK")
    }
end

Das war’s dann auch schon – Nun erkennt man beim Verlassen des Hauses sofort, ob ein Fenster noch gekippt oder gar offen ist und ob ein Licht vergessen wurde auszuschalten. Für letzteres habe ich mir dann eine „Leaving-Home-Funktion“ gebaut, welche auf Tastendruck alle Lampen im Haus ausschaltet.

Tatsächlich war zwar der Farbcode am Anfang etwas gewöhnungsbedürftig, aber die Funktion hat ihren Sinn schon ein paar mal erfüllt….

Viel Spaß damit – falls Du Anregungen hast oder etwas hier nützlich war für Dich, dann freue ich mich natürlich über Kommentare!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.