Hiermit soll beschrieben werden, wie mit einem Linux-Server (raspberry pi oder ähnlich), einer Fritzbox und einem iPhone oder Android-Handy die Anwesenheit eines oder mehrere Bewohner geprüft werden kann um verschiedene Stadien im Haus zu aktivieren.
Und vor allem kommt diese Lösung ohne Zugriffe auf Cloud-Dienste aus.
Im Forum wurde angekündigt, dass es Probleme geben könnte mit iPhone-Geräten.
Ich habe nun seit dem 09. Januar 2016 die Anwesenheitsdaten immer mitgeschrieben um nachzuvollziehen, wann das Gerät aus der Fritzbox verschwindet. Es gab nur einmal in der Nacht einen Aussetzer von ca. 1 1/2 Std. Das ist aber aus meiner Sicht vernachlässigbar, da
Aktualisierung am 17.02.2016: Ich habe durch einen Tipp aus dem Forum (direktes schreiben des Status auf dem Server) die Datei angepasst. Was mir jedoch nicht gefiel, dass die Daten (u.a. das Loxone-Kennwort) unverschlüsselt durch das heimische Netz geschickt werden. Das soll mit der neuen Methode meines Erachtens besser sein. Denn der Miniserver empfängt nur noch einen Status den der raspberry sendet.
|
Als Inspiration diente mir folgender Forumeintrag:
Anwesenheit per WLAN feststellen
Dort habe ich die Grunddatei vom User Dott verwendet.
Das Perlskript zur Fritzbox-Abfrage kommt von Bock-Systems. Bitte auch von dort bitte die notwendigen Einstellungen für die Fritzbox nachschauen.
Es gilt über die Fritzbox die MAC-Adressen der betroffenen Mobilfunkgeräte herauszufinden.
Die Übersicht für alle Netzwerkgeräte befindet sich bei FRITZ!OS 6.50 unter folgendem Pfad, wobei Android meistens mit "android-" beginnen und einer alphanumerischen Kombination enden.
Als Beispiel haben wir nun die MAC-Adressen erhalten
11:22:33:44:55:66 und 22:33:44:55:66:77, wobei eins davon ein iPhone und das andere ein Android-Handy ist.
sudo apt-get install libxml-simple-perl libio-all-lwp-perl libgetopt-long-descriptive-perl |
Anschließend folgendes Perl-Skript in einem beliebigen Verzeichnis unter etwa folgendem Namen speichern, /home/pi/fritzbox-bewohner1.pl.
Das Perl-Skript fragt die Fritzbox die MAC-Adressen ab und sendet per UDP "xxx-1" für online und "xxx"-0 für offline.
Die Information kann dann wie auf der Seite UDP Eingang definieren ausgewertet werden.
#!/usr/bin/perl -w use strict; use warnings; use LWP::Simple; use LWP::UserAgent; use XML::Simple; use Getopt::Long; use open qw(:std :utf8); use HTTP::Request::Common; use IO::Socket::INET; # ------------- Konfiguration ------------- my $ip = "192.168.xxx.xxx"; # IP Fritzbox my $port = "49443"; # Port Fritzbox my @macs_to_check = ("AA:BB:CC:DD:EE:FF"); # MAC Adresse der Geraete, es können mehrere eingetragen werden my $LOXIP = "192.168.xxx.xxx"; # IP Miniserver my $udpport = "34435"; # UDP-Port my $online = "xxx-1"; # Person Online my $offline = "xxx-0"; # Person Offline # ---------------- Programm ---------------- $ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0; $ENV{HTTPS_DEBUG} = 1; my $ua = new LWP::UserAgent; $ua->default_headers; $ua->ssl_opts( verify_hostname => 0 ,SSL_verify_mode => 0x00); my $resp_discover = $ua->get("https://$ip:$port/tr64desc.xml"); my $xml_discover; if ( $resp_discover->is_success ) { $xml_discover = $resp_discover->decoded_content; } else { die $resp_discover->status_line; } my $discover = XMLin($xml_discover); print "$discover->{device}->{modelName} gefunden...\n"; my $control_url = "not set"; my $service_type = "not set"; my $service_command = "GetSpecificHostEntry"; foreach(@{$discover->{device}->{deviceList}->{device}->[0]->{serviceList}->{service}}){ if("urn:LanDeviceHosts-com:serviceId:Hosts1" =~ m/.*$_->{serviceId}.*/){ $control_url = $_->{controlURL}; $service_type = $_->{serviceType}; } } if ($control_url eq "not set" or $service_type eq "not set"){ die "control URL/service type not found. Cannot request host info!"; } $ua->default_header( 'SOAPACTION' => "$service_type#$service_command" ); my $xml_mac_resp; my $any_online = 0; foreach my $mac (@macs_to_check){ my $init_request = <<EOD; <?xml version="1.0" encoding="utf-8"?> <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" > <s:Header> </s:Header> <s:Body> <u:$service_command xmlns:u="$service_type"> <NewMACAddress>$mac</NewMACAddress> </u:$service_command> </s:Body> </s:Envelope> EOD my $init_url = "https://$ip:$port$control_url"; my $resp_init = $ua->post($init_url, Content_Type => 'text/xml; charset=utf-8', Content => $init_request); $xml_mac_resp = XMLin($resp_init->decoded_content); if(exists $xml_mac_resp->{'s:Body'}->{'s:Fault'}){ if($xml_mac_resp->{'s:Body'}->{'s:Fault'}->{detail}->{UPnPError}->{errorCode} eq "714"){ print "MAC $mac nicht in der FritzBox gefunden!\n"; } } if(exists $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}){ if($xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewActive} eq "1"){ my $name = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewHostName}; my $ip = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewIPAddress}; my $iftype = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewInterfaceType}; print "MAC $mac ($name) ist online mit der IP $ip mit $iftype\n"; $any_online = 1; } if($xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewActive} eq "0"){ my $name = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewHostName}; print "MAC $mac ($name) ist offline\n"; } } } if ($any_online){ my $sock = new IO::Socket::INET(PeerAddr => $LOXIP, PeerPort => $udpport, Proto => 'udp', Timeout => 1) or die('Error opening socket.'); print $sock $online; exit 1; } else{ my $sock = new IO::Socket::INET(PeerAddr => $LOXIP, PeerPort => $udpport, Proto => 'udp', Timeout => 1) or die('Error opening socket.'); print $sock $offline; exit 0; } |
Um eine getrennte Abfrage für jeden Bewohner zu machen sind mehrere Skripte erforderlich. Also fritzbox-Bewohner1.pl, fritzbox-Bewohner2.pl, usw.
Um das ganze automatisiert abfragen zu können ist wieder ein cronjob und die Ausführberechtigung für das Skript notwendig.
chmod +x /home/pi/fritzbox-Bewohner1.pl |
sudo crontab -e |
Folgende Zeilen am Ende einfügen:
* * * * * /usr/bin/perl /home/pi/fritzbox-Bewohner1.pl -any >/dev/null 2>&1 |
Nun fragt der raspberry pi jede Minute den Status der anwesenden WLAN-Geräte bei der Fritzbox ab.
Den Empfang der UDP - Telegramme und die Verwertung im Miniserver ist unter UDP Eingang definieren beschrieben.