Versionen im Vergleich

Schlüssel

  • Diese Zeile wurde hinzugefügt.
  • Diese Zeile wurde entfernt.
  • Formatierung wurde geändert.

...

Info

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

  • Die Nachtabsenkung aktiv war
  • Und noch zwei weitere Handys für die Fritzbox sichtbar waren

 

 

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.

Benötigte Hard- und Software

  1. Linux-Server (raspberry pi ist ausreichend)
    1. eingerichter Webserver (Apache oder lighthttp)
  2. Fritzbox
  3. iPhone oder Android mit aktiviertem WLAN

Fritzbox MAC-Adressen

...

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.

Benötigte Hard- und Software

  1. Linux-Server (raspberry pi ist ausreichend)
    1. eingerichter Webserver (Apache oder lighthttp)
  2. Fritzbox
  3. iPhone oder Android mit aktiviertem WLAN

Fritzbox MAC-Adressen

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.

...

Anschließend folgendes Perl-Skript in einem beliebigen Verzeichnis unter etwa folgendem Namen speichern, /home/pi/fritzbox-bewohner1.pl.

 

Es sind folgende Anpassungen notwendig und zwar im oberen Bereich, beim dem Block und ziemlich weit unten im Bereich der Pfad-Angaben:

...

languageperl
titleAnpassungen sind in folgenden Bereichen vorzunehmen

...

Funktionsweise des Skripts

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.

 

Codeblock
languageperl
titlePerl-Skript zur Fritzbox-Abfrage
linenumberstrue
#!/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;

 
# ----------------/Konfig --- Konfiguration -------------
my $ip 
if ($arg_any){
    if ($any_online){= "192.168.xxx.xxx";            # IP Fritzbox
my $port   #print= "Anwesend49443";         my $datei = '/var/www/on-Bewohner1';    # Port Fritzbox
my @macs_to_check open= (my $fh, ">>", $datei) or die "Kann Datei $datei nicht oeffnen: $!";"AA:BB:CC:DD:EE:FF");    # MAC Adresse der Geraete, es können mehrere eingetragen werden
my $LOXIP = "192.168.xxx.xxx";            # IP printMiniserver
$fh strftime("%Y-%m-%d %H-%M-%S", localtime), " Anwesend\nmy $udpport = "34435";         close $fh;      #  UDP-Port
my $dateianwesend$online = '/var/www/anwesend-Bewohner1'"xxx-1"; 	        open (my $fhanwesend, ">", $dateianwesend) or die "Kann Datei $datei nicht oeffnen: $! # Person Online 
my $offline = "xxx-0";  	          # Person Offline
#  print $fhanwesend strftime("%Y-%m-%d %H-%M-%S", localtime), " Wert = 1\n";
        close $fhanwesend;
        }
        else{
  ---------------- 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    #print "Abwesend";
  = $resp_discover->decoded_content;
}
else {
        die $resp_discover->status_line;
}
 
my $datei$discover = '/var/www/off-Bewohner1'XMLin($xml_discover);
print "$discover->{device}->{modelName} gefunden...\n";

my $control_url = "not set";
my $service_type =     open (my $fh, ">>", $datei) or die "Kann Datei $datei nicht oeffnen: $!";
     "not set";
my $service_command = "GetSpecificHostEntry";
foreach(@{$discover->{device}->{deviceList}->{device}->[0]->{serviceList}->{service}}){
          print $fh strftimeif("%Y-%m-%d %H-%M-%S", localtime), " Abwesend\n";urn:LanDeviceHosts-com:serviceId:Hosts1" =~ m/.*$_->{serviceId}.*/){
                $control_url close $fh= $_->{controlURL};
                my $dateianwesend$service_type = '/var/www/anwesend-Bewohner1'$_->{serviceType};
        }
}
 
if ($control_url eq "not set" open (my $fhanwesend, ">", $dateianwesend) or die "Kann Datei $datei nicht oeffnen: $!";
                print $fhanwesend strftime("%Y-%m-%d %H-%M-%S", localtime), " Wert = 0\n";
     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 close= $fhanwesend<<EOD;
         exit 0;<?xml version="1.0" encoding="utf-8"?>
        }
}

 

Hier nun das Perl-Skript

Codeblock
languageperl
titlePerl-Skript zur Fritzbox-Abfrage
linenumberstrue
#!/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 POSIX qw/ strftime /;


# ---------------- Konfig ----------------
my $ip = "xxx.xxx.xxx.xxx";
my $port = "49443";
my @macs_to_check = ("11:22:33:44:55:66", "22:33:44:55:66:77");
# ----------------/Konfig ----------------


# Arguments
# "any" checks if at least one/any MAC is online
my $arg_any = '';
GetOptions('any' => \$arg_any);

# disable SSL checks. No signed certificate!
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;
$ENV{HTTPS_DEBUG} = 1;

# Discover Service Parameters
my $ua = new LWP::UserAgent;
$ua->default_headers;
$ua->ssl_opts( verify_hostname => 0 ,SSL_verify_mode => 0x00);

# Read all available services
my $resp_discover = $ua->get("https://$ip:$port/tr64desc.xml");
my $xml_discover;
if ( $resp_discover->is_success ) {<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>
                         $xml_discover = $resp_discover->decoded_content;
}
else {</u:$service_command>
             die $resp_discover->status_line; } </s:Body>
my $discover = XMLin($xml_discover); print "$discover->{device}->{modelName} detected...\n" unless $arg_any;

# Parse XML service response, get needed parameters for LAN host service
my $control </s:Envelope>
EOD
 
        my $init_url = "not sethttps://$ip:$port$control_url";
   my $service_type = "not set"; my $service$resp_commandinit = "GetSpecificHostEntry"; # fixed command for requesting info of specific MAC
foreach(@{$discover->{device}->{deviceList}->{device}->[0]->{serviceList}->{service}}){$ua->post($init_url, Content_Type => 'text/xml; charset=utf-8', Content => $init_request);
        $xml_mac_resp = XMLin($resp_init->decoded_content);
        if("urn:LanDeviceHosts-com:serviceId:Hosts1" =~ m/.*$_->{serviceId}.*/exists $xml_mac_resp->{'s:Body'}->{'s:Fault'}){
                $control_url = $_if($xml_mac_resp->{controlURL};
  's:Body'}->{'s:Fault'}->{detail}->{UPnPError}->{errorCode} eq "714"){
             $service_type = $_->{serviceType};         }print }"MAC $mac if ($control_url eq "not set" or $service_type eq "not set"){nicht in der FritzBox gefunden!\n";
             die "control URL/service type}
not found.
Cannot request host info!"; }   # Prepare request for}
query LAN host $ua->default_header( 'SOAPACTION' => "$service_type#$service_command" ); myif(exists $xml_mac_resp;
my $any_online = 0; # if arg any specified

foreach my $mac (@macs_to_check){
 ->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}){
      my $init_request = <<EOD;         <?xml version="1.0" encoding="utf-8"?>if($xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewActive} eq "1"){
                <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" >      my $name          <s:Header>
 = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewHostName};
              </s:Header>          my $ip = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewIPAddress};
   <s:Body>                     my $iftype =  <u:$service_command xmlns:u="$service_type">$xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewInterfaceType};
                        print "MAC $mac ($name) ist online mit der <NewMACAddress>$mac</NewMACAddress>IP $ip mit $iftype\n";
                     </u:$service_command>   $any_online = 1;
            </s:Body>    }
    </s:Envelope> EOD          my $init_url = "https://$ip:$port$control_url";if($xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewActive} eq "0"){
         my $resp_init   my $name = $ua->post($init_url, Content_Type => 'text/xml; charset=utf-8', Content => $init_request);$xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewHostName};
            $xml_mac_resp = XMLin($resp_init->decoded_content);            print "MAC $mac if(exists $xml_mac_resp->{'s:Body'}->{'s:Fault'}){($name) ist offline\n";
        }
 
 
    if($xml_mac_resp->{'s:Body'}->{'s:Fault'}->{detail}->{UPnPError}->{errorCode}
eq "714"){
}
    

        if ($any_online){
       print "Macmy $mac$sock not= found in FritzBox Database!\n" unless $arg_any;new IO::Socket::INET(PeerAddr => $LOXIP,
                PeerPort => }$udpport,
         }         if(exists $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}){
     Proto => 'udp', Timeout => 1) or die('Error opening socket.');
        print  if($xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewActive} eq "1"){$sock $online;
        exit 1;
}
        else{
      my $name = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewHostName};  my $sock = new IO::Socket::INET(PeerAddr => $LOXIP,
                PeerPort => $udpport,
          my $ip = $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewIPAddress}    Proto => 'udp', Timeout => 1) or die('Error opening socket.');
                print $sock $offline;
     my $iftype =  $xml_mac_resp->{'s:Body'}->{'u:GetSpecificHostEntryResponse'}->{NewInterfaceType};
                        print "Mac $mac ($name) is online with IP $ip on $iftype\n" unless $arg_any;
                        $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) is offline\n" unless $arg_any;
        }


        }

}
# If "any" arg was passed, only print summary status
if ($arg_any){
    if ($any_online){
                #print "Anwesend";
        my $datei = '/var/www/on-Bewohner1';
        open (my $fh, ">>", $datei) or die "Kann Datei $datei nicht oeffnen: $!";
            print $fh strftime("%Y-%m-%d %H-%M-%S", localtime), " Anwesend\n";
        close $fh;
        my $dateianwesend = '/var/www/anwesend-Bewohner1';
        open (my $fhanwesend, ">", $dateianwesend) or die "Kann Datei $datei nicht oeffnen: $!";
                print $fhanwesend strftime("%Y-%m-%d %H-%M-%S", localtime), " Wert = 1\n";
        close $fhanwesend;
        }
        else{
               #print "Abwesend";
                my $datei = '/var/www/off-Bewohner1';
                open (my $fh, ">>", $datei) or die "Kann Datei $datei nicht oeffnen: $!";
                print $fh strftime("%Y-%m-%d %H-%M-%S", localtime), " Abwesend\n";
                close $fh;
                my $dateianwesend = '/var/www/anwesend-Bewohner1';
                open (my $fhanwesend, ">", $dateianwesend) or die "Kann Datei $datei nicht oeffnen: $!";
                print $fhanwesend strftime("%Y-%m-%d %H-%M-%S", localtime), " Wert = 0\n";
                close $fhanwesend;

        exit 0;
        }
}

Funktionsweise des Skripts

Das Skript fragt die Fritzbox nach ob die im Konfig-Block angegeben MAC-Adressen anwesend sind und schreibt dann je nach Zustand in folgende Dateien:

  • Bei Anwesenheit
    • /var/www/anwesend-Bewohner1
      • das aktuelle Datum und die Uhrzeit und Wert = 1
    • /var/www/on-Bewohner1
      • fortlaufend das Datum und die Uhrzeit und den Status Anwesend
  • Bei Abwesenheit
    • /var/www/anwesend-Bewohner1
      • das aktuelle Datum und die Uhrzeit und Wert = 0
    • /var/www/on-Bewohner1
      • fortlaufend das Datum und die Uhrzeit und den Status Abwesend

...

exit 0;
}

Trennung des Skriptes

Um eine getrennte Abfrage für jeden Bewohner zu machen sind mehrere Skripte erforderlich. Also fritzbox-Bewohner1.pl, fritzbox-Bewohner2.pl, usw.

...