Ankündigung

Einklappen

Hinweis

Die Forenregeln wurden überarbeitet (Stand 7.11.22). Sie sind ab sofort verbindlich. Wir bitten um Beachtung.
Mehr anzeigen
Weniger anzeigen

Fritzbox-Anrufliste für rsslog aufbereiten

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [WireGate-Plugin] Fritzbox-Anrufliste für rsslog aufbereiten

    Hallo zusammen,

    anbei ein kleines Skript, was die Anrufliste der Fritzbox aktualisiert und in die rsslog-Datenbank postet. Was anzupassen ist: die Adresse der Fritzbox, das Passwort und der Pfad zur Datenbank.

    Achtung: Das ganze sollte NICHT als WG-Plugin laufen, bei längeren Anruflisten läuft das auch schommal 10-20s, und das ist als WG-Plugin gänzlich ungeeignet. Ich musste allerdings ein Präfix auswählen, und das passte noch am besten.

    Gruss,

    der Jan

    Code:
    #!/usr/bin/perl
    #
    # (c) 2011 by Jan N. Klug
    # Licenced under the GPLv3      
    #
    # sqlite-Anbindung inspiriert von rsslog.pl by Michael Markstaller
    # Fritzbox-Login aehnlich http://blog.soldierer.com/2009/12/06/neues-fritzbox-session-id-login-verfahren-in-perl/ by Walter Soldierer
    #
    # Fritzbox-Anrufliste für rsslog aufbereiten
    #
    
    # config
    my $boxpasswort = "XXXXXX";
    my $boxaddress = "fritz.box";
    my $logdb = '/var/www/rsslog.db';
    
    # ab hier nichts aendern
    
    #allgemeine Deklarationen
    use strict;
    
    use LWP 5.64;
    use Digest::MD5 'md5_hex';
    use XML::Simple;
    use DBI;
    use DateTime;
    
    # Fritzbox-LOGIN
    
    # challenge abholen
    
    my $user_agent = LWP::UserAgent->new; 
    my $http_response = $user_agent->get("http://$boxaddress/cgi-bin/webcm?getpage=../html/login_sid.xml");
    $http_response->content =~ /<Challenge>(\w+)<\/Challenge>/i and my $challengeStr = $1;
    
    # response zur challenge generieren
    my $ch_Pw = "$challengeStr-$boxpasswort";
    $ch_Pw =~ s/(.)/$1 . chr(0)/eg;
    my $challenge_response = "$challengeStr-" . lc(md5_hex($ch_Pw));
    
    # SID ermitteln
    $http_response = $user_agent->post("http://$boxaddress/cgi-bin/webcm",
    ["login:command/response" => $challenge_response, getpage => "../html/login_sid.xml" ], );
    $http_response->content =~ /<SID>(\w+)<\/SID>/i and my $SID = $1;
    
    # Gespraechsdaten aktualisieren und XML Gespraechs-Daten holen
    
    $http_response = $user_agent->post("http://$boxaddress/cgi-bin/webcm", [getpage => '../html/de/menus/menu2.html','sid' => $SID, 'var:menu' => 'home', 'var:pagename' => 'foncalls' ]);
    $http_response = $user_agent->get("http://$boxaddress/cgi-bin/webcm?getpage=../html/de/home/foncallsdaten.xml&sid=$SID" );
    
    # XML Daten parsen
    my $xml = new XML::Simple (KeyAttr=>[]);
    my @data = @{$xml->XMLin($http_response->content)->{Calls}};
    #@data = sort {$b->{'id'} <=> $a->{'id'}} @data;
    
    # Datenbank öfnnen und letzten fritzcall ermitteln
    if (! -e $logdb) {
     die "$logdb existiert nicht! Bitte mit rsslog.php anlegen"; # FIXME: create sqlite-db
    }
    
    my $dbargs = {AutoCommit => 0, PrintError => 1};
    my $dbh = DBI->connect("dbi:SQLite2:dbname=$logdb", "", "", $dbargs)
      or die "Couldn't open database: " . DBI->errstr;
    
    $dbh->commit();
    my $sth = $dbh->prepare('SELECT Max(t) FROM Logs WHERE tags LIKE \'%fritzcall%\';')
      or die "Couldn't prepare statement: " . $dbh->errstr;
    
    $sth->execute()             # Execute the query
      or die "Couldn't execute statement: " . $sth->errstr;
    
    my @dblast = $sth->fetchrow_array();
    
    $sth->finish();
    
    (my $year, my $month, my $day, my $hour, my $minute, my $second) = split(/[- :]/, @dblast[0]);
    
    if ($year == undef) {
      $year=1900; $month=1; $day=1; $hour=0; $minute=0; $second=0;
    }
    
    my $dblastdate =  DateTime->new( year => $year, month => $month, day => $day,
      hour => $hour, minute => $minute, second =>$second);
    
    # alle Gespreachsdaten durchsehen und neue eintragen
      
    $second = "00";
    
    my @calltype = ('inbound', 'missed', 'outbound');
    
    foreach my $call (@data) {
      ($day, $month, $year, $hour, $minute) = split(/[. :]/, $call->{'Date'});
      $year = "20" . $year;
      
      my $calldate =  DateTime->new( year => $year, month => $month, day => $day,
        hour => $hour, minute => $minute, second =>$second, time_zone => 'Europe/Berlin');
      $calldate->set_time_zone('UTC'); # all sqlite-data is in UTC !
      
      if ($calldate>$dblastdate)   { # is a new entry
        #my $sqldate = $calldate->strftime("%Y-%m-%d %T");
        my $sqlquery = 'INSERT INTO Logs(content, title, tags, t) VALUES( ' .
          " '" . $call->{'Number'} . "', '', " .
          " 'fritzcall,phone," . $calltype[$call->{'Type'}-1] . ",noack'," .
          " '" . $calldate->strftime("%Y-%m-%d %T") . "');";
        $dbh->do($sqlquery)
          or die "Couldn't execute command: " . $dbh->errstr;
        
        $dbh->commit()
          or die "Couldn't execute command: " . $dbh->errstr;
      }
    }
    
    $dbh->disconnect();
    KNX, DMX over E1.31, DALI, 1W, OpenHAB, MQTT

    #2
    Hallo Jan,
    das klingt spannend.
    Ich scheitere mal wieder beim Umsetzen.
    Deinen Code habe ich unter /var/xxx/fritz_call_mon_rsslog.pl abgelegt.
    Wenn ich die Datei per Browser aufrufe, bekomme ich keinerlei Meldung.
    In der rsslog.db ist leider auch kein Eintrag hinzugekommen.

    Ich habe noch nicht vestanden, wann die Einträge der FritzBox in die rsslog.db geschrieben werden. Rufst du dieses Script alle x Stunden auf? Hast du das per crontab umgesetzt?
    Gruß
    alexbeer

    Kommentar


      #3
      Du musst das unter /home/user ablegen und der Datei mindestens Ausführungsrechte für den Besitzer einräumen ("chmod u+x name.pl").

      Ich lasse das dann alle fünf Minuten von cron ausführen.

      Gruss,

      der Jan
      KNX, DMX over E1.31, DALI, 1W, OpenHAB, MQTT

      Kommentar


        #4
        Hi Jan,
        das läuft schon mal hervorragend. Jetzt schieb ich das freetzen meiner FB noch weiter hinaus, da ich es hauptsächlich auf den CallMonitor abgesehen hatte.

        Ich hätte gleich noch ein Feature-Request:
        Die letzten Anrufer haben wir ja schon - ich fände es klasse, wenn der Name zu der Nummer entweder aus dem Telefonbuch oder gar per revers-lookup gesucht werden könnte.

        Ich habe da auch schon etwas gefunden, das in die Richtung gehen könnte
        Anrufmonitor nutzen - Fritz!Box.
        Ich versuche mich da mal reinzufuchsen - könnte aber etwas dauern ...
        Gruß
        alexbeer

        Kommentar


          #5
          Hallo Jan,
          ich habe dich heute mal rangesetzt. Leider habe ich arge Verständnisprobleme - vielleicht kannst du mir ja ein paar Tipps geben:

          Mein Verständnis:
          Mit
          Code:
          my $sqlquery = 'INSERT INTO Logs(content, title, tags, t)
          wird ein Select auf die Fritz.Box DB gemacht und die aktuellen Einträge selektiert

          Meine Idee:
          Das Ergebnis der query wollte ich mit
          Code:
          $sqlquery->bind_columns
          oder
          Code:
          $ary_ref = $sqlquery->fetchrow_arrayref;
          in ein Array packen.
          Anschließend die $CallerID aus dem Array an das pl-Script aus dem Link oben übergeben und anstelle der Nummer den Namen des Anrufers in die RSSLOG.db schreiben.

          Allerdings bekomme ich bei den von mir verwendeten Methoden immer folgende Fehlermeldung:
          Code:
          Can't locate object method "fetchrow_arrayref" via package "INSERT INTO Logs(content, title, tags, t) VALUES( ....... );
          Irgendwo (finde den Link gerade nicht mehr) habe ich gelesen, dass die query nicht mit do(), sondern mit execute() aufgerufen werden müsse...

          Hast du - oder gerne auch jeder andere - da nen Ansatz?
          Gruß
          alexbeer

          Kommentar


            #6
            Zitat von alexbeer Beitrag anzeigen
            Mein Verständnis:
            Mit
            Code:
            my $sqlquery = 'INSERT INTO Logs(content, title, tags, t)
            wird ein Select auf die Fritz.Box DB gemacht und die aktuellen Einträge selektiert
            Keine Ahnung, was genau Du versuchst... aber der Befehl ist kein SELECT (lesen...) sonder ein Schreiben in die DB.

            Kommentar


              #7
              Ich weiss, was Du möchtest, aber so wird das nicht funktionieren. Du müsstest dafür rausfinden, wo die Fritzbox das Telefonbuch speichert (das lässt sich bestimmt er-google-n), dann diese Seite abrufen und ein entsprechendes Array anlegen. Vermutlich ist das ein XML, dass sich dann ähnlich parsen lässt wie die Anruferliste.

              Alles was SQL ist bezieht sich ausschliesslich auf die rsslog-Datenbank, meiner Kenntnis nach kann die Fritzbox damit nichts anfangen. Da musst du dann eigentlih auch garnichts dran ändern, ausser statt der Rufnummer den Namen im INSERT-Statement einzufügen.

              Gruss,

              der Jan
              KNX, DMX over E1.31, DALI, 1W, OpenHAB, MQTT

              Kommentar


                #8
                Ah, auf dem falschen Dampfer.
                Mt deiner Vermutung, dass das Telefonbuch xml basierz ist, liegst du richtig: http://wehavemorefun.de/fritzbox/ind...XML-Adressbuch das liegt wohl unter fritz.box/var/flash/phonebook.xml
                Vielleicht komme ich am Wochenende nen Schritt weiter.
                Gruß
                alexbeer

                Kommentar


                  #9
                  Die richtige URL für den Zugriff lautet

                  http://fritz.box/cgi-bin/webcm?getpa...gename=fonbuch
                  KNX, DMX over E1.31, DALI, 1W, OpenHAB, MQTT

                  Kommentar


                    #10
                    Der richtige Abruf dafür lautet allerdings:

                    Code:
                    $http_response = $user_agent->post("http://$boxaddress/cgi-bin/firmwarecfg", 
                      Content=>['sid' => $SID, 'PhonebookId' => 0, 'PhonebookExportName' => 'Telefonbuch', 
                      'PhonebookExport' => '' ], Content_Type => 'multipart/form-data');
                    Gruss,

                    der Jan
                    KNX, DMX over E1.31, DALI, 1W, OpenHAB, MQTT

                    Kommentar


                      #11
                      Hi,

                      ich hab heute dein Script versucht zum laufen zu bekommen.
                      Ich bekomme folgende Fehlermeldung:
                      Code:
                      root@wiregate619:/home/user# ./fritzbox.pl
                      DBD::SQLite2::st execute failed: no such table: Logs(1) at dbdimp.c line 412 at ./fritzbox.pl line 69.
                      Couldn't execute statement: no such table: Logs(1) at dbdimp.c line 412 at ./fritzbox.pl line 69.
                      Issuing rollback() for database handle being DESTROY'd without explicit disconnect() at ./fritzbox.pl line 69.
                      zum testen habe ich auf der FritzBox kein Passwort gesetzt, Berechtigungen der Dateien wurden auch gesetzt.

                      An was könnte es liegen?


                      Gruß

                      Kommentar


                        #12
                        Das sieht erstmal so aus, als würde die Datenbank nicht existieren? Hast Du den Pfad zu Datenbank angepasst und liegt da auch eine?

                        Gruss,

                        der Jan
                        KNX, DMX over E1.31, DALI, 1W, OpenHAB, MQTT

                        Kommentar


                          #13
                          Ja.
                          Im Script:
                          Code:
                          my $logdb = '/var/www/rsslog.db';
                          und rsslog.db:
                          Code:
                          [B]> ls -l /var/www/rsslog.db[/B]
                          -rwxrwxrwx 1 root root 0 24. Mär 12:35 /var/www/rsslog.db
                          stört der MySQL Server? (denke nicht, möchte es aber nicht ausschließen)

                          Gruß

                          Kommentar


                            #14
                            Der MySQL sollte nicht stören, aber 0 Byte scheint mir wenig zu sein. Am besten die DB von dem php von Chris erzeugen lassen, dann passts.

                            Der Jan
                            KNX, DMX over E1.31, DALI, 1W, OpenHAB, MQTT

                            Kommentar


                              #15
                              Genau das wars. Bei mir haben ein paar php pakete gefehlt. Anstatt einer Datenbank wurde nur eine leere Datei erstellt.
                              Danke

                              Gruß

                              Kommentar

                              Lädt...
                              X