# 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";
  }
}


