Versionen im Vergleich

Schlüssel

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

...

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

...

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

...

Perl-

...

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

Codeblock
languagebash
titleInstallieren von Apache
sudo apt-get install apache2

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

Codeblock
languagebash
titleInstallieren 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)

Codeblock
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.

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.

 

...

languageperl
titlePerl-Skript zur Fritzbox-Abfrage
linenumberstrue

...

Skriptes

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

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;

 
# ------------- 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 das ganze automatisiert abfragen zu können ist wieder ein cronjob und die Ausführberechtigung für das Skript notwendig.

Codeblock
languagebash
chmod +x /home/pi/fritzbox-Bewohner1.pl
Codeblock
languagebash
titlecronjob anlegen
sudo crontab -e

Folgende Zeilen am Ende einfügen:

die Ausführberechtigung für das Skript notwendig.

Codeblock
languagebash
* * * * * /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:

Image Removed

 

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

Image Removed

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

Image Removed

Der Statusbaustein sieht folgendermaßen aus:

Image Removed

 

...

chmod +x /home/pi/fritzbox-Bewohner1.pl
Codeblock
languagebash
titlecronjob anlegen
sudo crontab -e

Folgende Zeilen am Ende einfügen:

Codeblock
languagebash
* * * * * /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.