Dynamic Phone/Channel Control

We are looking to convert our phone simulation testing tools from
a very good tool which we can nolonger use because of contractual
requirements. I appologize in advance for the length of this post, but
the whole story is very important to us. Thanks for your attention.

Asterisk appears to be suited to our requirements. We were hoping
that we migh get some help / pointers to that goal.

Our current system consists of Perl code which encapsulates the actual
phone simulation/control program, connecting to this program via
sockets (telnet). Our system facilitates migration of tests between systems
with different users / phones.

The primary setup input for phone simulation is a comma-separated-value
(CSV) file specifying users, phones, and registrar systems.
Example:
userDN,deviceDN,registrar,regPort,userPort,iceType,userName,password,noAns
,
27001,25001,ao8-ed.inse.lucent.com,5260,5060,ICM,icm27001,,0
27002,25002,ao8-ed.inse.lucent.com,5260,5060,ICM,icm27002,
,0
46001,46001,ao2-oxe.inse.lucent.com,5060,5060,OXE,oxe46001,,0
46002,46002,ao2-oxe.inse.lucent.com,5060,5060,OXE,oxe46002,
,0

Program execution follows

  1. CSV file is read along with any other options
  2. Appropriate phone simulator configuration file(s) are generated
  3. Zero (if simulator is already executing) or more instances
    of the phone simulator are started with telnet connections to each
  4. Continuing throughout the test run, our controlling wrapper code
    A. Converts user requests associated with actions such as
    a. userX with phone N1, calls phone N2
    b. userY sends DTMF on phone N3
    c. userZ examines most recent DTMF arriving on phone N4
    B. Sends associated requests to appropriate phone simulator
    instance
    C. Routes the corresponding sinulator responses
    back to the initiating user

What we would like to do is modify our wrapper code to do the same
using Asterisk or some similar phone simulation vehicle.

Our progress:

  1. We have demonstrated, to ourselves, that phone registration as well
    as simple default activity such as “answer call” can
    be accomplished via generation of proper entries in sip.conf,
    extensions.conf files. See Partial excerpts from conf files below
    at end.

Still to be understood:

  1. Best way to program dynamic phone control
    We simulate 1000s of users 1000s of phones of which any 100s to 1000s
    of phones may be calling, called, sending DTMF, etc. at any time.
    Note that we often do not know in advance which phones will be involved
    with what activity, so often the phone, from our intial list, will
    call another phone and do some activity. The AMI (Asterisk Management
    Interface) looks promising. If that would work, I would appreciate a
    pointer or example on how one might implement functions such as:
    A. phone(from=>N1, to=>N2) where N1 and N2 are phone numbers from
    some possibly large group.
    B. sendDTMF(from=>N1, string=>S1) where N1 is the phone number of
    the phnoe called in A, and S1 is a string of DTMF characters.
    C. hangup(phone=>N1) where N1 is a phone currently active.
    D. isOffhook(phone=>N1) where N1 is a phone whose state is desiered.
    These are functions our wrapper supports and would have to be implemented
    by any simulator replacement. Our current hope is Asterisk will fit
    the bill.

How do we best simulate that type of activity? Re-writing
sip.conf,extensions.conf files on the fly and the reloads, while
possible looks rather slow.

  1. MS Windows support
    Some of our testing is done in a Microsoft Windows envirionment. It
    would be nice if we could execute there too. One possibility, we’ve
    considered, would be to require testing have a Linux box available
    which could host the simulation effort and be controled via socket.

  2. Is there anyway to reliably automate the instalation of asterisk.
    Some of our users will be a bit reluctant if they have to install
    something of the order of asterisk.

Partial excerpts from conf files:

sip.conf:
; ICM ao8-ed.inse.lucent.com (152.148.200.152)
register=>25001:xxxxxxx@152.148.200.152:5260/9999
register=>25002:xxxxxxx@152.148.200.152:5260/9999

; OXE ao8-ed.inse.lucent.com (152.148.200.152)
; oxe ao2-oxe.inse.lucent.com (152.148.200.242)
register=>46001:sippassword@152.148.200.242:5060/9998
register=>46002:sippassword@152.148.200.242:5060/9998

;
; ICM phone support
;
[9999]
type=friend
host=152.148.200.152 ; ao8-ed.inse.lucent.com
allow=all

;
; OXE phone support
;
[9998]
type=friend
host=152.148.200.242 ; ao2-oxe.inse.lucent.com
allow=all

extensions.conf:
[icm]
exten=>25001,1,Verbose(1,AMDS_authomation_recive_message)
same => n,Answer()
same => n,Wait(9)
same => n,SendDTMF(1)
same => n,Wait(99999)
same => n,Hangup()
exten=>25002,1,Verbose(1,AMDS_authomation_recive_message)
same => n,Answer()
same => n,Wait(9)
same => n,SendDTMF(1)
same => n,Wait(99999)
same => n,Hangup()

So far we have learned…
The following have been useful:
Perl Asterisk::AMI for control
Perl Asterisk::config for conf file manipulation

Cut from sip.conf:
;
; ICM
;
register=>62021:password@192.168.90.50:5260
register=>62022:password@192.168.90.50:5260
register=>62023:password@192.168.90.50:5260
register=>62024:password@192.168.90.50:5260
register=>62025:password@192.168.90.50:5260
;
; OXE
;
register=>51206:password@152.148.200.236:5060
register=>51207:password@152.148.200.236:5060
register=>51208:password@152.148.200.236:5060
register=>51209:password@152.148.200.236:5060
register=>51210:password@152.148.200.236:5060

Cut from extensions.conf:
[public]

include=>SRC
include=>DST
include=>ICM_CALL
include=>ICM_CALL_DST

[ICM_CALL]

	exten => _X.,1,Verbose(1, ICM_CALL ${CONTEXT} extent: ${EXTEN} channel: ${CHANNEL})
	same => n,1,Verbose(1,${CONTEXT} ${EXTEN} on ${CHANNEL} RegPort=${RegPort})
	same => n,Verbose(1, FromPhone=${FromPhone} ToPhone=${ToPhone} Registrar=${Registrar})
	same => n,Wait(1)
	same => n,NoOp("Output ext:${EXTEN} on ch: ${CHANNEL}")
	same => n,Dial(SIP/${FromPhone}@${Registrar}:${RegPort},20,rt)
	same => n,Wait(1)
	same => n,Dial(SIP/${ToPhone}@${Registrar}:${RegPort},20,rt)
	same => n,Wait(99999)
	same => n,Hangup()

[ICM_CALL_DST]

exten => _X.,1,Verbose(1, ICM_CALL_DST ${CONTEXT} extent: ${EXTEN} channel: ${CHANNEL})
same => n,Answer()
same => n,Read(d02,,1,,,99999)
same => n,SayNumber(${d02})
same => n,Read(d02,,,,,99999)
same => n,SayNumber(${d01})
same => n,Read(d02,,,,,99999)
same => n,Wait(99999)
same => n,Hangup()                           

Originate call (Perl source code cut) to give our style:
# Hack because Originate Variable
# does not appear to work
$registrarip = ‘127.0.0.1’; # Hack - still working out the SIP
$regPort = ‘5060’;
$self->asteriskSetGlobal(REGISTRAR => $registrarip)
or return $FALSE;
$self->asteriskSetGlobal(FROMPHONE => $deviceDN)
or return $FALSE;
$self->asteriskSetGlobal(TOPHONE => $call_devNum)
or return $FALSE;
$self->asteriskSetGlobal(RegPort => $regPort)
or return $FALSE;

my %acmd = (
    Action => 'Originate',
    Channel => "SIP/$deviceDN\@$registrarip:$regPort",
    Context => $context,
    Exten => $call_devNum,
    Priority => 1,
    Callerid => $callid,
    Timeout => $timeout * 1000,     # In msec

Variable => “from_phone=$phoneNumber|to_phone=$call_num|registrar=$registrar”,

Ignored??? ActionID => $actionId,

Async => 1, # Asynchronized actions

);
my $r_res = $self->asteriskCmd(\%acmd, %opth);
if (!defined($r_res)) {
    $self->report("Undefined asterisk call return: call_num=$call_num\n")
}
if (!$r_res->{'GOOD'}) {
    $self->report("Error Call($call_num): " . $r_res->{'Message'} . "\n");
    return $FALSE;
}

Findings:
Still have problems with total understanding of dialplan execution.
Still haven’t gotten DTMF reading to work.