Zum Ende der Metadaten springen
Zum Anfang der Metadaten

Sie zeigen eine alte Version dieser Seite an. Zeigen Sie die aktuelle Version an.

Unterschiede anzeigen Seitenhistorie anzeigen

Version 1 Nächste Version anzeigen »

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.

 

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.

  • Bei aktuell eingebuchten Geräten
    • Heimnetz -> Heimnetzübersicht -> Details beim jeweiligen Netzgerät
  • Bei vergangenen eingebuchten Geräten
    • Heimnetz -> Heimnetzübersicht -> Netzwerkverbindungen -> Details beim jeweiligen Netzgerät

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.

Einrichten des Linux-Servers

Falls ein Webserver noch nicht eingerichtet sein sollte, lässt sich das relativ schnell nachholen mit folgendem Befehl:

Installieren von Apache
sudo apt-get install apache2

Anschließende muss für die Funktionalität des Perl-Skriptes noch etwas nachinstalliert werden.

Installieren der Perl-Umgebung
sudo apt-get install libxml-simple-perl libio-all-lwp-perl libgetopt-long-descriptive-perl

Test des Webservers

Ein erster Test sollte der Ereichbarkeit des Webservers gelten, dazu die IP-ADRESSE des Servers eingeben und über folgenden Text freuen (Lächeln)

It works!
This is the default web page for this server.
The web server software is running but no content has been added, yet.

Einrichten des Perl-Skriptes

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:

Anpassungen sind in folgenden Bereichen vorzunehmen
# ---------------- 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 ----------------



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;
        }
}

 

Hier nun das Perl-Skript

Perl-Skript zur Fritzbox-Abfrage
#!/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 ) {
        $xml_discover = $resp_discover->decoded_content;
}
else {
        die $resp_discover->status_line;
}

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_url = "not set";
my $service_type = "not set";
my $service_command = "GetSpecificHostEntry"; # fixed command for requesting info of specific MAC
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!";
}


# Prepare request for query LAN host
$ua->default_header( 'SOAPACTION' => "$service_type#$service_command" );
my $xml_mac_resp;
my $any_online = 0; # if arg any specified

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 not found in FritzBox Database!\n" unless $arg_any;
                }

        }
        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) 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

Je nach An- oder Abwesenheit werden unter der Datei /var/www/anwesend-Bewohner1 nun zwei Werte gepeichert. Wobei 1 für An- und 0 für Abwesenheit steht. Diese Werte können nun zur Auswertung für den Miniserver verwendet werden.

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.

Automatisierung der Abfrage

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
cronjob anlegen
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.

Einrichtung Loxone

In Loxone muss als Erstes folgendes erstellt werden:

Einen virtuellen HTTP-Eingang mit folgenden Einstellungen:

 

Anschließend ein Virtueller HTTP Eingang Befehl mit folgenden Einstellungen:

Anschließend noch eine leicht abgewandelte Config-Version von dott:

Der Statusbaustein sieht folgendermaßen aus:

 

 

  • Keine Stichwörter