- Mitglied seit
- 17 Jun 2004
- Beiträge
- 15
- Punkte für Reaktionen
- 0
- Punkte
- 1
Hallo zusammen.
Ich war schon seit längerem auf der Suche nach einer Möglichkeit, die CallerID eines Anrufer per OSD unter Windows anzuzeigen. Da ich nichts gefunden habe was meinen Anforderungen gerecht wurde, habe ich mich mal rangesetzt und eine kleine Lösung mittels ein paar Perl-Scripts und dem Automatisierungs-Tool Girder gebastelt.
An dieser Stelle vielen Dank an Ber5erker, dessen Client-/Server-Scripts ich dabei verwurstet habe
---
Um dem Anrufer auch einen Namen zugeben, habe ich ein kleines Script geschrieben welches anhand einer Text-Datei einen Abgleich vornimmt.
/var/lib/asterisk/agi-bin/cid-match.agi
Die zugehörige Text-Datei ist recht simpel gestrickt und hat folgenden Aufbau:
/etc/asterisk/cid-match.settings
/etc/asterisk/extensions.conf
Der zweite Eintrag in der extensions.conf ist die Übermittlung von Event-Trigger, Name, Rufnummer und Zeit an Girder auf dem Windows-PC. Hier habe ich bei dem Script auf eine bereits existierende Lösung von jjk aus dem Promixis-Forum zurückgegriffen.
IP und Port des Zielrechners sind fest im Script hinterlegt. Werde ich bei Zeiten noch anpassen um flexibler zu sein.
/usr/girder/ievent.pl
Auf dem Windows-PC nimmt der Girder Internet Event Server die Daten entgegen. Girder öffnet das OSD und zeigt für ein paar Sekunden Anrufer-Name und -Nummer an (Anhang: Asterisk-OSD1.jpg).
Da mir wichtig war, mehr als nur den letzten Anrufer zu sehen, werden die Daten der letzten fünf Anrufer zwischengespeichert.
Über Ctrl+Shift+C kann ich bei Bedarf meinen "Anrufmonitor" (Anhang: Asterisk-OSD2.jpg) öffnen. Im Prinzip nichts weiter als ein völlig frei konfigurierbares HTML OSD. Dort werden mir, sofern vorhanden, die Daten der letzten Anrufer angezeigt.
Durch anklicken der Namen kann ein direkter Rückruf ausgeführt werden. Erst klingelt das interne Telefon, und nach dem Abnehmen wird der Ruf nach Aussen signalisiert.
Dafür läuft folgendes Script auf dem Asterisk und wartet auf Daten:
/usr/girder/empfaenger.pl
Das Gegenstück auf dem Windows-PC sieht so aus:
sender.pl
Da ich auf dem Windows-PC kein Perl laufen habe, hab ich die sender.pl mit perl2exe direkt ausführbar gemacht.
Bei einem Rückruf übergibt Girder Channel und Zielnummer als Parameter an die sender.exe. Diese überträgt die Daten an das Script empfaenger.pl auf dem Asterisk welches das Callfile erstellt und in den Context osd-callback springt.
/etc/asterisk/extensions.conf
Alles in allem vielleicht keine ideale Lösung und schlampig programmiert, aber man ist doch recht flexibel in der Darstellung und Verarbeitung der Daten.
Bei Interesse stelle ich das passende Girder GML-File gerne bereit.
Verbessungsvorschläge sowie positive und negative Kritik werden gerne genommen.
Ich war schon seit längerem auf der Suche nach einer Möglichkeit, die CallerID eines Anrufer per OSD unter Windows anzuzeigen. Da ich nichts gefunden habe was meinen Anforderungen gerecht wurde, habe ich mich mal rangesetzt und eine kleine Lösung mittels ein paar Perl-Scripts und dem Automatisierungs-Tool Girder gebastelt.
An dieser Stelle vielen Dank an Ber5erker, dessen Client-/Server-Scripts ich dabei verwurstet habe
---
Um dem Anrufer auch einen Namen zugeben, habe ich ein kleines Script geschrieben welches anhand einer Text-Datei einen Abgleich vornimmt.
/var/lib/asterisk/agi-bin/cid-match.agi
Code:
#!/usr/bin/perl
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();
my ($cid)=@ARGV;
my $basedir = "/etc/asterisk/";
$filename = "cid-match.settings";
&open_file("FILE1","","$basedir$filename");
my $counter = 0;
my $cidname = "unbekannt";
while (($line = &read_file("FILE1")) && ($counter < 100))
{
@tabledata = split(/\s*\|\s*/,$line ,$fields);
if ($tabledata[0] =~ $cid)
{
$cidname = $tabledata[1];
print STDOUT "SET VARIABLE CALLER_NAME \"$cidname\"\n";
}
else
{
print STDOUT "SET VARIABLE CALLER_NAME \"$cidname\"\n";
$counter++;
}
}
close(FILE1);
if ($counter == 0)
{
print STDERR "Datei hat keinen Inhalt.\n";
}
sub open_file
{
local ($filevar, $filemode, $filename) = @_;
open ($filevar,$filemode . $filename) ||
die ("Unable to open $filename");
}
sub read_file
{
local ($filevar) = @_;
<$filevar>;
}
Die zugehörige Text-Datei ist recht simpel gestrickt und hat folgenden Aufbau:
/etc/asterisk/cid-match.settings
Code:
1234567|Hans Testermann
3456789|Julia Musterfrau
/etc/asterisk/extensions.conf
Code:
exten => s,n,AGI(cid-match.agi|${CALLERIDNUM}) ;Auswertung der CID und Rückgabe des Anrufer-Namens in ${CALLER_NAME}
exten => s,n,System(perl /usr/girder/ievent.pl osd "${CALLER_NAME}" ${CALLERIDNUM} "${DATETIME}")
Der zweite Eintrag in der extensions.conf ist die Übermittlung von Event-Trigger, Name, Rufnummer und Zeit an Girder auf dem Windows-PC. Hier habe ich bei dem Script auf eine bereits existierende Lösung von jjk aus dem Promixis-Forum zurückgegriffen.
IP und Port des Zielrechners sind fest im Script hinterlegt. Werde ich bei Zeiten noch anpassen um flexibler zu sein.
/usr/girder/ievent.pl
Code:
#!/usr/bin/perl
# Set path according to your system
#
# Internet event client for Perl
# Modified from IE2Client.pl
#
$host = "10.10.x.x"; # Hardwire the host, port, and password
$port = 1244; # to match the settings of the server
$passwd = "xxxx"; # plugin.
use IO::Socket;
use Text::ParseWords;
use Digest::MD5;
my ($socket); # Socket will be global
##
## Mainline
##
{
my ($rsp, $ctx, $i, $DEBUG);
$DEBUG=0;
# Stop if no event
if ($#ARGV == -1) {die "Usage: ievent.pl <event payload(s)>\n"; }
# Create/connect the socket
$socket = IO::Socket::INET->new("$host:$port") || die $@;
$rsp = grdr_resp("quintessence"); # Validate/start the connection
$ctx = Digest::MD5->new->add("$rsp:$passwd");
$rsp = grdr_resp($ctx->hexdigest);
if ($rsp !~ /^accept$/) { die "Invalid password" }
if ($DEBUG) { printf("ARGV = %d\n", $#ARGV); }
if ($#ARGV > 0) {
for ($i = 1; $i <= $#ARGV; $i++) {
grdr_send("payload @ARGV[$i]");
if ($DEBUG) {printf("payload @ARGV[$i]\n");}
}
}
grdr_send(@ARGV[0]);
if ($DEBUG) {printf("$ARGV[0]\n");}
grdr_send("close"); # Shut everything down
close ($socket);
}
##
## Subroutines
##
sub grdr_send ## Send a girder command line
{
print $socket $_[0],"\n"; # Girder wants terminating "\n"
}
sub grdr_recv ## Get a girder response
{
my $line = <$socket>; # Get response
chomp $line; # Strip trailing "\n"
return $line;
}
sub grdr_resp ## Do a command-response sequence
{
grdr_send($_[0]);
return grdr_recv();
}
Auf dem Windows-PC nimmt der Girder Internet Event Server die Daten entgegen. Girder öffnet das OSD und zeigt für ein paar Sekunden Anrufer-Name und -Nummer an (Anhang: Asterisk-OSD1.jpg).
Da mir wichtig war, mehr als nur den letzten Anrufer zu sehen, werden die Daten der letzten fünf Anrufer zwischengespeichert.
Über Ctrl+Shift+C kann ich bei Bedarf meinen "Anrufmonitor" (Anhang: Asterisk-OSD2.jpg) öffnen. Im Prinzip nichts weiter als ein völlig frei konfigurierbares HTML OSD. Dort werden mir, sofern vorhanden, die Daten der letzten Anrufer angezeigt.
Durch anklicken der Namen kann ein direkter Rückruf ausgeführt werden. Erst klingelt das interne Telefon, und nach dem Abnehmen wird der Ruf nach Aussen signalisiert.
Dafür läuft folgendes Script auf dem Asterisk und wartet auf Daten:
/usr/girder/empfaenger.pl
Code:
#!/usr/bin/perl
# empfaenger.pl -- Ein Single-threaded-TCP-Server
use strict;
use IO::Socket;
use Asterisk::AGI;
use constant MYPORT => 52401;
my $sock = '';
my $client = 0;
my $counter = 0;
my @payload = '';
my $spoolpath = "\/var/spool\/asterisk\/outgoing";
$sock = new IO::Socket::INET(LocalPort => MYPORT,
Reuse => 1,
Listen => 5)
or die "can't create local socket: $@\n";
print "Accepting connections on Port ", MYPORT, "...\n";
while ($client = $sock->accept())
{
for (<$client>)
{
chomp;
@payload = split(/\s*\-\s*/,$_);
# Debug
# while (($payload[$counter] ne "") && ($counter < 30)) {
# print "Payload$counter: $payload[$counter]\n";
# $counter++; }
my $callfile = (int(rand(99999))+ 1) . ".call";
open(OUT, ">$spoolpath\/$callfile") or
die "Cannot create file $callfile: $!";
print OUT "Channel: $payload[0]\n";
print OUT "MaxRetries: 1\n";
print OUT "RetryTime: 60\n";
print OUT "WaitTime: 30\n";
print OUT "Context: osd-callback\n";
print OUT "Extension: $payload[1]\n";
print OUT "Priority: 1\n";
close(OUT);
print STDOUT "SET VARIABLE OSD-EXTERN \"$payload[1]\"\n";
}
$client->close() if defined $client;
}
Das Gegenstück auf dem Windows-PC sieht so aus:
sender.pl
Code:
#!/usr/bin/perl
# sender.pl -- Ein einfacher TCP-Client.
use strict;
use IO::Socket;
use constant TIMEOUT => 5;
my $ipaddr = '10.10.x.x';
my $portnr = '52401';
my $sock = '';
my $reply = '';
$sock = new IO::Socket::INET(PeerAddr => $ipaddr,
PeerPort => $portnr,
Proto => 'tcp', Timeout => TIMEOUT)
or die "can't connect to $ARGV[0]:$ARGV[1]: $@\n";
print $sock $ARGV[0],$ARGV[1];
$sock->close();
Da ich auf dem Windows-PC kein Perl laufen habe, hab ich die sender.pl mit perl2exe direkt ausführbar gemacht.
Bei einem Rückruf übergibt Girder Channel und Zielnummer als Parameter an die sender.exe. Diese überträgt die Daten an das Script empfaenger.pl auf dem Asterisk welches das Callfile erstellt und in den Context osd-callback springt.
/etc/asterisk/extensions.conf
Code:
[osd-callback]
exten => _.,1,NoOp(${EXTEN}) ;Debug
exten => _.,2,Dial(SIP/${EXTEN}@qsc_out||rm
exten => _.,3,Hangup
exten => h,1,Hangup
Alles in allem vielleicht keine ideale Lösung und schlampig programmiert, aber man ist doch recht flexibel in der Darstellung und Verarbeitung der Daten.
Bei Interesse stelle ich das passende Girder GML-File gerne bereit.
Verbessungsvorschläge sowie positive und negative Kritik werden gerne genommen.