Universal Plug and Play
Wie man Statusinformationen der FRITZ!Box bekommt
 
         
     
 
UPnPUPnP
 

Inhalt

Was ist UPnP?

UPnP steht für 'Universal Plug and Play', welches von plug-and-play (englisch) abgeleitet ist. Es ist eine Sammlung von Protokollen, welche vom UPnP Forum (englisch) definiert wurden.

Ein Teil dieser Ziele ist es nützliche Informationen über das Gerät im Netzwerk zu verbreiten, damit andere Geräte diese Informationen nutzen können um das neue Gerät zu integrieren.

Die Spezifaktionen über UPnP können hier (englisch) gefunden werden.

Wie kann man Informationen von UPnP Geräten abfragen?

Es gibt viele Wege um Informationen von UPnP Geräten zu erhalten. Es gibt sogar einige Werkzeuge, welche es ermöglichen über graphische Oberflächen mit UPnP zu experimentieren - wie zum Beipiel GUPnP (englisch).

Ich habe den Weg über Perl (englisch) und das Net::UPnP-Module (english) gewählt.

Das folgende Skript benutzt dieses Perl-Modul um UPnP Geräte im Netzwerk zu erkennen und Informationen über die verfügbaren Dienste abzufragen.

  1. #!/usr/bin/perl
  2.  
  3. # Geschrieben im August 2009 von Axel Arnold - http://www.axel-arnold.de
  4. # Dieser Code wird unter der CPL 1.0 (http://www.opensource.org/licenses/cpl1.0.php) zur Verfügung gestellt
  5.  
  6. use strict;
  7.  
  8. require LWP::UserAgent;
  9. require Net::UPnP::ControlPoint;
  10. require URI;
  11. require XML::LibXML;
  12.  
  13. # Subroutine um die Servicebeschreibung ueber http zu holen und alle verfuegbaren Actions aus dieser zu extrahieren
  14. sub getServiceActions {
  15.   my ($url) = @_;
  16.   my @result = ();
  17.  
  18.   my $ua = LWP::UserAgent->new;
  19.   $ua->timeout(10);
  20.   $ua->env_proxy;
  21.  
  22.   my $response = $ua->get( $url );
  23.  
  24.   if ( $response->is_success ) {
  25.     my $parser = XML::LibXML->new();
  26.  
  27.     my $doc = $parser->parse_string( $response->decoded_content );
  28.     my $root = $doc->firstChild();
  29.  
  30.     my $xpc = XML::LibXML::XPathContext->new( $root );
  31.     $xpc->registerNs('x', 'urn:schemas-upnp-org:service-1-0');
  32.     my @actions = $xpc->findnodes('//x:actionList/x:action/x:name' );
  33.     foreach my $action (@actions) {
  34.       @result=(@result, $action->textContent());
  35.     }
  36.   }
  37.  
  38.   return @result;
  39. }
  40.  
  41. if ((@ARGV) == 0) {
  42.   die "get_upnp_info <Muster des Geraetenamens>\n\nBeispiel: get_upnp_info FRITZ\n         get_upnp_info .\n";
  43. }
  44. my $devicePattern = "$ARGV[0]";
  45.  
  46. # Basisgeraete finden
  47. my $obj = Net::UPnP::ControlPoint->new();
  48. my @dev_list = $obj->search( st =>'upnp:rootdevice', mx => 3 );
  49.  
  50. # Iteriere ueber alle gefundenen Geraete
  51. foreach my $dev (@dev_list) {
  52.   # Pruefe ob das Geraet dem angegebenen Muster entspricht
  53.   $_ = $dev->getfriendlyname();
  54.   if ( not /$devicePattern/ ) {
  55.     next;
  56.   }
  57.   print "Device = " . $dev->getfriendlyname() . "\n";
  58.  
  59.   my $url = URI->new( $dev->getlocation() );
  60.   # hole alle Dienste
  61.   my @service_list = $dev->getservicelist();
  62.   foreach my $service (@service_list) {
  63.     my $serviceID = $service->getserviceid();
  64.     my $scpdurl = $service->getdevicedescription( name=>'SCPDURL' );
  65.     # hole alle Actions des Dienstes
  66.     $url->path( $scpdurl );
  67.     my @actions = getServiceActions( $url );
  68.     foreach my $action ( @actions ) {
  69.       $_ = $action;
  70.       # 'post' alle 'Get' Actions
  71.       if ( /^Get/ ) {
  72.         my %action_in_arg = ();
  73.         my $action_res = $service->postaction( $action, \%action_in_arg);
  74.         if ($action_res->getstatuscode() == 200) {
  75.           my $arg_ref = $action_res->getargumentlist();
  76.           my %args = %$arg_ref;
  77.           foreach my $k ( keys %args ) {
  78.             print "" . $serviceID . "::" . $action . ":" . $k . " = " . $args{$k} . "\n";
  79.           }
  80.         }
  81.       }
  82.     }
  83.   }
  84. }

Was kann man mit diesem Skript anstellen?

Ich benutze dieses Perl-Skript um den Status meiner FRITZ!Box in Nagios (englisch), einer Software zur Überwachung von Hard- und Software, zu verfolgen.

Dies ist das Nagios-Skript (es erwartet die Warnungs-Upstream-, die Fehler-Upstream-, die Warnungs-Downstream- und die Fehler-Downstream-Bitrate als Kommandozeilenparameter):

  1. #!/bin/ksh
  2.  
  3. # Erstellt im August 2009 von Axel Arnold - http://www.axel-arnold.de
  4. # Dieser Code wird unter der CPL 1.0 (http://www.opensource.org/licenses/cpl1.0.php) zur Verfügung gestellt.
  5.  
  6. dir=`dirname $0`
  7. minup=$1
  8. maxup=$2
  9. mindown=$3
  10. maxdown=$4
  11.  
  12. integer minup
  13. integer maxup
  14. integer mindown
  15. integer maxdown
  16.  
  17. upnp=`/usr/local/bin/get_upnp_info FRITZ!Box`
  18.  
  19. # ERROR - no physical link
  20. physical_link_status=`echo "$upnp" | grep 'GetCommonLinkProperties:NewPhysicalLinkStatus'`
  21. echo "$physical_link_status" | grep -E 'Up$' > /dev/null
  22. if [ $? -ne 0 ]; then
  23.     /usr/bin/echo "FRITZ!Box Physical Link is not Up!"
  24.     exit 2
  25. fi
  26. # ERROR - no DSL link
  27. link_status=`echo "$upnp" | grep 'GetDSLLinkInfo:NewLinkStatus'`
  28. echo "$link_status" | grep -E 'Up$' > /dev/null
  29. if [ $? -ne 0 ]; then
  30.     /usr/bin/echo "FRITZ!Box DSL Link is not Up!"
  31.     exit 2
  32. fi
  33.  
  34. upstream=`echo "$upnp" | grep 'GetCommonLinkProperties:NewLayer1UpstreamMaxBitRate' | awk -F'=' '{print $2}'`
  35. downstream=`echo "$upnp" | grep 'GetCommonLinkProperties:NewLayer1DownstreamMaxBitRate' | awk -F'=' '{print $2}'`
  36. # ERROR - upstream too low
  37. if [ $upstream -lt $minup ]; then
  38.     /usr/bin/echo "FRITZ!Box max. Upstream Bitrate too low! | $upstream $downstream"
  39.     /usr/bin/echo "$upstream $downstream | "
  40.     exit 2
  41. # WARNING - upstream too low
  42. elif [ $upstream -lt $maxup ]; then
  43.     /usr/bin/echo "FRITZ!Box max. Upstream Bitrate too low! | $upstream $downstream"
  44.     /usr/bin/echo "$upstream $downstream | "
  45.     exit 1
  46. fi
  47.  
  48. # ERROR - downstream too low
  49. if [ $downstream -lt $mindown ]; then
  50.     /usr/bin/echo "FRITZ!Box max. Downstream Bitrate too low! | $upstream $downstream"
  51.     /usr/bin/echo "$upstream $downstream | "
  52.     exit 2
  53. # WARNING - downstream too low
  54. elif [ $downstream -lt $maxdown ]; then
  55.     /usr/bin/echo "FRITZ!Box max. Downstream Bitrate too low! | $upstream $downstream"
  56.     /usr/bin/echo "$upstream $downstream | "
  57.     exit 1
  58. fi
  59.  
  60. uptime=`echo "$upnp" | grep 'GetStatusInfo:NewUptime' | awk -F'=' '{print $2}'`
  61. upseconds=uptime
  62. integer uptime;
  63. integer days
  64. integer hours
  65. integer minutes
  66. integer seconds
  67. days=$uptime/60/60/24
  68. uptime=$uptime-($days*60*60*24)
  69. hours=$uptime/60/60
  70. uptime=$uptime-($hours*60*60)
  71. minutes=$uptime/60
  72. uptime=$uptime-($minutes*60)
  73. seconds=$uptime
  74. /usr/bin/echo "Uptime ${days}d ${hours}h ${minutes}min ${seconds}sec | $upstream $downstream"
  75. /usr/bin/echo "$upstream $downstream | "
  76. exit 0

Kommentare

Stefan, 07-12-09 21:02:
Sowas habe ich schon lange gesucht. Vielen Dank für die Arbeit. Können Sie mir sagen, wie ich das ganze in Nagios genau einbaue?
Axel, 12-12-09 11:47:
Ich habe das ksh Skript unter /etc/nagioc/localcommands/check_fritzbox.ksh abgelegt und folgende Dateien angepasst:

/etc/nagios/resource.cfg:
#hinzugefuegt
$USER2$=/etc/nagios/localcommands

/etc/nagios/objects/commands.cfg:
# hinzugefuegt:
define command {
command_name check_fritzbox
command_line $USER2$/check_fritzbox.ksh $ARG1$ $ARG2$ $ARG3$ $ARG4$
}

/etc/nagios/objects/local-net.cfg:
# hinzugefuegt
define service {
use remote-service
host_name router
service_description FRITZ Box
check_command check_fritzbox!1100000!1140000!14000000!14300000
}
Ullrich, 30-07-10 14:34:
Hallo Axel,

ich hatte vor einiger Zeit schon einmal Deine Fritz!Box-Überwachung am Laufen, aber dann ist irgendwann die Festplattte mit dem system darauf gestorben. Jetzt wollte ich die Sache noch einmal angehen und habe das ganze neu installiert, aber ich bekomme keine Info (get_upnp_info) zurück. Ich weiß einfach nicht mehr weiter. Vielleicht hast Du zeit für eine kleine Offline-Diskussion.

Vielen Dank im Voraus
Ullrich

Kommentar hinzufügen

* - Pflichtfeld







Alle Themen

UPnP
Wie kann man Informationen von UPnP Geräten, wie der Fritz Box, erhalten?
Datenbanken
Automatische Konvertierung von MySQL Datenbanken zu SQLite Datenbanken.
SSH Tunnel
Durchleitung von Verbindungen aller Protokolle über SSH.
Zuletzt geändert: 12.12.2009