|
|
Version Date: 6/15/00
This document contains information about the Tool Command Language (TCL) Interactive Voice Response (IVR) application programming interface (API) Version 1.0 commands that you can use to write TCL scripts to interact with the Cisco IVR feature. It provides an annotated example of a TCL IVR script and includes instructions for testing and loading a TCL IVR script.
This document helps developers writing voice application software for Cisco voice interfaces, such as the Cisco AS5x00 series. This includes independent software vendors (ISVs), in-house corporate developers, system integrators, and Original Equipment Manufacturers (OEMs).
This document includes the following sections:
IVR is a term that is used to describe systems that provide information in the form of recorded messages over telephone lines in response to user input in the form of spoken words, or more commonly dual tone multifrequency (DTMF) signaling. For example, when a user makes a call with a debit card, an IVR application is used to prompt the caller to enter a specific type of information, such as a PIN. After playing the voice prompt, the IVR application collects the predetermined number of touch tones (digit collection), forwards the collected digits to a server for storage and retrieval, and then places the call to the destination phone or system. Call records can be kept and a variety of accounting functions performed.
The IVR application (or script) is a voice application designed to handle calls on a voice gateway, which is a router that is equipped with Voice over IP (VoIP) features and capabilities.
The prompts used in an IVR script can be either static or dynamic. With static prompts, the prompt message is pre-recorded in its entirety and played as a single unit. With dynamic prompts, the prompt message is pre-recorded in pieces and the pieces are assembled dynamically during play. For example, dynamic prompts are used to inform the caller of how much time is left in their debit account, such as:
"You have 15 minutes and 32 seconds of call time left in your account."
The above prompt is created using eight individual prompt files. They are: youhave.au, 15.au, minutes.au, and.au, 30.au, 2.au, seconds.au, and leftinyouraccount.au. These audio files are assembled dynamically by the underlying system and played as a prompt based on the selected language and prompt file locations.
The Cisco IVR (Interactive Voice Response) feature, available in Cisco IOS Release 12.0(6)T and later, provides IVR capabilities using TCL 1.0 scripts. These scripts are signature locked, and can be only modified by Cisco. The IVR feature allows IVR scripts to be used during call processing. The scripts interact with the IOS software to perform various call-related functions. Starting with release 12.1(3), the TCL script lock will be removed, thus allowing customers to create and change their own TCL scripts.
TCL is an interpreted scripting language. Because TCL is an interpreted language, scripts written in TCL do not have to be compiled before they are executed. TCL provides a fundamental command set, which allows for standard functions such as flow control (if, then, else) and variable management. By design, this command set can be expanded by adding "extensions" to the language to perform specific operations.
Cisco has created a set of extensions, called TCL IVR commands, that allows users to create IVR scripts using TCL. Unlike other TCL scripts, which are invoked from a shell, TCL IVR scripts are invoked when a call comes into the gateway.
The remainder of this document assumes that you are familiar with TCL and how to create scripts using TCL.If you are not, we recommend that you read TCL and the TK Toolkit by John Ousterhout (published by Addison Wesley Longman, Inc).
Cisco plans to develop a new TCL script format (TCL 2.0) that will address scalability and performance issues.
The Open TCL IVR feature is currently supported on the Cisco AS5300 voice platform only. In order to use the open TCL IVR feature you need the following:
1. Cisco AS5300 (Voice platform) universal access server
2. Cisco IOS Release 12.1(3) or later.
3. TCL version 7.1 or later.
Calls can come into a gateway using analog lines, ISDN lines, a VoIP link, or a VoFR link. TCL IVR scripts can provide full functionality for calls received over analog or ISDN lines. The functionality provided for calls received over VoIP or Voice over Frame Relay (VoFR) links varies depending on the release of Cisco IOS software being used. For example, if you are using Cisco IOS Release 12.0, you cannot play prompts or tones, and you cannot collect tones.
Developers using this guide may be interested in joining the Cisco Developer Support Program. This new program has been developed to provide you a consistent level of support that you can depend on while leveraging Cisco interfaces in your development projects.
A signed Developer Support Agreement is required to participate in this program. For more details, and access to this agreement, please visit us at: http://www.cisco.com/warp/public/779/servpro/programs/ecosystem/devsup, or contact developer-support@cisco.com
This section of the document includes information on how to create and use TCL IVR scripts. This section includes the following topics:
Before you write an IVR script using TCL, you should familiarize yourself with the TCL extensions for IVR scripts.
You can use any text editor to create your TCL IVR script. Follow the standard conventions for creating a TCL script and incorporate the TCL IVR commands as necessary.
A sample script is provided in this section to illustrate how the TCL IVR commands can be used.
Certain standard TCL commands can be used in TCL IVR scripts. These commands are as follows:
append | array | break | case |
catch | concat | continue | error |
eval | expr | for | foreach |
format | global | history | if |
incr | info | join | lappend |
lindex | linsert | list | llength |
lrange | lreplace | lsearch | lsort |
proc | puts | regexp | regsub |
rename | return | set | split |
string | switch | tcl_trace | unset |
uplevel | upvar | while |
|
For additional information about the standard TCL commands, see the TCL and the TK Toolkit by John Ousterhout (published by Addison Wesley Longman, Inc).
In addition to the standard TCL commands, you can use the TCL extensions for IVR scripts that Cisco has created. Also, Cisco modified two of the existing TCL commands, puts and exit, to perform specific tasks. The TCL IVR commands are as follows:
| Command | Description |
acceptCall | Sends setup acknowledgement, call proceeding, and call connect messages to the incoming call leg. |
ani | Returns the originating number, which is supplied by the incoming call leg. |
authenticate | Sends an authentication request to an external system, typically a Remote Access Dial- In User Services (RADIUS) server. |
authorize | Sends an authorization request to an external system, typically a RADIUS server. |
callID | Returns the call ID used in the Cisco IOS debug messages. |
callProceeding | Sends a call proceeding message to the incoming call leg. |
clearOutgoingLeg | Deletes a conference and disconnects the outgoing call leg. |
conferenceCreate | Creates a conference between two call legs. |
conferenceDelete | Deletes a conference between two call legs. |
creditTimeLeft | Returns the credit time available for this call. |
did | Determines whether the incoming dial peer is configured for dial-in direct (DID) operation. |
dnis | Returns the destination number. |
exit | Exits the script, clears the call leg, and cleans up the data structures. |
failureCode | Returns the last failure event and code. |
getVariable | Returns the value of a specified variable. |
insertMessage | Inserts a message to the originating (calling) party. |
insertTone | Inserts a beep to the originating (calling) party. |
placeCall | Places a call to the specified destination. |
playFailureTone | Plays one of two tones depending on the last failure event. |
playPrompt | Plays a prompt to the incoming call leg. Designed for use with dynamic prompts. |
playTone | Plays a call progress tone. |
promptAndCollect | Plays a prompt to the originating (calling) party and collects digits in a specified pattern. |
puts | Outputs a debug string to the console if the IVR state debug flag is set. |
rdn | Returns the redirect number that came with the call. |
setLocation | Sets the location of the audio files. |
setTimeout | Sets the initial digit collection timeout and the inter-digit collection timeout values. |
setVariable | Sets the value of a specified variable. |
setupAck | Sends a call setup acknowledgement back to the incoming call leg. |
startTimer | Causes the script to block until a specified number of seconds passes or an event (such as a destination hang up or an origination hang up) occurs. |
waitEvent | Causes the script to pause until an event occurs. |
For more information about these commands, see the "TCL IVR Command Reference" .
The following annotated example illustrates how the TCL IVR commands can be used.
We start with the header information, which includes the name of the script, the date the script was created and by whom, and some general information about what the script does.
It is also a good idea to include a version number for the script. We recommend that you use a three digit system where the first digit indicates a major version of the script, the second digit should be incremented with each minor revisions (such as a change in function within the script), and the third number should be incremented each time other changes are made to the script.
# Script Loaded by: Dram # Script Version 1.0.1 # Script LookDate: Sept. 30 20:58:49 1999 #------------------------------------------------------------------ # September 1998, David Ramsthaler # # Copyright (c) 1998, 1999, 2000 by cisco Systems, Inc. # All rights reserved. #------------------------------------------------------------------ # # This script authenticates using (ani, dnis) for (account, password). If # that fails, it collects account and pin number, then authenticates # using (account, pin). # # If authentication passes, it collects the destination number and # places the call. #
Next, we define a series of procedures.
The get_account procedure defines the parameters of the account prompt and collects the account information. In this procedure:
proc do_get_account {} {
global state
global account
set prompt(url) flash:enter_account.au
set prompt(interrupt) true
set prompt(abortKey) *
set prompt(terminationKey) #
set patterns(account) .+
set event [promptAndCollect prompt info patterns ]
if {$event == "collect success"} {
set state get_pin
set account $info(digits)
return 0
}
if {$event == "collect aborted"} {
set state get_account
return 0
}
if {$event == "collect fail"} {
set state get_account
return 0
}
set state end
return 0
}
The get_pin procedure defines the parameters of the PIN prompt and collects the PIN. In this procedure:
proc do_get_pin {} {
global state
global pin
set prompt(url) flash:enter_pin.au
set prompt(interrupt) true
set prompt(abortKey) *
set prompt(terminationKey) #
set patterns(account) .+
set event [promptAndCollect prompt ReturnInfo patterns ]
if {$event == "collect success"} {
set state authenticate
set pin $info(digits)
return 0
}
if {$event == "collect aborted"} {
set state get_account
return 0
}
if {$event == "collect fail"} {
# timeout
if {$info(code) == 102} {
set state get_pin
return 0
}
# invalid number
if {$info(code) == 28} {
set state get_pin
return 0
}
}
set state end
return 0
}
The authenticate procedure passes the information collected to a RADIUS server for authentication and waits for a reply. In this procedure:
proc do_authenticate {} {
global state
global pin
global account
set event [authenticate $account $pin info]
if { $event == "authenticated" } {
set state authen_pass
return 0
}
if {$event == "authentication failed"} {
set state authen_fail
return 0
}
set state end
return 0
}
The get_dest procedure defines the parameters of the destination prompt and collects the destination phone number. In this procedure:
proc do_get_dest {} {
global state
global destination
set prompt(url) flash:enter_destination.au
set prompt(interrupt) true
set prompt(abortKey) *
set prompt(terminationKey) #
set prompt(dialPlan) true
set event [promptAndCollect prompt info ]
if {$event == "collect success"} {
set state place_call
set destination $info(digits)
return 0
}
if {$event == "collect aborted"} {
set state get_dest
return 0
}
if {$event == "collect fail"} {
set state get_dest
return 0
}
set state end
return 0
}
The authen_pass procedure determines whether the destination phone number has been provided. In this procedure:
proc do_authen_pass {} {
global state
global destination
set dnislen [string len [dnis]]
if { [did] && $dnislen } {
set destination [dnis]
set state place_call
} else {
set state get_dest
}
return 0
}
The place_call procedure places the call to the specified destination. In this procedure:
proc do_place_call {} {
global state
global destination
set event [placeCall $destination callInfo info]
if {$event == "active"} {
set state active
return 0
}
if {$event == "call fail"} {
set state place_fail
return 0
}
set state end
return 0
}
The active_notimer procedure specifies that no time limit is set on the call. The script waits idly for an event.
proc do_active_notimer {} {
global state
set event [waitEvent]
while { $event == "digit" } {
set event [waitEvent]
}
set state end
return 0
}
The active_last_timer procedure monitors the last few seconds of time allowed for the call to ensure that the user does not exceed their allotted credit time. In this procedure:
proc do_active_last_timer {} {
global state
set event [startTimer [creditTimeLeft] info]
while { $event == "digit" } {
set event [startTimer $info(timeLeft) info]
}
if { $event == "timeout" } {
clearOutgoingLeg returnInfo
set state out_of_time
} else {
set state end
}
return 0
}
The active_timer procedure monitors the amount of time used during the call to ensure that the user does not go past their allotted credit time. In this procedure:
proc do_active_timer {} {
global state
if { [creditTimeLeft] < 10 } {
do_active_last_timer
return 0
}
set delay [expr [creditTimeLeft] - 10]
set event [startTimer $delay info]
while { $event == "digit" } {
set event [startTimer $info(timeLeft) info]
}
if { $event == "timeout" } {
insertMessage flash:beep.au returnInfo
do_active_last_timer
} else {
set state end
}
return 0
}
The active procedure determines whether there is a time limit on the call. In this procedure:
proc do_active {} {
global state
if { ( [creditTimeLeft] == "unlimited") ||
([creditTimeLeft] == "uninitialized") } {
do_active_notimer
} else {
do_active_timer
}
return 0
}
The out_of_time procedure plays a message (out_of_time.au) if the user is out of time.
proc do_out_of_time {} {
global state
set prompt(url) flash:out_of_time.au
set prompt(playComplete) true
set event [promptAndCollect prompt info ]
set state end
return 0
}
The authen_fail procedure plays a message (auth_failed.au) if the information that the user provided is not authenticated by the RADIUS server.
proc do_authen_fail {} {
global state
set prompt(url) flash:auth_failed.au
set prompt(playComplete) true
set event [promptAndCollect prompt info ]
set state end
return 0
}
The place_fail procedure plays a tone if the call cannot be placed.
proc do_place_fail {} {
global state
playFailureTone 5 returnInfo
set state end
return 0
}
Finally, we put all the procedures together in a main routine. The main routine passes the origination and destination phone numbers (if available) to the RADIUS server for authentication. If the response from the RADIUS server is "authenticated," the authen_pass procedure is called.
If the response from the RADIUS server is anything other than "authenticated," the get_account procedure is called.
From there, the main routine reads the state as set by each procedure to determine which procedure to call next.
#-------------------------------------------------------
# The main routine begins here.
#
acceptCall
set event [authenticate [ani] [dnis] info]
if {$event != "authenticated"} {
set state get_account
} else {
set state authen_pass
}
while {$state != "end"} {
if {[info proc do_$state] == do_$state}
do_$state
}
It's important to thoroughly test a script before it is deployed.
To test a script, you must place it on a router and place a call to activate the script. When you test your script, make sure that you test every procedure in the script and all variations within each procedure. Errors that occur in parts of the script that are not tested will not be found. For example, if you have the following:
if {[dnis]=="1234"} {
promptAndcollect prompt info
The misspelling of the promptAndCollect command will not be detected until the number 1234 is dialed.
You can view debugging information applicable to the TCL IVR scripts that are running on the router. The debug voip ivr command allows you to specify the type of debug output you want to view. To view debug output, enter the following command in privileged Exec mode:
[no] debug voip ivr [states | error | script | dynamic| all]If you specify "error," output is displayed only if an error occurs in the script. If you specify "states," the output provides information about what is happening in an IVR application. If you specify "dynamic" this shows the dynamic prompt play information. If you specify "all," both error and states information is displayed.
The output of any TCL puts commands is displayed if script debugging is on.
Following are some of the errors that may appear and their causes:
| Error Message | Description |
|---|---|
wrong # args: should be "cmd... ..." | Script exits with error information due to the wrong number of arguments. |
bad args: should be "cmd... ..." | Script exit with error information due to incorrect argument(s). |
verb-name called in wrong state, ... other detail information... | Script exit with error information due to verb being called in the wrong state. |
verb-name ignored, ... other detail information | Command is ignored due to verb being called in the wrong state. |
To associate an application with your TCL IVR script and load the script, use the following command:
(config)#call application voice script_name url [parameter value]In this command:
In the following example, the application named "test" is associated with the TCL IVR script called newapp.tcl, which is located at tftp://keyer/debit_audio/.
(config)#call application voice test tftp://keyer/debit_audio/newapp.tcl
If you modify your script, you can reload it using only the script name as shown below:
(config)#call application voice load script_nameTo invoke your TCL IVR script to handle a call, you must associate the script with an inbound dial peer. To associate your script with an inbound dial peer, enter the following commands in configuration mode:
(config)#dial-peer voice number voipIn these commands:
For example, the following commands indicate that the application called "newapp" should be invoked for calls that come in from an IP network and are destine for the telephone number of 125.
(config)#dial-peer voice 3 voip (conf-dial-peer)#incoming called-number 125 (conf-dial-peer)#application test
For more information about inbound dial peers, see the Cisco IOS software documentation.
To view a list of the voice applications that are configured on the router, use the show call application voice command. A one-line summary of each application is displayed. The description includes the names of the audio files the script plays, the operation of the interrupt keys, what prompts are used, and the caller interaction.
#show call application voice [ [name] | [summary] ]In this command:
The following is an example of the output of the show call application voice command.
router#show call app voice clid_authen_collect
Idle call list has 0 calls on it.
Application clid_authen_collect
The script is compiled into the image
It has 0 calls active.
The TCL Script is:
------------------
# clid_authen_collect.tcl
#----------------------------------
# September 1998, David Ramsthaler
#
# Copyright (c) 1998, 1999 by cisco Systems, Inc.
# All rights reserved.
#----------------------------------
# Mimic the clid_authen_collect script in the SP1.0 release.
#
# It authenticates using (ani, dnis) for (account, password). If
# that fails, it collects account and pin number, then authenticates
# using (account, pin).
#
# If authentication passes, it collects the destination number and
# places the call.
#
# The main routine is at the bottom. Start reading the script there.
#
proc do_get_account {} {
global state
global account
set prompt(url) flash:enter_account.au
set prompt(interrupt) true
set prompt(abortKey) *
set prompt(terminationKey) #
set patterns(account) .+
set event [promptAndCollect prompt info patterns ]
if {$event == "collect success"} {
set state get_pin
set account $info(digits)
return 0
}
if {$event == "collect aborted"} {
set state get_account
return 0
}
if {$event == "collect fail"} {
set state get_account
return 0
}
set state end
return 0
}
proc do_get_pin {} {
global state
global pin
set prompt(url) flash:enter_pin.au
set prompt(interrupt) true
set prompt(abortKey) *
set prompt(terminationKey) #
set patterns(account) .+
set event [promptAndCollect prompt info patterns ]
if {$event == "collect success"} {
set state authenticate
set pin $info(digits)
return 0
}
if {$event == "collect aborted"} {
set state get_account
return 0
}
if {$event == "collect fail"} {
# timeout
if {$info(code) == 102} {
set state get_pin
return 0
}
# invalid number
if {$info(code) == 28} {
set state get_pin
return 0
}
}
set state end
return 0
}
proc do_authenticate {} {
global state
global pin
global account
set event [authenticate $account $pin info]
if { $event == "authenticated" } {
set state authen_pass
return 0
}
if {$event == "authentication failed"} {
set state authen_fail
return 0
}
set state end
return 0
}
proc do_get_dest {} {
global state
global destination
set prompt(url) flash:enter_destination.au
set prompt(interrupt) true
set prompt(abortKey) *
set prompt(terminationKey) #
set prompt(dialPlan) true
set event [promptAndCollect prompt info ]
if {$event == "collect success"} {
set state place_call
set destination $info(digits)
return 0
}
if {$event == "collect aborted"} {
set state get_dest
return 0
}
if {$event == "collect fail"} {
set state get_dest
return 0
}
set state end
return 0
}
proc do_authen_pass {} {
global state
global destination
set dnislen [string len [dnis]]
if { [did] && $dnislen } {
set destination [dnis]
set state place_call
} else {
set state get_dest
}
return 0
}
proc do_place_call {} {
global state
global destination
set event [placeCall $destination callInfo info]
if {$event == "active"} {
set state active
return 0
}
if {$event == "call fail"} {
set state place_fail
return 0
}
set state end
return 0
}
proc do_active_notimer {} {
global state
set event [waitEvent]
while { $event == "digit" } {
set event [waitEvent]
}
set state end
return 0
}
proc do_active_last_timer {} {
global state
set event [startTimer [creditTimeLeft] info]
while { $event == "digit" } {
set event [startTimer $info(timeLeft) info]
}
if { $event == "timeout" } {
clearOutgoingLeg retInfo
set state out_of_time
} else {
set state end
}
return 0
}
proc do_active_timer {} {
global state
if { [creditTimeLeft] < 10 } {
do_active_last_timer
return 0
}
set delay [expr [creditTimeLeft] - 10]
set event [startTimer $delay info]
while { $event == "digit" } {
set event [startTimer $info(timeLeft) info]
}
if { $event == "timeout" } {
insertMessage flash:beep.au retInfo
do_active_last_timer
} else {
set state end
}
return 0
}
proc do_active {} {
global state
if { ( [creditTimeLeft] == "unlimited") ||
([creditTimeLeft] == "uninitialized") } {
do_active_notimer
} else {
do_active_timer
}
return 0
}
proc do_out_of_time {} {
global state
set prompt(url) flash:out_of_time.au
set prompt(playComplete) true
set event [promptAndCollect prompt info ]
set state end
return 0
}
proc do_authen_fail {} {
global state
set prompt(url) flash:auth_failed.au
set prompt(playComplete) true
set event [promptAndCollect prompt info ]
set state end
return 0
}
proc do_place_fail {} {
global state
playFailureTone 5 retInfo
set state end
return 0
}
#---------------------------------------
# And here is the main loop
#
acceptCall
set event [authenticate [ani] [dnis] info]
if {$event != "authenticated"} {
set state get_account
} else {
set state authen_pass
}
while {$state != "end"} {
puts "cid([callID]) running state $state"
if {$state == "get_account"} {
do_get_account
} elseif {$state == "get_pin"} {
do_get_pin
} elseif {$state == "authenticate"} {
do_authenticate
} elseif {$state == "get_dest"} {
do_get_dest
} elseif {$state == "place_call"} {
do_place_call
} elseif {$state == "active"} {
do_active
} elseif {$state == "authen_fail" } {
do_authen_fail
} elseif {$state == "authen_pass" } {
do_authen_pass
} elseif {$state == "place_fail"} {
do_place_fail
} elseif {$state == "out_of_time"} {
do_out_of_time
} else {
break
}
}
With IVR scripts, you use URLs to call the script and to call the audio files that the script plays. The VoIP system uses IOS File System (IFS) to read the files, so any IFS supported URLs can be used, which includes TFTP, FTP, or a pointer to a device on the router.
The URL of the IVR script is a standard URL that points to the location of the script. Examples include:
URLs for audio files are different from those used to load IVR scripts. With URLs for audio files:
This section provides some answers to frequently asked questions about using TCL IVR scripts.
1. How do I get information from my RADIUS server to the TCL IVR script?
After you perform an authentication and authorization, you can use the getVariable command to obtain the credit amount, credit time, and cause codes maintained by the RADIUS server. See the "getVariable" .
2. How do I keep the network from charging for the incoming call if there is no answer?
Although gateways do not control the charges for each call, in most networks you are only charged for completed calls. Therefore, if the incoming network does not detect a completed call, you are not charged. The placeCall command accepts an incoming call only if it succeeds in placing the call. At that point the incoming network will detect the completed call and charges will begin to accrue.
Normally, if the script is going to play prompts and collect digits, it will need to accept the incoming call by running the acceptCall command. If the script does not accept the incoming call, there may be a relatively short timer on the incoming network.
3. What happens if my script encounters an error?
When an error is encountered in the script, the call is cleared with a cause of TEMPORARY_FAILURE (41). If the IVR application has already accepted the incoming call, the caller will hear silence. If the script has not accepted the incoming call, the caller might hear a fast busy signal.
If the script exits with an error and IVR debugging is on (as described in "Testing and Debugging Your Script" ), the location of the error in the script is displayed at the command line.
This section provides an alphabetical listing of the new TCL IVR commands. The following is provided for each command:
For information about how returns and events are defined in the code, see "Value Definitions" .
The acceptCall command is used at the beginning of the main routine in a TCL script. It sends setup acknowledgement, call proceeding, and call connect messages to the incoming call leg. The Gateway is responsible for translating these messages into the appropriate protocol messages (depending on the call leg) and sending them to the caller.
acceptCall
None
None
Non blocking
# Accept a call and then prompt redialer for a pattern acceptCall set prompt(url) flash:redialer_tone.au set prompt(interrupt) true set patterns(accountAndPW) \\*\\*.+#\\*\\*.+# set event [promptAndCollect prompt returnInfo patterns]
The ani command returns the call origination number, which it obtains from the incoming callInfo data structure.
ani
None
This command returns the origination number (as a decimal string) or a NULL string if the number is not available. The origination number is the number provided by the incoming call leg.
Non blocking
# Authenticate using origination number as the user account number set event [authenticate [ani] [dnis] info]
The authenticate command validates the authenticity of the user. This command sends the account number and password to the appropriate server for authentication and waits for a response. In many cases, ani is used as the account number and dnis (or a NULL value) is used as the password.
authenticate account password [av-send] returnInfo
The arguments of this command are:
This command returns the following:
Blocking
# Authenticate using origination number as the account number
set event [authenticate [ani] [dnis] info]
if {$event == "authentication failed"} {
puts authentication failed with code $info(code)
exit
}
set av-send(h323-credit-amount) 25.0
set av-send(h323-ivr-out,0) "payphone:true" set av-send(h323-ivr-out,1) "creditTime:3400"
The authorize command sends an AAA authorization request and waits for a response. Typically, this command is used to provide additional information to the RADIUS server (destination and origination numbers) after a user has been successfully authenticated. It sends the authorization request to the RADIUS server after the IVR application prompts the user to enter the destination number.
authorize account password destination ani [av-send] returnInfo
The arguments of this command are:
The account, password, and returnInfo arguments are the same as those specified in the authentication command. The destination is the destination, or called, number and the ani is the origination, or calling, number. The destination and ani fields are used to provide additional information to the external server.
This command returns the following:
Blocking
# authorize the call, and get the available credit time.
set event [authorize $account $pin $destination [ani] info]
if {$event == "authorized"} {
set num [getVariable aaa h323-credit-amount CreditAmount]
}
set av-send(h323-credit-amount) 25.0
set av-send(h323-ivr-out,0) "payphone:true" set av-send(h323-ivr-out,1) "creditTime:3400"
The callID command is used for debugging purposes only. It can be used in problem determination for a particular call. This command returns the call ID (which is used in the IOS debug messages) of the incoming or outgoing call leg. This call ID has no meaning outside the router that is handling the call.
callID [outgoing]
The argument of this command is:
This command returns an integer greater than zero, which represents the call ID of the incoming or outgoing call leg. If you specify outgoing and there is no outgoing call leg, zero is returned.
Non blocking
# Display the call IDs in a debug message puts "Incoming callID [callID] connected to outing callID [callID outgoing]"
Each call leg is assigned a call ID. The Cisco IOS software begins assigning call IDs at 1 when the system is rebooted. The call ID is increment for each call leg and will eventually wrap.
The callProceeding command sends a call proceeding message to the incoming call leg. The Gateway is responsible for translating this message into the appropriate protocol message (depending on the call leg) and sending them to the caller.
![]() | Caution The ISDN state machine actually connects the incoming call on a setup acknowledgement. |
callProceeding
None
None
Non blocking
# Send call proceeding while placing the call callProceeding # we have not accepted the call yet. placeCall will place the outbound # call, conference the two call legs, and accept the inbound call leg. # set callInfo(destinationNum) $destination set event [placeCall $destination callInfo info]
The clearOutgoingLeg command deletes the conference and disconnects the outgoing call leg.
clearOutgoingLeg returnInfo
The argument of this command is:
This command returns a "disconnect done outgoing" event, even if no outgoing call leg exists.
Blocking
# If time runs out, clear the outgoing call and play out of time message
if {$event == "timeout"} {
clearOutgoingLeg returnInfo
set prompt(url) flash:out_of_time.au
set event [promptAndCollect prompt info]
}
The command is ignored if the outgoing call is not connected.
The conferenceCreate command creates a conference between the call legs. This command ignores any digits entered by the caller.
conferenceCreate returnInfo
The argument of this command is:
This command returns a "conference created" event. If the called party hangs up during the conferenceCreate, an "outgoing disconnected" event is returned and the returnInfo(code) will indicate the cause.
Blocking
# Delete the conference, play a message, then recreate it
set event [conferenceDelete returnInfo]
if {$event!= "conference deleted"} {
exit 0
}
set prompt(url) message.au
promptAndCollect prompt info
set event [conferenceCreate returnInfo]
if {$event!= "conference created"} {
exit
}
If this command is invoked while a conference is already established, the command is ignored. If two call legs do not exist, the script returns an error code, which causes the underlying infrastructure to disconnect the call and clean up.
The conferenceDelete command deletes a conference between call legs. It ignores digits and will abort and return if it receives any event other than the expected one.
conferenceDelete returnInfo
The argument of this command is:
This command returns a "conference deleted" event, even if a conference does not exist. If the outgoing call leg disconnected, "outgoing disconnected" is returned.
Blocking
# Delete the conference, play a message, then recreate it
set event [conferenceDelete returnInfo]
if {$event != "conference deleted"} {
exit 0
}
set prompt(url) message.au
promptAndCollect prompt info
set event [conferenceCreate returnInfo]
if { $event != "conference created" } {
exit 0
}
If the destination party disconnects, the cause code is saved internally but is not returned with this command.
The creditTimeLeft command returns the amount of credit time available for this call.
creditTimeLeft [-settlement | -aaa]
The arguments of this command are:
If no argument is specified, the lesser of the two credit times is requested.
This command returns one of the following:
If no argument is specified, the lesser of the OSP and AAA values is returned. If the two values are an integer and "uninitialized", the integer is returned.
Non blocking
# wait for the credit time we have
set event [startTimer [creditTimeLeft] returnInfo]
while { $event == "digit" } {
set event [startTimer [creditTimeLeft] returnInfo]
}
The did command determines whether the incoming dial peer is configured for DID operation.
did
None
This command returns either a 0 (the dial peer is not configured for DID) or a 1 (the dial peer is configured for DID).
Non blocking
# If DID, just place the call
if {[did]} {
set destination [dnis]
} else {
# play a dial tone, and collect against the pattern
playTone Dial
set prompt(dialPlan) true
set event [promptAndCollect prompt returnInfo]
if {event != "collect success"} {
puts "Call [callID] got event $event collecting destination"
exit 0
}
set destination returnInfo(digits)
}
If there is no incoming call, the script will exit with error information.
The dnis command returns the destination phone number.
dnis
None
This command returns the destination number, if it was provided with the incoming call. If no destination number was provided with the incoming call, this command returns a null value.
Non blocking
# Authenticate using destination number as the user password set event [authenticate [ani] [dnis] info]
The exit command exits the script, and then clears the call and cleans up the data structures. You can use this command to set the cause code for a call.
exit [code]
The argument of this command is:
None
Non blocking
# set event [placeCall destination callInfo info]
if {$event != active} {
puts "Call [callID] got $event when placing call"
exit 0
}
If the inbound call leg is not yet connected, setting a cause code can change what the caller hears. It may be a busy signal, a fast busy signal, or silence.
The failureCode command returns the last failure event and code.
failureCode returnInfo
The argument of this command is:
The return value is the return event if the last failure event was "authentication failed", "collect fail", or "call fail". In these cases, returnInfo(code) is failure code from that event. Otherwise (if there is no previous failure event), the return value is "success", and returnInfo(code) is "0".
Non blocking
# get the last failure event and code
set event [failureCode returnInfo]
if {$returnInfo(code) == 17} {
set destination $forwardOnBusy
}
The getVariable command returns the value of a variable based on its type and name.
getVariable {callInfo | config | local | radius | aaa} name [returnInfo]
The arguments of this command are:
| Variable Type | Variable Name | Variable Description |
|---|---|---|
callInfo | ani | The origination (calling) number is returned. |
callIDin | The incoming call ID is returned. "0" is the return value if there is no incoming call ID. | |
callIDout | The outgoing call ID is returned. "0" is the return value if no outgoing call ID. | |
callIPin | The incoming IP leg's address is returned. Null is returned if the incoming leg is not an IP leg. | |
did | The value of the DID flag (0 or 1) is returned. | |
dnis | The destination (called) number is returned. | |
config
| uidLen | The account length is returned. |
pinLen | The PIN length is returned. | |
warningTime | The time to play the warning message is returned. | |
retryCount | The number of retries for entering digits is returned. | |
redirectNumber | The number for redirection of a call is returned. This variable can return a value of "not configured". | |
local | creditTimeLeft | The length of credit time remaining is returned. |
language | The language selected is returned. | |
radius1 | creditAmount | The credit amount remaining in the account is returned. |
| creditTime | The credit time remaining in the account is returned. |
| promptID | The ID of the prompt is returned. |
| redirectNumber | The number for redirection of a call is returned. |
| redirectIP | The IP address for the preferred route is returned. |
| preferredLang | The language that the billing system returns as the preferred language of the end user. Currently, three languages are supported; en (english), sp (spanish) and ch (mandarin). You can define additional languages as needed. |
| timeAtDest | The current time at the destination. |
| returnCode | This information is returned only after an authorization command is issued. It returns either a numerical value or "Unknown variable name." The numerical value indicates what action the IVR application should take, namely to play a particular audio file to inform the end user of the reason for the failed authorization. If "Unknown variable name" is returned, this indicates that the external RADIUS server is out of service. |
aaa | h323-ivr-in | A generic VSA for the billing server to send any information to the gatway in the form of an avpair like "color:blue" or "advprompt:rtsp://www.cisco.com/rtsp/areyouready.au |
| h323-ivr-out | A generic VSA for the gateway to send any information to the billing server in the form of an avpair like "color:blue" or "advprompt:rtsp://www.cisco.com/rtsp/areyouready.au |
| h323-credit-amount | The credit amount remaining in the account is returned. |
| h323-credit-time | The credit time remaining in the account is returned. |
| h323-prompt-id | The ID of the prompt is returned. |
| h323-redirect-number | The number for redirection of a call is returned. |
| h323-redirect-ip-addr | The IP address for the preferred route is returned. |
| h323-preferred-lang | The language that the billing system returns as the preferred language of the end user. Currently, three languages are supported; en (english), sp (spanish) and ch (mandarin). You can define additional languages as needed. |
| h323-time-and-day | The current time and day at the destination. |
| h323-return-code | This information is returned only after an authorization command is issued. It returns either a numerical value or "Unknown variable name." The numerical value indicates what action the IVR application should take, namely to play a particular audio file to inform the end user of the reason for the failed authorization. If "Unknown variable name" is returned, this indicates that the external AAA server is out of service. |
| h323-billing-model | Indicates the billing model used for the call. Initial values: 0=Credit, 1=Debit. Note: The debit card application will assume a Debit billing model. |
| 1The argument radius, though currently supported, has been obsoleted by aaa. It is strongly recommended that you use aaa and not radius. |
This command returns the value of the variable, as indicated in the preceding table. If you specify a variable name other than one listed in the preceding table, the command returns "Unknown variable name." Following is an example of how AAA information is returned for the attribute h323-ivr-in:
returnInfo(0) payphone:true returnInfo(1) color:blue
Non blocking
set event [authorize $account $pin $destination $ani info]
set num [getVariable aaa h323-ivr-in ivrIn]
if {$num != 0} {
## We got values back for h323-ivr-in, $num=2
## ivrIn(0)="payphone:true"
## ivrIn(1)="whateverValue"
## Do something
}
set num [getVariable aaa h323-credit-amount creditAmount]
if {$num != 0} {
## We got creditAmount back, $num=1
## creditAmount(0)=100.00
## Do something
}
set num [getVariable aaa xxx returnInfo]
## $num=0, because there is no VSA returned with a name matched "xxx"
h323-ivr-in=value
h323-ivr-in=payphone:true
getVariable aaa h323-ivr-in returnInfo
For more information about using VSAs to transmit information between the Voice Gateway and the AAA server, see the Vendor-Specific Attributes Implementation Guide.
The insertMessage command inserts a message to the originating (calling) party. This command blocks until the message completes. Digits are ignored. The destination (called) party will not hear anything (the tone or the calling party) while the message is playing.
insertMessage url returnInfo
The arguments of this command are:
This command returns "play complete." However, "outgoing disconnected" is returned if the called party hangs up.
Blocking
# Give the caller a warning 10 seconds before cutting him off
set event [startTimer [expr creditTime-10] retinfo]
if {$event == "Timeout"}
insertMessage tenSecondsLeft.au returnInfo
if { $event != "play complete} exit 0
startTimer 10
exit 0
}
If no conference is active when this command is invoked, the script returns an error code, which causes the underlying infrastructure to disconnect the call and clean up.
The insertTone command inserts a beep to the originating (calling) party. The tone is actually a 60 msec ring. The destination (called) party will not hear the tone. This command is typically used to warn the caller 10 seconds before the call is cut off.
insertTone
None
None
Non blocking
# If a timeout occurs, tell the caller with a beep
if { $event == "timeout" } {
insertTone
}
For information about how tones are defined in the code, see the "Tones" .
The placeCall command places a call to the specified destination.
placeCall destination info returnInfo
The arguments of this command are:
This command returns "active" or "call fail." If the call fails, the failure code is stored in returnInfo(code).
Blocking
# Place a call, setting an account number, and check the return
set callInfo(accountNum) $account
set ev [placeCall $destination callInfo info]
if {$ev == "active"} {
set state active
}
if {$ev == "call fail"} {
set state place_fail
}
The following arguments are defined in the code for the placeCall command:
The playFailureTone command plays a tone according to the last failure event and code. This command blocks until either the number of seconds elapses or an event occurs. The tone played is busy if the last failure code is Normal, unspecified, or busy. Otherwise, the tone played is congestion. This command is typically used to give the caller the appropriate tone (fast busy, normal busy, and so forth) on failure.
playFailureTone numSeconds returnInfo
The arguments of this command are:
This command returns "timeout" or an event. The value is stored in returnInfo(timeLeft). If a timeout occurs, returnInfo(timeLeft) is 0.
Blocking
# play failure tone for 5 seconds playFailureTone 5 returnInfo
For information about how tones are defined in the code, see the "Tones" .
The playPrompt command plays a prompt to the incoming call leg. This command is similar to the promptAndCollect command, except this command allows dynamic prompting.
playPrompt prompt_array_name returnInfo [promptInfo]
The arguments of this command are:
Blocking
# Get the destination number
set amt [getVariable radius creditAmount]
set param(interrupt) true
set param(abortKey) *
set param(dialPlan) true
set param(terminationKey) #
set ev [playPrompt param info en_you_have.au %a$amt %s1000 en_enter_dest.au]
if {$ev == "collect success"} {
set destination $info(digits)
set state second_authorize
return 0
}
if {$ev == "collect aborted"} {
set state get_dest
return 0
}
(config)#call application voice myApp language 3 en
setVariable language 3 setLocation tftp://keyer/en_audio/ en 0 setLocation tftp://keyer/fr_audio/ fr 0
(config)#call application voice myApp language 3 fr
playPrompt welcomeMessage
tftp://keyer/fr_audio/welcomeMessage.au
The playTone command creates a call progress tone. This command sends a user-specified tone to the call leg. Because there is no capability for this over an IP leg, a VoIP call leg ignores this command. If a conference is in session, the digital signalling processor (DSP) stops sending data to the remote end while playing a tone. This command is typically used give the caller a dial-tone if the script needs to collect digits.
playTone tone [outgoing]
The arguments of this command are:
playTone "Off Hook Alert"
None
Non blocking
# Output a ring for 5 seconds playTone Ring startTimer 5 elapsedTime playTone None
For information about how tones are defined in the code, see the "Tones" .
The promptAndCollect command plays a prompt to the caller and collects digits against a set of patterns. This command is similar to the playPrompt command, except this command does not allow dynamic prompting.
promptAndCollect prompt_array_name returnInfo [patterns]
The arguments of this command are:
This command returns "collect success," in which case returnInfo(digits) is the string collected. If the digits were collected against a pattern, returnInfo(patternName) is the name of the pattern. If the digits were collected against a dial plan, then returnInfo(patternName) is NULL.
This command can also return "play complete," if prompt(playCompete) was set, or "collect fail," if the digits collected do not match the pattern. If the digits collected do not match the pattern, the collected digits are not returned to the script.
If no pattern is defined and neither dialPlan nor playComplete is set to True, "collect fail" will be returned. If you use the argument "set patterns (anypattern) .+" to set the patterns, the PromptAndCollect command accepts any pattern of digits.
Blocking
# Prompt for destination number allow * entry to abort
set prompt(url) flash:EnterDest.au
set prompt(interrupt) true
set prompt(abortKey) *
set prompt(dialPlan) true
set event [promptAndCollect prompt info]
if {$event == "collect success"} {
set state place_call
set destination $info(digits)
}
The following arguments are defined in the code for the promptAndCollect command:
The puts command outputs a debug string to the console if the IVR state debug flag is set (using the debug voip ivr state command).
puts [-nonewline] string
The arguments of this command are:
This command returns an empty string.
Non blocking
puts "Handling call ID [callID]"
The rdn command returns the redirect number that came with the call.
rdn
None
This command returns the redirect number or a null string if no redirect number is available.
Non blocking
# place the call to the rdn set event [placeCall [rdn] callInfo info]
If there is no incoming call, the script will exit with error information.
The setLocation command specifies the location of the audio files for each language and category.
setLocation url language category
The arguments of this command are:
None
Non blocking
# install params set accountLen [getVariable config uidLen] set pinLen [getVariable config pinLen] set retryCnt [getVariable config retryCount] set operatorNum [getVariable config redirectNumber] set warnTime [getVariable config warningTime] set preLanguage [getVariable radius preferredLang] setVariable language 1 setLocation tftp://keyer/echeng/bowie_audio/ en 0
If you specify an invalid category or a language that has not been configured, the script returns an error code, which causes the underlying infrastructure to disconnect the call and clean up.
The setTimeout command sets the initial digit collection timeout and the inter-digit collection timeout values. This command overrides any configuration of the voice port. If you set the timeout to 0, this disables the timer.
setTimeout initialdigitTimeout interdigitTimeout
The arguments of this command are:
None
Non blocking
# set the digit timeouts short for redialer interaction setTimeout 2 1
The setVariable command sets the value of a specified variable.
setVariable name value
The arguments of this command are:
| Name | Value | Description |
longPound | true, false | If longPound is false, any pound sign (#) is reported as a # digits. If longPound is true, # digits longer than one second are reported as long pound events. |
language | 0 through 9 | Specifies the language to be used. |
If language is specified as the variable, this command can return one of the following:
Non blocking
#install parameters setVariable language 1 setVariable longPound true
The setupAck command sends a call setup acknowledgement message to the incoming call leg. This command is ignored if a setup acknowledgement, proceeding, or connect message has already been sent (for example, if the script has already issued a callProceeding or acceptCall command).
setupAck
None
None
Non blocking
# acknowledge the setup before waiting on authentication setupAck set event [authenticate [ani] [dnis] info]
If there is no incoming call, the script will exit with error information.
The startTimer command blocks until either a specified number of seconds elapses or another event (such as a destination hang up) occurs. The timer does not continue running after the startTimer command returns.
startTimer numSeconds returnInfo
The arguments of this command are:
This command returns "timeout" if no other event occurs. If an event occurs, returnInfo(timeLeft) contains the amount of time left. Otherwise, it contains 0.
Blocking
# wait for the credit time we have
set event [startTimer [creditTimeLeft] returnInfo]
while { $event == "digit" } {
set event [startTimer [creditTimeLeft] returnInfo]
}
The waitEvent command causes the script to sit idly until an event occurs.
waitEvent returnInfo
The argument of this command is:
This command returns:
Blocking
# Place a call, then just sit on waitEvent, ignoring digits
set callInfo(destinationNum) destination
set event [placeCall destination callInfo info]
if {$event != active} {
puts "Call [callID] got $event when placing call"
exit 0
}
set event [waitEvent returnInfo]
while {$event == "digit" } {
puts "ignoring received digit $returnInfo(digits)"
set event [waitEvent]
}
Within the code that supports the TCL IVR scripts, there is a series of defined values. These values are listed in this section.
The valid event values for the TCL IVR commands are:
The retInfo variable in most commands is an associative array that can contains information in the following fields:
For tones, the possible values are:
AAA--Authentication, Authorization, and Accounting. A suite of network security services that provides the primary framework through which you can set up access control on your Cisco router or access server.
ANI--Automatic number identification. Same as calling party.
CDR--Call Data Record.
CLI--Command line interface.
DID--Dial in direct. Calls in which the gateway uses the number that you initially dialed (DNIS) to make the call, as opposed to prompting you to dial additional digits.
DNIS--Dialed number identification service. Same as the called number.
DSP--Digital signalling processor.
DTMF--Dual tone multifrequency. Use of two simultaneous voice-band tones for dialing (such as touch tone).
Gatekeeper--A Gatekeeper maintains a registry of devices in the multimedia network. The devices register with the Gatekeeper at startup and request admission to a call from the Gatekeeper.
The Gatekeeper is an H.323 entity on the LAN that provides address translation and control access to the LAN for H.323 terminals and gateways. The Gatekeeper can provide other services to the H.323 terminals and gateways, such as bandwidth management and locating gateways.
gateway--A gateway allows H.323 terminals to communicate with non-H.323 terminals by converting protocols. A gateway is the point where a circuit-switched call is encoded and repackaged into IP packets.
An H.323 gateway is an endpoint on the LAN that provides real-time, two-way communications between H.323 terminals on the LAN and other ITU-T terminals in the WAN or to another H.323 gateway.
IFS--Cisco IOS File System.
ISDN--Integrated Services Digital Network. Communication protocol, offered by telephone companies, that permits telephone networks to carry data, voice, and other source traffic.
IVR--Interactive voice response. When someone dials in, IVR responds with a prompt to get a personal identification number (PIN), and so on.
OSP--Open Settlement Protocol. Protocol used to allow carriers to communicate with third-party settlement servers.
PIN--Personal identification number. Password used with account number for authentication.
POTS--Plain old telephone service. Basic telephone service supplying standard single line telephones, telephone lines, and access to the PSTN.
PSTN--Public Switched Telephone Network. PSTN refers to the local telephone company.
RADIUS--Remote Access Dial-In User Service. Database for authenticating modem and ISDN connections and for tracking connection time.
TCL--Tool Command Language. TCL is an interpreted script language developed by Dr. John Ousterhout of the University of California, Berkeley, and is now developed and maintained by Sun Microsystems Laboratories.
URL--Universal Resource Locator. Standardized addressing scheme for accessing hypertext documents and other services using a browser.
VoFR--Voice Over Frame Relay. Voice over Frame Relay enables a router to carry voice traffic (for example, telephone calls and faxes) over a Frame Relay network. When sending voice traffic over Frame Relay, the voice traffic is segmented and encapsulated for transit across the Frame Relay network using FRF.12 encapsulation.
VoIP--Voice over IP. The ability to carry normal telephone-style voice signals over an IP-based network with POTS-like functionality, reliability, and voice quality. VoIP is a blanket term that generally refers to Cisco's open standards-based (for example, H.323) approach to IP voice traffic.
Cisco Connection Online (CCO) is Cisco Systems' primary, real-time support channel. Maintenance customers and partners can self-register on CCO to obtain additional information and services.
Available 24 hours a day, 7 days a week, CCO provides a wealth of standard and value-added services to Cisco's customers and business partners. CCO services include product information, product documentation, software updates, release notes, technical tips, the Bug Navigator, configuration notes, brochures, descriptions of service offerings, and download access to public and authorized files.
CCO serves a wide variety of users through two interfaces that are updated and enhanced simultaneously: a character-based version and a multimedia version that resides on the World Wide Web (WWW). The character-based CCO supports Zmodem, Kermit, Xmodem, FTP, and Internet e-mail, and it is excellent for quick access to information over lower bandwidths. The WWW version of CCO provides richly formatted documents with photographs, figures, graphics, and video, as well as hyperlinks to related information.
You can access CCO in the following ways:
For a copy of CCO's Frequently Asked Questions (FAQ), contact cco-help@cisco.com. For additional information, contact cco-team@cisco.com.
Cisco documentation and additional literature are available in a CD-ROM package, which ships with your product. The Documentation CD-ROM, a member of the Cisco Connection Family, is updated monthly. Therefore, it might be more current than printed documentation. To order additional copies of the Documentation CD-ROM, contact your local sales representative or call customer service. The CD-ROM package is available as a single package or as an annual subscription. You can also access Cisco documentation on the World Wide Web at http://www.cisco.com, http://www-china.cisco.com, or http://www-europe.cisco.com.
If you are reading Cisco product documentation on the World Wide Web, you can submit comments electronically. Click Feedback in the toolbar and select Documentation. After you complete the form, click Submit to send it to Cisco. We appreciate your comments.

![]()
![]()
![]()
![]()
![]()
![]()
![]()
Posted: Mon Aug 7 19:25:49 PDT 2000
Copyright 1989-2000©Cisco Systems Inc.