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 an | Resultat (Farbe) | Resultat: ( Helligkeit) |
nein | nein | nein | nichts | nichts |
ja | nein | nein | blau | hoch |
nein | ja | nein | blau | gering |
nein | nein | ja | gelb | hell |
ja | nein | ja | rot | hell |
nein | ja | ja | rot | gering |
ja | ja | ja | rot | hell |
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 (Link zu ELV, Link zu etwas günstigerem ELV 3er-Set) 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 (Link zu ELV, Link zu günstigerem ELV-Bausatz) 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 (Link zu ELV) 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!