[Asterisk-Users] Re: Asterisk Question

Michael Collins mcollins at fcnetwork.biz
Wed Mar 1 12:21:36 MST 2006


> Thanks for this example - it has really got me started!
> 

Paul, 
I did some tinkering and I think I found something that might be
helpful.  If not, I did at least learn quite a bit about AGI scripting
and dialplan writing! :)

Okay, first I created a pretend file with numbers: /tmp/numbers.txt
It is simply a list of numbers from 001 to 020, like so:
001
002
003
...
019
020

Since you have to check the file in reverse order, I have the AGI script
read in the values, assign them to an array, @NUMS, then I perform a
"reverse" on @NUMS:
@NUMS = reverse @NUMS;

Now "020" is the first value in the array, or $NUMS[0].
"019" is the second value, or $NUMS[1].

If the number of previous messages that have been read (which I put in
the dialplan variable NUM_MSGS_READ) is 0, then the "next" number is
referenced by grabbing $NUMS[0].  If the number of previous messages
that have been read is 1, then the "next" number is referenced by
grabbing $NUMS[1], and so on.

I created two different dialplan extensions so I could tinker.  The
first one hard codes the value of NUM_MSGS_READ to 3.  Thus the return
value of NEXT_NUM is $NUMS[3], which is 017.  The second one lets the
caller enter in the value for NEXT_NUM, which is good for testing
purposes.  I tried to add some validation logic to handle exceptions.  I
didn't test it thoroughly but hopefully it illustrates the point.

Here are the dialplan extensions:

; AGI test2.1
; hard coded NUM_MSGS_READ
;
exten => 555,1,Noop(Starting AGI test)
exten => 555,n,Answer
exten => 555,n,Wait(1)
exten => 555,n,SetVar(NUM_MSGS_READ=3)
exten => 555,n,Playback(beep)
exten => 555,n,AGI(agi_var_test2.pl)
exten => 555,n,GotoIf($[${NEXT_NUM:1} = INVALID ]?invalid:ok)
exten => 555,n(ok),SayDigits(${NEXT_NUM})
exten => 555,n,Wait(1)
exten => 555,n,Playback(beep)
exten => 555,n,Hangup
exten => 555,n(invalid),Playback(invalid)
exten => 555,n,Hangup

; AGI test2.2
; For kicks, let the caller set the value of NUM_MSGS_READ
;
exten => 556,1,Noop(Starting AGI test)
exten => 556,n,Answer
;exten => 556,n,SetVar(NUM_MSGS_READ=X)
exten => 556,n,Wait(1)
exten => 556,n,Playback(please-enter-the)
exten => 556,n,Playback(digits)
exten => 556,n,Read(NUM_MSGS_READ,,2,,,10)
exten => 556,n,Playback(beep)
exten => 556,n,AGI(agi_var_test2.pl)
exten => 556,n,GotoIf($[${NEXT_NUM:1} = INVALID ]?invalid:ok)
exten => 556,n(ok),SayDigits(${NEXT_NUM})
exten => 556,n,Wait(1)
exten => 556,n,Playback(beep)
exten => 556,n,Hangup
exten => 556,n(invalid),Playback(invalid)
exten => 556,n,Hangup
exten => 556,t,Playback(vm-goodbye)
exten => 556,t,Hangup


The Read() application in exten 556 is configured to accept up to two
digits with a 10 second digit timeout.  On a timeout it plays a goodbye
message.  In both extensions, there is a test to make sure that NEXT_NUM
doesn't contain the string "INVALID" - if it does then we go to a
priority and voice that to the caller.  The AGI script will return
"1INVALID" or "2INVALID" depending upon why the script failed.  See the
notes in the code for details.

Here's the AGI script, agi_var_test2.pl:

#!/usr/bin/perl
#
# agi_var_test2.pl
#
# Reads in info from file /tmp/numbers.txt into array @NUMS
# Uses Asterisk var NUM_MSGS_READ to count from end of @NUMS
# Assigns appropriate value from @NUMS to Asterisk var NEXT_NUM
#
use strict;
use warnings;
use Asterisk::AGI;

# the AGI object
my $agi = new Asterisk::AGI;

# pull AGI variables into %input
my %input = $agi->ReadParse();

my @NUMS = ();     # Array to hold data from file
my $number;        # Value to be sent back to Asterisk

my $infile = '/tmp/numbers.txt';
open(FILEIN,"<",$infile) or die "$infile - $!\n";
while(<FILEIN>) {
    chomp;

    # Perform some data validation, just to be safe
    s/^\s|\s+$|^\s+$//;    # remove whitespace, just in case
    next unless length;    # skip if nothing left...
    next unless m/^\d+$/;  # skip if line contains any non-digits
    push @NUMS,$_;
} # while(<FILEIN>)
close(FILEIN);

# reverse array to make it easier to find our value
# e.g. last line of file becomes first item in @NUMS:
# $NUMS[0] = last item of file
# $NUMS[1] = next to last item of file, etc.

@NUMS = reverse @NUMS;

my $arraypos = $agi->get_variable('NUM_MSGS_READ');
if ( ! $arraypos ) {
    # if we get to this point, something is wrong...
    $agi->set_variable('NEXT_NUM','1INVALID');
    exit(1);    # 1INVALID = AGI script could not read NUM_MSGS_READ
}

# since @NUMS is zero based, $arraypos = next unread number
$number = $NUMS[$arraypos];
if ( $number ) {
    $agi->set_variable('NEXT_NUM',$number);
    exit(0);    # Normal exit!
} else {
    $agi->set_variable('NEXT_NUM','2INVALID');
    exit(1);    # 2INVALID = NUM_MSGS_READ larger than number of items
in @NUMS
}


Okay, that's all I've got for now.  Let us know how it goes!

-MC



More information about the asterisk-users mailing list