averlon has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am currently trying some things with Net::Fritz. In general I got it working.
Now I would like to try to setup a callmonitor to get informed on incoming and outgoing calls.
Could someone give me a hint what Service to call to get informed by calls?
Thanks

2022-10-12 Athanasius moved the question up from the signature area.

Regards Kallewirsch
  • Comment on Net::Fritz what service to use to catch incoming call

Replies are listed 'Best First'.
Re: Net::Fritz what service to use to catch incoming call
by Corion (Patriarch) on Oct 08, 2022 at 08:00 UTC

    Back in the day, I wrote a small call monitor that used TCP port 1012 - the FritzBox sends a CSV-line for each incoming/outgoing call there. Today I would rewrite this using Mojolicious as the event loop, or maybe some other thing, but here is my code. The most interesting part is in dispatch_line, everything else is just setting up the (re)connection to the Growl service and AnyEvent (both of which I don't use anymore ...)

    package AnyEvent::FritzBox; use strict; use List::MoreUtils qw( zip ); use AnyEvent; use AnyEvent::Socket; use AnyEvent::Handle; use Data::Dumper; use Scalar::Util qw(weaken blessed); # Dial C<#96*5*> to enable the TCP call monitor use vars qw< %indicator_map %field_map >; %indicator_map = ( CALL => 'on_call', RING => 'on_ring', CONNECT => 'on_connect', DISCONNECT => 'on_disconnect', ); %field_map = ( on_call => [ qw[ date kind id local_id local_number remote_n +umber provider ] ], on_ring => [ qw[ date kind id remote_number local_number pro +vider ] ], on_connect => [ qw[ date kind id local_id remote_number ]], on_disconnect => [ qw[ date kind id seconds ]], ); sub new { my ($class, %args) = @_; $args{ on_call } ||= sub {}; $args{ on_ring } ||= sub {}; $args{ on_disconnect } ||= sub {}; $args{ max_retries } ||= 10; # We always give up after 10 attempts + to connect $args{ reconnect_cooldown } ||= 2; # Start value for the exponenti +al falloff $args{ current_reconnect } = undef; # we are not (yet) reconnectin +g if ($args{ log } && !ref $args{ log }) { $args{ log } = sub { print "@_\n" }; }; my $self = bless \%args => $class; my $s = $self; my $connected = AnyEvent->condvar; my $have_handle = AnyEvent->condvar(cb => sub { #$self->log("Have handle"); $s->setup_handle($self->{ handle }); $connected->send() if $connected; # This should be done more elegantly by # putting this into the callback of $connected my $c = $s->{on_connect}; unshift @_, $s; undef $s; goto &{ $c } if $c; }); if (! $self->{ handle }) { $self->{ host } ||= 'fritz.box'; $self->{ port } ||= 1012; $self->log("Launching connect"); $self->connect( $self->{host}, $self->{port}, $have_handle); } else { $have_handle->send(); }; # We are synchronous here in case there is no continuation passed +in if ($self->{synchronous} or not $self->{on_connect}) { $args{ on_connect_fail } = sub { undef $self; $connected->send +; }; $connected->recv; } else { $args{ on_connect_fail } = sub {}; }; undef $connected; # clean up stuff held by closure $self }; sub log { my $s = shift; my $l = $s->{log}; goto &$l if $l; }; sub connect { my ($self,$host,$port,$connected) = @_; $self->log("Connecting to $host:$port"); tcp_connect $host, $port, sub { my ($fh) = @_; if (! $fh) { $self->log("Couldn't connect to $host:$port"); $self->timed_reconnect($host,$port,$connected); # launch r +econnect timer return; }; # we got a connection, reset our retry counters $self->log("Connected to $host:$port"); $self->{current_reconnect} = undef; $self->setup_handle($fh); $connected->send(); }; return 1 }; sub timed_reconnect { my ($self,$host,$port) = @_; if (! $self->{current_reconnect}->{timer}) { if ($self->{current_reconnect}->{retried}++ < $self->{max_retr +ies}) { # We add a fuzz delay of up to 2 seconds to prevent stampe +ding herds my $cooldown = $self->{reconnect_cooldown} ** $self->{curr +ent_reconnect}->{retried} + rand(2); $self->log( "Reconnecting in $cooldown seconds" ); $self->{current_reconnect}->{timer} ||= AnyEvent->timer(af +ter => $cooldown, cb => sub { $self->log( "Reconnecting to $host:$port" ); # Tell ourselves that our callback triggered delete $self->{current_reconnect}->{timer}; my $connected = AnyEvent->condvar(); $connected->cb(sub { $self->log( "Reconnected" )} ); $self->connect($host, $port, $connected); }); } else { $self->log("Maximum number of reconnects reached"); $self->{on_connect_fail}->($host,$port); die "No connection to $host:$port after $self->{max_retrie +s}"; }; } else { $self->log("Already reconnecting"); }; }; sub setup_handle { my ($self,$fh) = @_; if (not(blessed $fh and $fh->isa('AnyEvent::Handle'))) { $fh = AnyEvent::Handle->new( fh => $fh, ); }; $self->{handle} = $fh; $self->{ handle }->on_read(sub { my $h = $_[0]; $h->push_read( line => sub { #warn "READ: @_"; $self->dispatch_line(@_); }); }); #weaken $self; $self->{ handle }->on_error(sub { #warn "[" . __PACKAGE__ . "] socket error: $_[2]"; $_[0]->destroy; # Try to reconnect here, after some timeout if ($self) { if ($self->{current_reconnect} && $self->{current_reconnect}->{retried} >= $self->{max_r +etries}) { # Well, somebody could hear this, somewhere die "Maximum retries ($self->{max_retries}) reached tr +ying to connect to $self->{host}:$self->{port}"; }; $self->timed_reconnect($self->{host}, $self->{port}); }; }); }; # Outbound calls: datum;CALL;ConnectionID;LocalExtension;usedNumber;ca +lledNumber; # Inbound calls: datum;RING;ConnectionID;callerId;localNumber; # Connect: datum;CONNECT;ConnectionID;LocalExtension;Number; # Disconnect: datum;DISCONNECT;ConnectionID;durationInSeconds; sub dispatch_line { my ($self, $handle, $payload) = @_; $payload =~ s/\s+$//; return unless $payload; #warn "<<$payload>>"; my @info = split /;/, $payload; my $arg_handler = $indicator_map{ $info[1] }; #warn "Checking for \$self->{'$arg_handler'}"; if (my $handler = $self->{ $arg_handler }) { #warn "Triggering '$arg_handler'"; @_ = ($self, zip @{ $field_map{ $arg_handler } }, @info); goto &$handler; }; }; 1;
Re: Net::Fritz what service to use to catch incoming call
by choroba (Cardinal) on Oct 10, 2022 at 17:32 UTC
    Please, don't put your question into the "signature" part of the node. Some monks (e.g. me) use CSS to hide the signatures, so to them, your question appears empty.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]