Intro: Meine OH 3 Umgebung läuft auf einem Windows 10 Rechner, da ich kein Linuxer bin
scheinbar gab es im vergangenen Jahr dann noch einmal Interesse an der von mir genutzten und mit Hilfe dieses und des KNX-USER-FORUM (und einen besonderen Dank an Udi1Toni) entwickelten Anwesendheitssimulation. Daher möchte ich dies hier noch einmal in Summe vorstellen. Ziel sollte es sein, eine möglichst automatische (smarte) Steuerung zu erreichen und bisher läuft dies bei uns seit mittlerweile fast 3 Jahren ohne Probleme und seit einigen Tagen nun auch unter openHAB 3
Zur Präsenzerkennung nutze ich das TR-064 Binding für die Fritzbox. Die Zeit - bis eine Statusänderung erkannt wird - liegt bei wenigen Minuten, was aber für mich völlig akzeptabel ist. Da das WLAN bis auf die Strasse reicht, werden wir bereits bei Annäherung an das Haus erkannt und die Simulation meist mit betreten des Hausflurs beendet.
iOS Info: Mittlerweile gibt es in iOS eine Hardware und eine private MAC pro WLAN, welche aber dann auch immer gleich ist. Damit die Geräte immer erkannt werden, wurden beide MACs im TR-064 Binding bekannt gegeben und ich prüfe auf eine Gruppe.
Anwesendheitssimulation: Diese sollte - gerade bei einem Urlaub - möglichst nah am eigenen Verhalten sein. Daher habe ich mich für einen Zustand 7 Tage in der Vergangenheit entschieden. Zum einen ist dann immer der gleiche Wochentag (es wird somit nicht am Montag das Verhalten vom Sonntag reproduziert) und die Verschiebung der Helligkeit ist auch im Rahmen. Damit es sich nicht in der 2. Woche 100% wiederholt, habe ich beim schalten eine kleine, willkürliche Verzögerung eingebaut. Dies alles wird bei mir über JDBC in einer SQLite DB gespeichert. Das anlegen der DB habe ich mit der kostenlosen App "DB Browser für SQLite" erstellt. Dies muss "nur" installiert werden und im Anschluß kann darüber eine neue DB erstellt werden. Dazu browsed (neu-Deutsch) man einfach in des Ziel-Verzeichnis, gibt einen DB Namen an und fertig. Im nächsten Schritt benötigt JDBC einmalig den Pfad zu dieser Datenbank, welcher über die BasicUI konfiguriert wird. Im Anschluß kümmert sich openHAB (zum Glück) automatisch um das anlegen der Struktur und füllen der DB
Last but not least sollte möglichst alles lokal (ohne externe Cloud) laufen
Achtung: Ich gehe hier nicht auf die Konfiguration der einzelnen Bridges/Things ein und bei den Items müssen die eigenen Channel noch ergänzt werden
PS: Wer Schreibfehler findet, der darf diese als Geschenk behalten
Items
In der Gruppe gLights_auto sind natürlich nur die Items, welche bei einer Simulation geschaltet werden sollen.
Code: Alles auswählen
Group:Switch:OR(ON, OFF) sFboxDadiPhoneOnline "Dad iPhone [MAP(presence.map):%s]" <man_3> (GhostMode, Parents)
Group:Switch:OR(ON, OFF) sFboxMumiPhoneOnline "Mum iPhone [MAP(presence.map):%s]" <woman_2> (GhostMode, Parents)
Group:Switch:OR(ON, OFF) sFboxChild1iPhoneOnline "Child1 iPhone [MAP(presence.map):%s]" <girl_2> (GhostMode)
Group:Switch:OR(ON, OFF) sFboxChild2iPhoneOnline "Child2 iPhone [MAP(presence.map):%s]" <girl_2> (GhostMode)
Group:Switch:OR(ON, OFF) Parents "Eltern [(%d)]" <present> (All)
Group:Switch:NOR(ON, OFF) GhostMode "Family [(%d)]" <present> (All)
Group gLights_auto
Group gNetDevices
Switch Absence "Anwesendheitssimulation" <vacation>
Switch Night {channel="knx:device:bridge:THEBEN_Lichtsensor"}
// Close House Switch
Switch myCloseItSwitchVis
Switch myCloseItSwitch {autoupdate="false"}
// Sun Protection
Switch ManSunProtection "manuelle Beschattung"
Switch SunProtection "Sonnenschutzautomatik" {channel="knx:device:bridge:GiraTS2:swc1"} // zusätzlich kann die Beschattung auch im Wohnzimmer geschaltet werden
Switch mySunProtectionVis
// Dad iOS
Switch sFboxDadiPhonePhysic "Dad iPhone Physic [MAP(presence.map):%s]" <man_3> (sFboxDadiPhoneOnline) { channel="tr064:....."}
Switch sFboxDadiPhonePrivate "Dad iPhone Private [MAP(presence.map):%s]" <man_3> (sFboxDadiPhoneOnline) { channel="tr064:....."}
// Mum iOS
Switch sFboxMumiPhonePhysic "Mum iPhone Physic [MAP(presence.map):%s]" <woman_2> (sFboxMumiPhoneOnline) { channel="tr064:....."}
Switch sFboxMumiPhonePrivate "Mum iPhone Private [MAP(presence.map):%s]" <woman_2> (sFboxMumiPhoneOnline) { channel="tr064:....."}
// Child1 iOS
Switch sFboxChild1iPhonePhysic "Child1 iPhone Physic [MAP(presence.map):%s]" <girl_2> (sFboxChild1iPhoneOnline) { channel="tr064:....."}
Switch sFboxChild1iPhonePrivate "Child1 iPhone Private [MAP(presence.map):%s]" <girl_2> (sFboxChild1iPhoneOnline) { channel="tr064:....."}
// Child2 iOS
Switch sFboxChild2iPhonePhysic "Child2 iPhone Physic [MAP(presence.map):%s]" <girl_2> (sFboxChild2iPhoneOnline) { channel="tr064:....."}
Switch Lampe_OG_Schlafz_Decke "Schlafzimmerdecke" <light> (gLights_auto, OG_Schlaf, Lampen) {channel="knx:...."}
Switch Lampe_OG_Schlafz_Bett_links "Nachttisch links" <poweroutlet> (gLights_auto, OG_Schlaf, Lampen) {channel="knx:...."}
Switch Lampe_OG_Schlafz_Bett_rechts "Nachttisch rechts" <poweroutlet> (gLights_auto, OG_Schlaf, Lampen) {channel="knx:...."}
Ghostmode
Code: Alles auswählen
rule Ghost
when
Item GhostMode changed
then
if (GhostMode.state == OFF) {
Absence.postUpdate(OFF) // Stoppe Anwesendheitssimulation
} else if (GhostMode.state == ON) {
gNetDevices.allMembers.filter(f|(f.state)!==OFF).forEach[ n| //Schalte alle Netzdevices aus, z.B. Musiccast
n.sendCommand(OFF)
logInfo("NetDevice", n.name + " received OFF")
]
if (Night.state == ON) {
Absence.postUpdate(ON) // Starte Anwesendheitssimulation
}
if (Night.state == ON && Rollladen.state < 100) {
Rollladen.members.filter(f|(f.state as DecimalType).intValue!==100).forEach[ s| //schliesse alle Rollladen, die nicht schon unten sind
s.sendCommand(DOWN)
logInfo("Shutter", s.name + " received DOWN")
]
Steckd_Zaunwand.sendCommand(OFF) // Schalte Licht im Garten aus
}
}
end
Code: Alles auswählen
rule AbsenceMode // Nachricht über Statusänderung
when
Item Absence changed
then
val mailActions = getActions("mail","mail:smtp:xxx")
if (Absence.state == ON) {
mailActions.sendMail("xxx@api.prowlapp.com", "Attention", "Anwesenheitssimulation gestartet !!")
} else if (Absence.state == OFF) {
mailActions.sendMail("xxx@api.prowlapp.com", "Attention", "Anwesenheitssimulation gestoppt !!")
}
end
Code: Alles auswählen
rule "Presence Simulator"
when
Time cron "0 */1 * * * ?" //prüfe jede Minunte
then
if (Absence.state == ON) {
println("-> Presence Simulation")
gLights_auto.members.filter(f|f.state.toString!==f.historicState(new DateTimeType().zonedDateTime.minusDays(7),"jdbc").state.toString).forEach[ m|
Thread::sleep((2000 + Math::random * 1000.0).intValue) //verschiebe die Zeit etwas, damit es in 7 Tagen nicht wieder exact gleich ist
m.sendCommand(m.historicState(new DateTimeType().zonedDateTime.minusDays(7),"jdbc").state.toString)
logInfo("Presence","Restore {} to historic state: {}",m.name, m.historicState(new DateTimeType().zonedDateTime.minusDays(7),"jdbc").state)
]
}
end
Code: Alles auswählen
rule NightStarts
when
Item Night changed
then
if (Night.state == ON && now.toLocalTime.getHour >= 15) {
ManSunProtection.sendCommand(OFF) // schalte manuelle Beschattung aus
SunProtection.sendCommand(OFF) // schalte automatische BEschattung aus
mySunProtectionVis.postUpdate(ON) // aktiviere Button in Sitemap
gShutterOG.members.filter(f|(f.state as DecimalType).intValue!==100).forEach[ s| //fahre alle Rollladen im OG runter
s.sendCommand(DOWN)
logInfo("Shutter", s.name + " received DOWN")
]
Lampe_Haustuere.sendCommand(ON) // schalte Lampe an der Haustüre ein
if (Parents.state == OFF) {
gShutterEG.members.filter(f|(f.state as DecimalType).intValue!==100).forEach[ s| // Wenn Eltern nicht zu Hause sind, fahre auch EG alle Rollladen runter
s.sendCommand(DOWN)
logInfo("Shutter", s.name + " received DOWN")
]
if (GhostMode.state == OFF) {
// Ein Kind ist zu Hause, also keine Anwesendheitssimulation notwendig
} else if (GhostMode.state == ON) {
Absence.postUpdate(ON) // Starte Anwesendheitssimulation
}
} else if (Parents.state == ON) {
// Hier fahre ich die Rollladen im EG in einen bestimmten Zustand
//z.B. bleiben die Rollladen zum Garten offen
// Hier schalte ich dann Deko Lampen im Wohnzimmer
myCloseItSwitchVis.postUpdate(ON) // aktiviert einen Button in der Sitemap
myCloseItSwitch.postUpdate(OFF) // default wert aktiviert
}
} else if (Night.state == OFF) {
// Nacht ist vorbei, nur vorbereitet
}
end
Code: Alles auswählen
rule Sunset_Event_15
when
Channel 'astro:sun:sunset_15:set#event' triggered START
then
logInfo("Astro", "Sun set +15")
if (Parents.state == ON && Rollladen.state < 100) {
// Eltern zu Hause, Garten Rollladen nicht unten und Sonnenuntergang ist 15 Min vorbei
// => in der Regel ist es nun dunkel genug = Gartendekolampen schalten ein
} else if (Rollladen.state == 100) {
// Eltern nicht ON = nicht da oder undefinierter Zustand und Rollladen alle unten = keine Gartenbeleuchtung notwendig
} else {
// vorbereitet
}
end
Code: Alles auswählen
sitemap presence label="Anwesendheitssimulation"
{
// ###################################################################################
Frame {
Switch item=myCloseItSwitch label="Aussen" icon="stophand" visibility=[myCloseItSwitchVis=="ON"] mappings=[ON="Rollladen schliessen!"]
Text label="Haus Status" icon="shield" {
Group item=Comfort icon="settings" label="Komfortfunktionen"{
Switch item=Absence mappings=[OFF="Aus", ON="Ein"]
Switch item=SunProtection icon="sun" mappings=[OFF="Aus", ON="Ein"]
}
Switch item=ManSunProtection visibility=[mySunProtectionVis=="OFF"]
Group item=GhostMode icon="users"
}
}
// ###################################################################################
}
Für weitere Tipps und Anregungen freue ich mich auf die Antworten.
Viele Grüße und für die, welche es nutzen möchten => viel Spaß beim Nachbau