Seite 1 von 2

Anrufernummer aus Fritz!Box auslesen

Verfasst: Mi, 21. Mär 2018 11:52
von bendixen
Ich möchte über LAN ein Signal an meine Fritz!Box 7580 senden und in der Folge die aktuell eingehende Anrufernummern in einer Datei erfassen, die ich beständig zur Weiterbearbeitung abfrage.
Bisher bekomme ich die Anrufernummer über einen an die Fritz!Box via S0-Anschluss angeschlossenen ISDN-Controller Fritz!Box USB und dem CAPI-Monitor von Stefan Schmitz (Capimon.exe).
Janrufmonitor ist mir bekannt aber die Installation viel zu aufwendig für das Auslesen nur der einen gerade eingehenden Anrufernummer.
Wer hat Erfahrung zu diesem Thema und kann mir weiterhelfen.

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Mi, 21. Mär 2018 13:03
von andreas

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 9:13
von Udo
Hallo,

vorausgesetzt AVM hat in den letzten Jahren das nicht geändert (bei mir läuft eine 7490) ist das ein Thema das Spaß macht.
Die FritzBox schickt Informationen über eingehende und ausgehende Anrufe über Port 1012. Es wird ein Socket zu Adresse, Port geöffnet, und dann wird auf einkommende Daten gewartet. Die schickst du an einen neuen Thread, der sie verarbeitet.

Zum dem Thema Socket gibt es ein Beispiel in den Alaska Samples ... asinet\sockets oder du suchst nach ServerThread.

Bei mir sieht das so aus:

Aufruf im Main.prg

Code: Alles auswählen

  * ---------------------------------------------------------------------------
  *  Thread  Telefonschnittstelle
  * ---------------------------------------------------------------------------
  IF FRITZ_ON
    IF empty(FRITZ_IP)
      msg("Die Fritzbox kann nicht aktiviert werden,\ "+;
          "da keine IP Adresse angeben wurde.","",;
          " dFAKT Friztbox-Schnittstelle","W",oDfdlg)
    ELSE
      oThread := ServerThread():new( alltrim(FRITZ_IP) , 1012 )
      oThread:start()
    ENDIF
  ENDIF

Der ServerThread

Code: Alles auswählen

/* ***************************************************************************
 *
 * Der ServerThread wartet auf ankommende Nachrichten
 */
CLASS ServerThread FROM Thread
   PROTECTED:
   VAR nPort     /* Zielport */
   VAR cAddress  /* Zieladresse */
   VAR nSocket
   VAR nError

   EXPORTED:
   METHOD init, atStart, execute, atEnd, stop
   METHOD logCall
ENDCLASS


METHOD ServerThread:init( cAddress, nPort )
   ::Thread:init()
   ::nSocket  := 0
   ::cAddress := cAddress
   ::nPort    := nPort
RETURN self

/*
 * Threadstart!
 *
 * Der Socket wird erzeugt, und mit setInterval(0) wird dafuer gesorgt,
 * dass execute permanent laeuft.
 */
METHOD ServerThread:atStart
   ::nSocket := SocketOpen(SOCK_STREAM, ::cAddress, ::nPort, @::nError)

   IF ::nSocket <> 0
      ::setInterval(0)
   ELSE
     /* hier irgendwas nuetzliches mit nError anfangen FIXME */
   ENDIF
RETURN self


/*
 * Thread laeuft hier
 *
 * Daten von der Box werden empfangen
 */
METHOD ServerThread:execute
   LOCAL cBuffer := space(1024) /* keine ahnung, wie gross das werden darf FIXME */
   LOCAL nRead

   IF ::nSocket <> 0
      /* der Socket ist Blocking, also wird gewartet */
      nRead := SocketRecv(::nSocket, @cBuffer, 1024, @::nError)

      IF nRead > 0
         ::logCall( left(cBuffer, nRead) )
      ENDIF
   ENDIF
RETURN self


/*
 * Thread is ending!
 */
METHOD ServerThread:atEnd
   ::nSocket := 0
RETURN self


/*
 * Stop listening thread from outside!
 *
 * :setInterval( NIL ) results in :execute() not being called again.
 * SocketClose() causes SocketAccept() -which is blocking- to return.
 * :synchronize(0) causes external function to wait until this thread
 * has ended.
 */
METHOD ServerThread:stop
   IF ::nSocket <> 0
      ::setInterval( NIL )

      SocketClose( ::nSocket )

      ::synchronize(0)
   ENDIF
RETURN self


/*
 * Anzeige der Anrufinformation
 *  Ausgehende Anrufe: datum;CALL;ConnectionID;Nebenstelle;GenutzteNummer;AngerufeneNummer;
 *  Eingehende Anrufe: datum;RING;ConnectionID;Anrufer-Nr;Angerufene-Nummer;
 *  Zustandegekommene Verbindung: datum;CONNECT;ConnectionID;Nebenstelle;Nummer;
 *  Ende der Verbindung: datum;DISCONNECT;ConnectionID;dauerInSekunden;
*/

METHOD ServerThread:logCall( cData )
   LOCAL oThread

   oThread := Thread():new()
   oThread:Start("Telefon","FRITZBOX",cData)

RETURN self


Die Weiterverarbeitung erfolgt in der Procedure "Telefon". Die muss im eigenen Thread gestartet werden, da ja mehrere ein und ausgehende Telefonate gleichzeitig eintreffen können.

Glück Auf!
Udo

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 9:41
von brandelh
Das werde ich mir auch mal ansehen, in der Web-Oberfläche der Fritz.Box erscheinen die Infos erst nachdem Ende (evtl. etwas verspätet danach) ...
wenn ich also am PC wissen will, wer gerade angerufen hat (und ein anderer im Hause abgenommen hat) ... habe ich nun einen anderen Weg :-)

Evtl. kann ich mir auch einen RING ... wer ruft gerade an ... Bildschirm einblenden, mal sehen

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 10:21
von bendixen
Danke für die Antworten!
Ich werde versuchen, das in meinem Programm zu realisieren.
Muss leider anmerken, dass meine Programmier-Kenntnisse aus dBase-Clipper-Ursprüngen (1986 beginnend) stammen und ich bisher lediglich den Übergang zu Xbase++ (im Prinzip 1:1) bewältigt habe und mir die aktuellen 'höheren' Programmiertechniken noch fremd sind.

Grüße, Jürgen

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 13:00
von Udo
@Jürgen - dann hast du mir beim Thema Clipper 1 Jahr voraus :wink:
Das Programm solltest du zum Laufen bringen, ich gehöre auch nicht zu den Fittesten unter den Xbaselern.
Fährst du zum Forentreffen nach Dresden ?

@Hubert, du bekommt alle Ereignisse sofort im Netz signalisiert. Mit dem RING, öffne ich die Kundendaten und habe alles auf dem Schirm bevor ich den Hörer abhebe. Etwas knifflig ist es gewesen die Dauer der Gespräche, insbesondere bei mehreren gleichzeitig ein- und ausgehenden Telefonaten, festzuhalten. Aber wenn man erst mal alles einfach in eine DBF wegschreibt hat man schon mal Spaß.

Ach, noch ein Tipp, die Anzeige der Telefonate so ausgeben, dass nicht ein Thread den anderen übermalt. Viele Wege führen nach Rom...

Glück Auf!
Udo

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 13:21
von Martin Altmann
Vielleicht gibt es ja im nächsten Jahr beim Forentreffen einen Vortrag dazu. Man hört ja so einiges im Hintergrund 8)

Viele Grüße,
Martin

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 14:05
von brandelh
Für mich wäre das nur interessant um ...
1. bekannte Nummern von unbekannten (Werbeanrufe), bzw.
2. unbeliebten ... ne den jetzt nicht ... zu unterscheiden ...

Ein Brüller durchs Haus "Nicht abheben !!!" würde mir dann den Tag retten :-)

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 15:19
von Manfred
hast Du keine Robinsonliste?

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 15:50
von brandelh
hast Du keine Robinsonliste?
Ich kenne Regenbogentabellen, aber das ist wohl was anderes ;-)

die aus dem 2. Punkt sind durchaus Bekannte und auch Familienmitglieder ... aber irgendwann will man ja mal seine Ruhe haben (ich zumindest) :-)

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 15:56
von Jan
Was hilft mir denn die Robinsonliste gegen verbotene Kaltaquise-Anrufe? An die Liste halten sich nur legal arbeitende, seriöse Firmen.

Jan

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 16:04
von Manfred
in der 7490 z.B kann man verschiedene Telefonbücher anlegen. Darunter auch eines, was man als Robinsonliste laufen läßt. Dort kommen dann Telefonnummern rein, die man nicht annehmen will. Dann wird in Telefonie/Rufbehandlung/Rufsperren dieses Telefefonbuch für eingehened Anrufe als gesperrt eingetragen. Und nichts tut sich mehr mit den Rufnummern.
Man kann aber auch Telefonbücher anlegen und die darin angelegten Rufnummern als wichtig kennzeichnen und dann der Fritzbox sagen, die wichtigen versehe bitte mit einem speziellen Klingelton (geht aber m.E. nur mit Fritztelefonen) Oder ordnet bestimmten Anrufernummern bestimmte Klingeltöne zu. Dann kann man direkt hören, wer es ist, wenn die anrufen. Da bekommt der alte Spruch :" habe ich am Klingelton erkannt" zur Geltung.

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 16:20
von Bertram Hansen
So mache ich das bei meiner FritBox 7490 auch. Jeder der nervt kommt manuell in die Liste und dann ist Ruhe. :D

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 17:29
von bendixen
@Udo - Hänge leider fest. Finde bei mir (Xbase++ 1.90) nichts zu folgendem Hinweis:

"Zum dem Thema Socket gibt es ein Beispiel in den Alaska Samples ... asinet\sockets oder du suchst nach ServerThread."

Habe mir ein kleines Progrämmchen zum Testen gestrickt, scheitere dabei an den Socket... Wie komme ich über die Hürde?

Forentreffen in Dresden scheitert an meiner Sauerstoffabhängigkeit.

Grüße, Jürgen

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 22. Mär 2018 17:42
von Jan
bendixen hat geschrieben: Do, 22. Mär 2018 17:29Forentreffen in Dresden scheitert an meiner Sauerstoffabhängigkeit.
?

Jan

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Fr, 23. Mär 2018 6:29
von brandelh
Die Socket Funktionen sind in der Asinet Bibliothek, die gibt es aber erst mit Professional Version

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Fr, 23. Mär 2018 7:33
von Koverhage
Bertram,
leider ist dort bei 30 Nummern Schluss.
Werde mal wie Manfred vorgeschlagen versuchen dieses Limit mit Anlegen von Telefonbüchern zu umgehen.

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Fr, 23. Mär 2018 10:34
von Udo
Hallo Jürgen,

Sorry, an die verschiedenen Xbase Versionen habe ich nicht gedacht. V1.9 benutze ich schon eine ganze Weile nicht mehr. Das führt dann aber zu der Frage (in die Runde), kann man dem Mann helfen ?

Kann ich mit V2.0 Jürgen die kleine Routine in irgendeiner Form (DLL ?) zur Verfügung stellen, dass er sie mit V1.9 nutzen kann ? Wäre das erlaubt ?
Hmmm, alternativ eine EXE, die ihm die Werte 1:1 übergibt. Aber wie wäre da der Ansatz....

Glück Auf!
Udo

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Fr, 23. Mär 2018 10:42
von Tom
Hallo, Udo.

Du müsstest Runtimes (DLLs) mitliefern, die dann nicht weitergegeben werden dürften.*

Trotz 2.0 verwende ich für alles, was mit Servern, Mail und Internet zu tun hat, weiter Xb2.Net. Das ist enorm robust, sehr schnell und extrem zuverlässig. Und der Code, um einen Telefonserver aufzusetzen, wie hier skizziert, wäre auch kompakter. Dies nur am Rande.

(*aber zum Testen geht das natürlich.)

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Fr, 23. Mär 2018 11:09
von Bertram Hansen
Koverhage hat geschrieben: Fr, 23. Mär 2018 7:33 Bertram,
leider ist dort bei 30 Nummern Schluss.
Werde mal wie Manfred vorgeschlagen versuchen dieses Limit mit Anlegen von Telefonbüchern zu umgehen.
Bin aktuell bei 18 Sperreinträgen. Da habe ich noch ein wenig Luft.

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Fr, 23. Mär 2018 12:05
von bendixen
Mir wäre ja jede mögliche Lösung willkommen, die in Verbindung mit meinem Xbase++ 1.90 die gerade eingehende Rufnummer auslesen lässt.
Grüße, Jürgen

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Fr, 23. Mär 2018 17:16
von Udo
Hallo Jürgen,

ich sitze auf den Koffern für die Osterferien; die Lösung über eine DLL muss ich mir mal ansehen. Besser wäre ich könnte dir eine EXE geben, die die Fritzbox Daten 1:1 an dein Programm schickt, damit du sie beliebig verarbeiten kannst. Sollte ja möglich sein von einem Xbase Programm an ein anderes Daten zu schicken. So in die Richtung gedacht, etwas in die Windows- Ereignisqueue zu schicken, auf das du im Event-Handler zugreifen kannst. Aber das muss warten - die Sonne ruft.

Ich bin dann mal weg, Udo

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Sa, 24. Mär 2018 8:07
von bendixen
Hallo Udo,
ich wünsche dir vorab sonnige Osterferien.
Bin schon mal zuversichtlich auf die Lösung gespannt:
Meine Zotac-Anwendung (PI223) würde ohne Fritz!Card USB auskommen und im USB-Hub einen freien Port gewinnen.
Grüße, Jürgen

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 26. Apr 2018 9:41
von Udo
Hallo Jürgen,

endlich bin ich dazu gekommen mir die Fritz Geschichte noch mal anzusehen. Ich schicke dir einen Link per PN zum Download einer compilierten Version, die die Fritz Nachrichten 1:1 in eine DBF Tabelle "Telefon" schreibt. Die kannst du dann mit einem 1.9 Programm öffnen und weiterverarbeiten. Das Programm rufst du auf mit xFritz.exe <IP-Adresse deiner Fritzbox > [Port, default 1012]

Code: Alles auswählen

#include "Common.ch"
#include "Appevent.ch"
#include "Asinetc.ch"

#define CRLF chr(13)+chr(10)


/* This is our main procedure
 */
PROCEDURE Main( cFritzIP, cPort )
  LOCAL nEvent, mp1, mp2, oXbp, oThread

  cls
  ? "Hallo Fritz"

  IF empty(cFritzIP)         // 192.168.152.1
    ? "Die Fritzbox kann nicht aktiviert werden,"+;
        "da keine IP Adresse angeben wurde."
    ?
    ? "Syntax:  xFritz.exe  IP-Adresse   [Port]"
  ELSE
    IF !file("telefon.dbf")
      dbcreate( "Telefon.dbf",;
                {{ "FRITZMSG", "C", 100, 0}} )
      ? "telefon.dbf angelegt"

    ENDIF

    oThread := ServerThread():new( alltrim(cFritzIP) ,;
               iif(cPort == NIL, 1012, cPort ) )
    oThread:start()

    ?  "Abbruch mit ESC"

     DO WHILE nEvent<> xbeP_Close
        nEvent := AppEvent( @mp1, @mp2, @oXbp )
        oXbp:handleEvent( nEvent, mp1, mp2 )

        IF nEvent == xbeK_ESC
           EXIT
        ENDIF
     ENDDO
  ENDIF

RETURN

///<summary>
///<para>  wandelt den durch 'cDiv' getrennten 'cText' in ein Array um </para>
///<para>  cDiv default ";"   </para>
///</summary>
///<returns>  aZeilen                                                      </returns>
FUNCTION Explode(cText,cDiv)
  **************************
  LOCAL aRet := {}
  LOCAL nPos := 0
  cDiv := IIF(cDiv==NIL,";",cDiv)
  nPos := at(cDiv,cText)
  DO WHILE nPos>0
    aadd(aRet,left(cText,nPos-1))
    cText := substr(cText,nPos+1)
    nPos := at(cDiv,cText)
  ENDDO
  IF !empty(cText)
    aadd(aRet,cText)
  ENDIF
RETURN (aRet)


/* ***************************************************************************
 *
 * Der ServerThread wartet auf ankommende Nachrichten
 */
CLASS ServerThread FROM Thread
   PROTECTED:
   VAR nPort     /* Zielport */
   VAR cAddress  /* Zieladresse */
   VAR nSocket
   VAR nError

   EXPORTED:
   METHOD init, atStart, execute, atEnd, stop
   METHOD logCall
ENDCLASS


METHOD ServerThread:init( cAddress, nPort )
   ::Thread:init()
   ::nSocket  := 0
   ::cAddress := cAddress
   ::nPort    := nPort
RETURN self

/*
 * Threadstart!
 *
 * Der Socket wird erzeugt, und mit setInterval(0) wird dafuer gesorgt,
 * dass execute permanent laeuft.
 */
METHOD ServerThread:atStart
   ::nSocket := SocketOpen(SOCK_STREAM, ::cAddress, ::nPort, @::nError)
   ? ts()+"Start"
   IF ::nSocket <> 0
      ::setInterval(0)
   ELSE
     /* hier irgendwas nuetzliches mit nError anfangen FIXME */
   ENDIF
RETURN self


/*
 * Thread laeuft hier
 *
 * Daten von der Box werden empfangen
 */
METHOD ServerThread:execute
   LOCAL cBuffer := space(1024) /* keine ahnung, wie gross das werden darf FIXME */
   LOCAL nRead

   IF ::nSocket <> 0
      /* der Socket ist Blocking, also wird gewartet */
      nRead := SocketRecv(::nSocket, @cBuffer, 1024, @::nError)

      IF nRead > 0
         ::logCall( left(cBuffer, nRead) )
      ENDIF
   ENDIF
RETURN self


/*
 * Thread is ending!
 */
METHOD ServerThread:atEnd
   ::nSocket := 0
   ? ts()+"End"
RETURN self


/*
 * Stop listening thread from outside!
 *
 * :setInterval( NIL ) results in :execute() not being called again.
 * SocketClose() causes SocketAccept() -which is blocking- to return.
 * :synchronize(0) causes external function to wait until this thread
 * has ended.
 */
METHOD ServerThread:stop
   IF ::nSocket <> 0
      ::setInterval( NIL )

      SocketClose( ::nSocket )

      ::synchronize(0)
   ENDIF
RETURN self


/*
 * Anzeige der Anrufinformation
 *  Ausgehende Anrufe: datum;CALL;ConnectionID;Nebenstelle;GenutzteNummer;AngerufeneNummer;
 *  Eingehende Anrufe: datum;RING;ConnectionID;Anrufer-Nr;Angerufene-Nummer;
 *  Zustandegekommene Verbindung: datum;CONNECT;ConnectionID;Nebenstelle;Nummer;
 *  Ende der Verbindung: datum;DISCONNECT;ConnectionID;dauerInSekunden;
*/

METHOD ServerThread:logCall( cData )
   #define FC_
   LOCAL oThread
   ? cData

   oThread := Thread():new()
   oThread:Start("Telefon","FRITZBOX",cData)

RETURN self


/// <summary>
/// <para>  cQuelle  - Eingangsschnittstelle z.b. FRITZBOX              </para>
/// <para>  cData    - Uebergabedaten                                   </para>
/// </summary>
/// <returns> NIL                                                </returns>
PROCEDURE Telefon(cQuelle, cData)
  use telefon.dbf alias tel new
  dbappend()
  tel->fritzmsg := cData
  dbskip(0)
  dbunlock()
  dbclosearea()
RETURN



STATIC FUNCTION ts()

RETURN( dtoc(date())+" "+time()+": " )
Das Rausschreiben in eine Textdatei wäre auch möglich gewesen, ich denke aber die DBF hat den Vorteil, dass Schreiben (xFritz) und Lesen (dein Programm) zeitgleich stattfinden können.

Friedhelms Vortrag auf dem Forentreffen in Dresden hat mich dazu verleitet mir die Simple Services anzusehen und in der Tat kann man recht schnell xFritz als Service schreiben und installieren.

Code: Alles auswählen

#include "service.ch"
#include "fileio.ch"

#define STAT_RUNNING    1
#define STAT_NOTRUNNING 2
#define STAT_PAUSING    3

#define CRLF chr(13)+chr(10)


PROCEDURE Main()
  ServiceApplication():start()
RETURN

CLASS ServiceApplication FROM ServiceApp

  HIDDEN:
    CLASS VAR    _Status

  EXPORTED:

    CLASS ACCESS METHOD getStopped VAR Stopped

    CLASS METHOD main
    CLASS METHOD pause
    CLASS METHOD CONTINUE
    CLASS METHOD stop

ENDCLASS

CLASS METHOD ServiceApplication:getStopped()
RETURN(::_Status==STAT_NOTRUNNING)

CLASS METHOD ServiceApplication:main()
   LOCAL oWasSagtFritz := ServerThread():new( "192.168.178.1", 1012 )
   oWasSagtFritz:Start()

  DO WHILE ::_Status != STAT_NOTRUNNING

    IF ::_Status == STAT_PAUSING
      /* $TODO: pause your application */
      Sleep( 10 )
      Loop
    ENDIF
    /* Die Haupschleife macht NIX - gelauscht wird im ServerThread  */
    sleep(10)

  ENDDO

  ::oWasSagtFritz:Stop()

RETURN self

CLASS METHOD ServiceApplication:pause()
  ::_Status := STAT_PAUSING
RETURN

CLASS METHOD ServiceApplication:continue()
  ::_Status := STAT_RUNNING
RETURN

CLASS METHOD ServiceApplication:stop()
  ::_Status := STAT_NOTRUNNING
RETURN

Ist im wesentlichen aus den Xbase Samples (ja - sorry, Prof 2.0) übernommen. Dort findet sich auch der Code für den Controler um den Service auf dem PC zu installieren. Ich bin überrascht, wie einfach das geht. Ich war nur noch zu faul die Parameter IP Adresse und Port aus einer INI auszulesen, damit man das allgemein verwenden kann. Aber, wenn es jemand braucht, wäre das auch kein Problem.

Glück Auf!
Udo

Re: Anrufernummer aus Fritz!Box auslesen

Verfasst: Do, 26. Apr 2018 9:44
von brandelh
Diesen Beitrag setzt ich bei mir gleich mal auf Favorit, SUPER :-)