|
|
Cisco is building voice gateways to connect more traditional telephone networks to Voice over IP networks. Customers who are installing VoIP networks often need a mechanism at the gateway to present a customized interface to the caller.
The IVR application provides Interactive Voice Response (IVR) capabilities using Tool Command Language (TCL) scripts. For example, an IVR script is played when a caller receives a voice-prompt instruction 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) and forwards the collected digits to a server for storage and retrieval. Call records can be kept and a variety of accounting functions performed.
The IVR feature software allows the use of one of several interactive voice response scripts during the call processing functionality. The scripts are designed to interact with the IVR application software to perform the various functions. IVR scripts contain both executable files and audio files that interact with the system software.
IVR applications can be assigned to specific ports or invoked based on DNIS. (Refer to the List of Terms on page x.) An Internet Protocol (IP) Public Switched Telephone Network (PSTN) gateway can have several different IVR applications to accommodate many different gateway services, and the IVR applications can be customized to present different interfaces to the different callers.
The IVR scripts are the default scripts for all Cisco voice features. All IVR scripts that were developed for releases prior to Cisco IOS Release 12.0(5)T are modified and secured with a proprietary Cisco locking mechanism using TCL. Only Cisco internal technical support personnel can open and modify these scripts. When the script is activated, the system verifies the Cisco signature level. If the script is inconsistent with the authorized signature level, the script will not load and the customer's console screen will display an error message.
Cisco provides these audio files, however we recommend that you record your own audio files to use with these scripts.
To obtain a complete description of each IVR script, use the show call application voice [<application name>| summary] command and insert the desired script name in the application name field. The screen output displays a description of each script.
| Script Name | Action |
|---|---|
| flash:enter_account.au | Asks caller to enter account number the first time. |
| flash:auth_fail_retry.au | Played after two failures, asks user to reenter account number. |
| flash:enter_pin.au | Asks caller to enter PIN number. |
| flash:enter_destination.au | Asks caller to enter destination phone number. |
flash:auth_fail_final.au | Informs caller that authorization failed three times |
Audio File Name | Action |
|---|---|
auth_fail_retry.au | Informs the caller that authorization failed. Prompts to please reenter your account number followed by the pound sign (#). |
auth_fail_final.au | Informs the caller, "I'm sorry, your account number cannot be verified. Please hang up and try again." |
| Audio File Name | Action |
|---|---|
| flash:enter_account.au | Asks caller to enter the account number the first time. |
| flash:auth_fail_retry.au | Plays after first two failures, asks user to reenter the account number. |
| flash:enter_destination.au | Asks the caller to enter the destination phone number. |
| flash:auth_fail_final.au | Informs the caller that authorization failed three times. |
|
|
To use Interactive Voice Response with scripts on your Cisco access platform, configure the in bound VoIP dial-peer. Perform the following commands beginning in dial-peer configuration mode:
| Step | Command | Purpose | ||
|---|---|---|---|---|
| 5800 (config) # dial-peer | Enter dial-peer configuration mode. | ||
| 5800 (dial-peer) # dial-peer voice number pots | Enter dial-peer configuration mode to configure a POTS dial peer. Note The number value of the dial-peer voice pots command is a tag that uniquely identifies the dial peer. | ||
| 5800 (dial-peer) # call application voice app name | Enter the command to initiate the IVR application and the selected application name. Enter the application name and the location of where the IVR script is stored. | ||
| 5800 (dial-peer) # destination-pattern call number | Enter the number to be dialed when calls fail. For example, the operator number. | ||
| 5800 (dial-peer) # port port number | Configure the voice port associated with this dial peer. |
Use the application field, in the inbound dial peer to associate an application with an incoming call. This field is applicable to the dial-peer of the POTS encapsulation type only. Examples of applications entered in this field are the IVR scripts.
When a call initially comes in, an application is selected by the Call Control Applications Programming Interface (CCAPI) based on configuration in the inbound dial peer.
Use the show running configuration command to generate screen output showing the configured parameters. The following IVR configuration uses the clid_col_dnis_3.tcl IVR script:
Router # show running-config Building configuration... Current configuration: ! ! Last configuration change at 17:57:03 pst Wed Feb 24 1999 ! version 12.0 service timestamps debug uptime service timestamps log uptime no service password-encryption service udp-small-servers service tcp-small-servers ! hostname sblab115 ! boot system tftp username/c5800-p4-mz 172.29.20.12 boot system tftp username/c5800-p4-mz 172.29.20.12 no logging buffered aaa new-model aaa authentication login no_rad local aaa authentication login h323 group radius local ! clock timezone pst -8 clock summer-time pdt recurring ip subnet-zero ip domain-name cisco.com ip name-server 172.29.20.223 ip name-server 172.69.20.13 ! call application voice c4 tftp://santa/username/clid_4digits_npw_3.tcl call application voice c5 tftp://santa/username/clid_col_dnis_3.tcl ! voice-port 1/0/0 ! voice-port 1/0/1 ! voice-port 1/1/0 shutdown pre-dial-delay 0 ! voice-port 1/1/1 shutdown pre-dial-delay 0 ! dial-peer voice 997 voip destination-pattern 997 session target loopback:rtp ! dial-peer voice 1 pots application clid ! dial-peer voice 2 pots ! dial-peer voice 100 pots application c5 answer-address 1234 destination-pattern 100 port 1/0/0 ! voice-port 1/1/0 shutdown pre-dial-delay 0 ! voice-port 1/1/1 shutdown pre-dial-delay 0 ! dial-peer voice 997 voip destination-pattern 997 session target loopback:rtp ! dial-peer voice 1 pots application clid ! dial-peer voice 2 pots ! dial-peer voice 100 pots application c5 answer-address 1234 destination-pattern 100 port 1/0/0 ! dial-peer voice 110 pots application clid destination-pattern 110 direct-inward-dial port 1/1/0 ! dial-peer voice 111 pots destination-pattern 111 port 1/1/1 ! dial-peer voice 114 voip destination-pattern 114... session target dns:sblab114 ! dial-peer voice 991 pots destination-pattern 991 port 1/0/0 session target loopback:uncompressed ! dial-peer voice 992 pots destination-pattern 992 port 1/0/1 session target loopback:uncompressed Router #
New Cisco IOS commands are available to deal with IVR functionality. These commands are entered when the dial peer is being configured. The commands are as follows:
The following examples are given for comparison purposes only.
Router # show call application voice session
Application session
The script is compiled into the image
It has 0 calls active.
The TCL Script is:
------------------
# session.tcl
#------------------
# September 1998, Development Engineer name
#
# Copyright (c) 1998, 1999 by cisco Systems, Inc.
# All rights reserved.
#----------------------------------
#
# This tcl script mimics the default SESSION app
#
# If DID is configured, just place the call to the dnis
# Otherwise, output dial-tone and collect digits from the
# caller against the dial-plan.
#
# Then place the call. If successful, connect it up, otherwise
# the caller should hear a busy or congested signal.
# Don't accept until we can place outgoing side.
# acceptCall
#
# The main routine is at the bottom. Start reading there.
proc do_active_notimer {} {
set event [waitEvent]
while { $event == "digit" } {
set event [waitEvent]
}
proc do_active_last_timer {} {
set event [startTimer [creditTimeLeft] info]
while { $event == "digit" } {
set event [startTimer $info(timeLeft) info]
}
if { $event == "timeout" } {
clearOutgoingLeg retInfo
do_out_of_time
}
proc do_active_timer {} {
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
}
proc do_out_of_time {} {
set prompt(url) flash:out_of_time.au
set prompt(playComplete) true
set event [promptAndCollect prompt info ]
# And here is the main routine
#
#if DID, don't collect digits, just place the call.
if {[did]} {
set destination [dnis]
} else {
# play a dial tone, and collect against the pattern setupAck
playTone Dial
set prompt(dialPlan) true
set event [promptAndCollect prompt retInfo]
if {$event != "collect success"} {
puts "Call [callID] got event $event collecting destination"
exit 0
}
set destination $retInfo(digits)
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]
if {$event != "active"} {
puts "Call [callID] got $event when placing call\n"
exit 0
}
# The call is active, they are talking.
#
if { ( [creditTimeLeft] == "unlimited") ||
([creditTimeLeft] == "uninitialized") } {
do_active_notimer
} else {
do_active_timer
Application clid_authen
The script is compiled into the image
It has 0 calls active.
The TCL Script is:
------------------
# clid_authen.tcl
#----------------------------------
# September 1998, Development Engineer name
--More-
#
# Copyright (c) 1998, 1999 by cisco Systems, Inc.
# All rights reserved.
#----------------------------------
# Mimic the clid_authen script in the SP1.0 release.
#
# It authenticates using (ani, dnis) for (account, password). If
# that fails, play a message and end the call.
#
# 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_dest {} {
global state
global destination
playTone Dial
set prompt(dialPlan) True
set prompt(terminationKey) #
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
}
set state get_fail
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
--More--
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_get_fail {} {
global state
playTone None
--More--
set prompt(url) flash:collect_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
--More--
set event [authenticate [ani] [dnis] info]
if {$event != "authenticated"} {
set state authen_fail
} else {
set state authen_pass
}
while {$state != "end"} {
puts "cid([callID]) running state $state"
if {$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 == "get_fail"} {
--More--
do_get_fail
} elseif {$state == "out_of_time"} {
do_out_of_time
} else {
break
}
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, Development Engineer name
#
# Copyright (c) 1998, 1999 by cisco Systems, Inc.
# All rights reserved.
#----------------------------------
# Mimic the clid_authen_collect script in the SP1.0 release.
#
--More--
# 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
--More--
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
}
![]()
![]()
![]()
![]()
![]()
![]()
![]()
Posted: Wed Nov 3 16:57:28 PST 1999
Copyright 1989-1999©Cisco Systems Inc.