|
# Category=Phone
|
|
|
|
#@ Interface to the Asterisk PBX for CallerID and Voicemail
|
|
#
|
|
|
|
=begin comment
|
|
|
|
Use this code to provide an interface between Misterhouse and the Asterisk
|
|
PBX using the Asterisk AGI and Asterisk Manager interfaces. T
|
|
|
|
This module provides the following features:
|
|
o Obtains CallerID information directory from Asterisk AGI
|
|
o Logs DTMF Dialing from Asterisk AGI
|
|
o Polls Asterisk for any new VoiceMail using Asterisk Manager
|
|
o Polls Asterisk for Unregistered IAX2 connections (phone system down) using Asterisk Manager
|
|
|
|
You must have the Asterisk PERL libraries installed.
|
|
You can download them from here: http://asterisk.gnuinter.net/
|
|
|
|
Add these to you mh.ini for AGI to Misterhouse security. These values must
|
|
match the corresponding values in /var/lib/asterisk/agi-bin/Misterh=House.agi
|
|
server_asterisk_port = 8090
|
|
asterisk_server_username = yourusername
|
|
asterisk_server_password = yourpassword
|
|
|
|
Add these to your mh.ini for Misterhouse to Asterisk Manager security
|
|
These settings must match the corresponding fields in /etc/asterisk/manager.conf
|
|
asterisk_manager_host = <name or IP address of asterisk server>
|
|
asterisk_manager_port = <manager port>
|
|
asterisk_manager_username = <manager username>
|
|
asterisk_manager_password = <manager password>
|
|
|
|
You manager.conf file needs to have "read classes" disabled to prevent asynchronous
|
|
events from being sent to the code module.
|
|
|
|
Define these parameters to check voice mail
|
|
asterisk_voicemail_period = <minutes between voicemail checks>
|
|
asterisk_voicemail_box = <mailbox id to check for voicemail>
|
|
|
|
=cut
|
|
|
|
use Asterisk::Manager;
|
|
use CID_Lookup;
|
|
use CID_Log;
|
|
use CID_Announce;
|
|
use Telephony_Item;
|
|
use PocketSphinx;
|
|
|
|
my ($auth, $username, $password, $callername, $callernumber, $line);
|
|
|
|
$ast_callerid = new Telephony_Item();
|
|
$cid_lookup = new CID_Lookup($ast_callerid);
|
|
$cid_log = new CID_Log($cid_lookup);
|
|
$cid_announce = new CID_Announce($cid_lookup, 'Call from $format1');
|
|
|
|
# Create the asterisk server on MisterHouse to accept incoming connections from Asterisk AGI
|
|
$asterisk_server = new Socket_Item(undef, undef, 'server_asterisk');
|
|
|
|
# Create the asterisk manager interface to poll Asterisk
|
|
$astman = new Asterisk::Manager;
|
|
|
|
$asterisk_listener = new PocketSphinx_Listener ("sphinx_microphone", 16000, 0, 1);
|
|
|
|
# Here we find data sent from Asterisk and parse it out and do what needs to be done with it.
|
|
# I am not good with MisterHouse as of yet to know the best way to handle certain things but this
|
|
# works for me and may need to be changed around to work for you. One of the things I changed is
|
|
# CallerID stuff so that I can keep better track of the line that the call came in on. I just copied
|
|
# some of the code from other files in MisterHouse to do what I needed done but there is definetly
|
|
# better ways to do this and I am hoping that someone will help guide me in the right direction
|
|
# or take it upon themselves to fix it and redistribute it back out for all to use.
|
|
if (my $data = said $asterisk_server) {
|
|
print_log("asterisk DATA: $data") if $Debug{asterisk};
|
|
# First check for the login and password before letting them do anything.
|
|
if (!$auth){
|
|
if ($data =~ /Login: (.*)/){
|
|
$username = $1;
|
|
} elsif ($username && $data =~ /Secret: (.*)/){
|
|
$password = $1;
|
|
if ($config_parms{asterisk_server_username} eq $username &&
|
|
$config_parms{asterisk_server_password} eq $password) {
|
|
$auth = 1;
|
|
} else {
|
|
set $asterisk_server "Incorrect login information\n\n";
|
|
$username = '';
|
|
$password = '';
|
|
}
|
|
}
|
|
} else {
|
|
if ($data =~ /CallerID:/){
|
|
$callername = "Unknown";
|
|
$callernumber = "Unknown";
|
|
$line = "1";
|
|
if ($data =~ /CallerID: .* \<+(.*)\> Line: (.*)/) {
|
|
$callername = "Unknown";
|
|
$callernumber = $1;
|
|
$callernumber =~ s/\"//g;
|
|
$callernumber =~ s/\+//g;
|
|
$line = $2;
|
|
}
|
|
elsif ($data =~ /CallerID: (.*) \<(.*)\> Line: (.*)/) {
|
|
$callername = $1;
|
|
$callernumber = $2;
|
|
$callernumber =~ s/\"//g;
|
|
$callernumber =~ s/\+//g;
|
|
$line = $3;
|
|
}
|
|
elsif ($data =~ /CallerID: (.*) Line: (.*)/) {
|
|
$callername = "Unknown";
|
|
$callernumber = $1;
|
|
$callernumber =~ s/\"//g;
|
|
$callernumber =~ s/\+//g;
|
|
$line = $2;
|
|
}
|
|
$ast_callerid->cid_name($callername);
|
|
$ast_callerid->cid_number($callernumber);
|
|
$ast_callerid->address($line);
|
|
$ast_callerid->cid_type("N");
|
|
$cid_lookup->set ("CID", $ast_callerid);
|
|
$callername = $cid_lookup->name( );
|
|
&audrey_callerid ($callername, $callernumber);
|
|
} elsif ($data =~ /DTMF:/){
|
|
$data =~ /DTMF: (.*) CallFrom: (.*)/;
|
|
$ast_callerid->cid_name("");
|
|
$ast_callerid->cid_number($1);
|
|
$ast_callerid->address($2);
|
|
$ast_callerid->cid_type("N");
|
|
my $dtmf = $1;
|
|
my $callfrom = $2;
|
|
$cid_lookup->set ("DIALED", $ast_callerid);
|
|
} elsif ($data =~ /Command:/){
|
|
$data =~ /Command:(.*) Response=(.*)/;
|
|
my $cmd = $1;
|
|
my $response = lc($2);
|
|
my $respond = "asterisk" if $response =~ /^y/;
|
|
print_log("Asterisk Command: $cmd with response code: $response") if $Debug{asterisk};
|
|
&process_external_command($cmd, 0, 'asterisk', $respond);
|
|
} elsif ($data =~ /Sphinx/){
|
|
$data =~ /(.*): extension: (.*)/;
|
|
my $command = $1;
|
|
my $extension = $2;
|
|
print_log("Asterisk Sphinx: command: $command extension: $extension") if $Debug{asterisk};
|
|
if ($command =~ /Sphinx Connect/) {
|
|
$asterisk_listener->start_listener( );
|
|
}
|
|
if ($command =~ /Sphinx Disconnect/) {
|
|
$asterisk_listener->stop_listener( );
|
|
}
|
|
}
|
|
$auth = '';
|
|
}
|
|
}
|
|
|
|
sub hangup_callback {
|
|
print_log "asterisk: hangup callback\n";
|
|
}
|
|
|
|
sub default_callback {
|
|
my (%data) = @_;
|
|
foreach (keys %data) {
|
|
print_log ("asterisk callback: $_: ". $data{$_}) if $Debug{asterisk};
|
|
}
|
|
}
|
|
|
|
# Inform the humans that the phone system is down
|
|
sub asterisk_down {
|
|
return if (state $mode_occupied eq 'vacation');
|
|
print_log ("asterisk: asterisk_down");
|
|
$Save{voiceMail} = 0;
|
|
speak (rooms=> "all", text=> "Danger will robinson ... the telephone system appears broken");
|
|
}
|
|
|
|
# Connect to the Asterisk Manager interface
|
|
sub asterisk_connect {
|
|
print_log "asterisk_connect::" if $Debug{asterisk};
|
|
my $connect = $astman->connected;
|
|
return if ($astman->connected);
|
|
$astman->host($config_parms{asterisk_manager_host});
|
|
$astman->user($config_parms{asterisk_manager_username});
|
|
$astman->port($config_parms{asterisk_manager_port});
|
|
$astman->secret($config_parms{asterisk_manager_password});
|
|
&asterisk_down if (!$astman->connect);
|
|
$astman->setcallback('Hangup', \&hangup_callback);
|
|
$astman->setcallback('DEFAULT', \&default_callback);
|
|
}
|
|
|
|
sub asterisk_disconnect {
|
|
$astman->disconnect;
|
|
print_log "asterisk_disconnect::" if $Debug{asterisk};
|
|
}
|
|
|
|
# Query Asterisk for Unregistered IAX2 connections
|
|
sub check_iax2 {
|
|
my $teliax_active = 0;
|
|
&asterisk_connect;
|
|
my (@data) = $astman->sendcommand( 'Action' => 'Command', 'Command' => "iax2 show registry", 2, 2);
|
|
foreach (@data) {
|
|
$_ =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/;
|
|
my $host = $1;
|
|
my $dnsmgr = $2;
|
|
my $username = $3;
|
|
my $client = $4;
|
|
my $refresh = $5;
|
|
my $state = $6;
|
|
if (($username eq 'jduda') && ($state eq 'Registered')) {
|
|
$teliax_active = 1;
|
|
}
|
|
print_log "asterisk iax2: $host $dnsmgr $username $client $refresh $state" if $Debug{asterisk};
|
|
}
|
|
&asterisk_down if (!$teliax_active);
|
|
&asterisk_disconnect;
|
|
}
|
|
|
|
# Query Asterisk for Unregistered IAX2 connections
|
|
sub check_sip {
|
|
my $teliax_active = 0;
|
|
&asterisk_connect;
|
|
my (@data) = $astman->sendcommand( 'Action' => 'Command', 'Command' => "sip show registry", 2, 2);
|
|
foreach (@data) {
|
|
$_ =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/;
|
|
my $host = $1;
|
|
my $username = $2;
|
|
my $refresh = $3;
|
|
my $state = $4;
|
|
if (($username eq 'jduda') && ($state eq 'Registered')) {
|
|
$teliax_active = 1;
|
|
}
|
|
print_log "asterisk sip: $host $username $refresh $state" if $Debug{asterisk};
|
|
}
|
|
&asterisk_down if (!$teliax_active);
|
|
&asterisk_disconnect;
|
|
}
|
|
|
|
# Query Asterisk for New Voice Mail Messages
|
|
sub check_voice_mail {
|
|
&asterisk_connect;
|
|
my (%data) = $astman->sendcommand('Action' => "MailboxCount", 'Mailbox' => $config_parms{asterisk_voicemail_box});
|
|
foreach (keys %data) {
|
|
print_log "asterisk vm: $_: ". $data{$_} if $Debug{asterisk};
|
|
if ($_ =~ /NewMessages/) {
|
|
$Save{voiceMail} = $data{$_};
|
|
}
|
|
}
|
|
&asterisk_disconnect;
|
|
}
|
|
|
|
# Check for New VoiceMail using a Voice Command
|
|
$v_voice_mail = new Voice_Cmd("any voice mail");
|
|
if (my $state = said $v_voice_mail) {
|
|
&check_voice_mail;
|
|
if ($Save{voiceMail}) {
|
|
my $message = "messages";
|
|
if ($Save{voiceMail} == 1) {
|
|
$message = "message";
|
|
}
|
|
speak (rooms=> "all", text=> "You have $Save{voiceMail} voice mail $message waiting");
|
|
} else {
|
|
speak (rooms=> "all", text=> "no voice mail messages");
|
|
}
|
|
}
|
|
|
|
# Periodically check for New VoiceMail and IAX2 connections
|
|
if ($New_Minute) {
|
|
if ($config_parms{asterisk_voicemail_period} && !($Minute % $config_parms{asterisk_voicemail_period})) {
|
|
&check_voice_mail;
|
|
if ($Save{voiceMail} && (state $mode_occupied ne 'vacation')) {
|
|
run_voice_cmd "any voice mail";
|
|
}
|
|
}
|
|
# &check_iax2 if ( !($Minute % 5) );
|
|
&check_sip if ( !($Minute % 5) );
|
|
}
|
|
|
|
|
|
$v_call_phone = new Voice_Cmd("call [shelia,shelia cell,meghan cell,meghan]");
|
|
if (my $state = said $v_call_phone) {
|
|
&asterisk_connect;
|
|
my $number = "";
|
|
if ($state eq 'shelia') {
|
|
$number = "7818850102";
|
|
} elsif ($state eq 'shelia cell') {
|
|
$number = "7147851962";
|
|
} elsif ($state eq 'meghan cell') {
|
|
$number = "8438227696";
|
|
} elsif ($state eq 'meghan') {
|
|
$number = "7013642900";
|
|
}
|
|
my (%data) = $astman->sendcommand( Action => "Originate",
|
|
Channel => "SIP/101",
|
|
Context => "internal",
|
|
Exten => $number,
|
|
Priority => "1",
|
|
Timeout => "30000"
|
|
);
|
|
foreach (keys %data) {
|
|
print_log "asterisk vm: $_: ". $data{$_} if $Debug{asterisk};
|
|
}
|
|
&asterisk_disconnect;
|
|
}
|
|
|
|
#Action: Originate
|
|
#Channel: SIP/101
|
|
#Context: home
|
|
#Exten: 5406050674
|
|
#Priority: 1
|
|
#Callerid: 7817361994
|
|
#Timeout: 30000
|
|
#Variable: var1=23|var2=24|var3=25
|
|
#ActionID: ABC45678901234567890
|
|
|
|
sub audrey_callerid {
|
|
my ($name, $number) = @_;
|
|
print_log "audrey_callerid: $name $number";
|
|
my $file = "$Pgm_Root/web/misc/callerid.shtml";
|
|
open (DATA, ">$file") || print_log "Couldn't open file $file, $!";
|
|
print DATA "<html><head><title>CALLERID</title>";
|
|
print DATA "<h1>CALLERID</h1><br />";
|
|
print DATA "<h2>$name</h2><br />";
|
|
print DATA "<h2>$number</h2><br />";
|
|
print DATA "</html>";
|
|
close DATA;
|
|
run_voice_cmd "Set all Audrey screen on";
|
|
run_voice_cmd "Set all Audrey to callerid screen";
|
|
set $t_audrey_callerid 60 * 3;
|
|
}
|
|
|
|
$t_audrey_callerid = new Timer;
|
|
if (expired $t_audrey_callerid) {
|
|
run_voice_cmd "Set all Audrey to main screen";
|
|
run_after_delay 5, sub {
|
|
run_voice_cmd "Set all Audrey screen off";
|
|
}
|
|
}
|
|
|
|
|