📜 ⬆️ ⬇️

We write voice IVR menu in TCL language using Cisco IVR API

Today we are talking about the voice menu ( IVR ) for Cisco routers, which we will write in TCL, and connect to Cisco 3845.

So, first, let's understand the basics


Cisco, starting with IOS 12, supports both VXML and TCL scripts for working with voice menus. However, unlike VXML , TCL scripts have much more interaction with the Cisco IVR API . It is also possible to connect hybrid IVR scripts, with embedded pieces of VXML code inside the TCL script.

You can download all the documents related to Cisco IVR from Cisco here .
')

FSM


The first is the FSM transitions.
Finite-State Machines is an abstract automaton, the number of possible internal states of which is finite.
It looks like this:
set ivr_fsm(CALLCOMES,ev_setup_indication) "act_Setup same_state" 

Such transitions can be any number, and they are located at the end of the TCL script.

Let's see what it is all about.
The general syntax of this command is:
 set array(CURRSTATE, curr_event) “act_proc NEXTSTATE” 

Where:
array is the name of the FSM array.
CURRSTATE is the name of the current state at which the curr_event event was received .
act_proc is the name of the function to be executed when the curr_event event arrives .
NEXTSTATE is the name of the state that will be set after the execution of act_proc .

In other words, FSM is a marker by which Cisco compares the event received from the API with curr_event and the current status with CURRSTATE , if they are described in any FSM transition, the act_proc procedure is called and the state is changed to NEXTSTATE .

The most important thing in this is that the current event and state are compared with all the described FSM transitions at the same time . Those. for Cisco, the order in which the FSM transitions are located does not matter; they are all processed asynchronously.

Functions


The second point is the functions themselves, which must be described before the script is initialized.

The assignment of all commands and states is described in detail in the tcl_ivr_2.0_programming_guide file, which you can download here , I’ll only dwell on those that I will use directly in the script

1) Script initialization


The beginning of any TCL IVR script contains the init procedure, in my example, this function looks like this:
 proc init { } { puts "\n proc Init start" global param } 

Here, essentially, a screen is executed with the puts "..." command and the definition of a global variable param

The script initialization occurs after the description of all functions, and begins with the launch of the function init . This simple things ended, then everything is much more interesting.

The last executable line of the script should be the line that defines the start FSM transition and the start state. In our case it is:
 fsm define ivr_fsm CALLCOMES 

This means that the FSM name of the array is given as ivr_fsm , and the starting state is CALLCOMES . We'll finish with initialization, it will be more clear what is going on (I hope).

2) Greetings


 proc Play_Welcome { } { puts "\n\n IVR - proc Play_Welcome start \n\n" global playng_files global param global pattern global numbers global workingtime # ,     init_perCallVars #  GetDate #      ,   if {$workingtime} { set after_welcome $playng_files(takenumber) } else { set after_welcome $playng_files(noworking) } #     set param(interruptPrompt) true set param(abortKey) * set param(terminationKey) # #   leg setupack leg_incoming leg proceeding leg_incoming leg connect leg_incoming #        leg collectdigits leg_incoming param pattern #    ,    #   param(interDigitTimeout),    #  ev_collectdigits_done media play leg_incoming %s500 $playng_files(welcome) $after_welcome $playng_files(onhold) # ,      ev_named_timer timer start named_timer $numbers(waiting_time) t1 } 

Here everything is described in some detail.

The result of this procedure will be to connect the incoming line to Cisco at the expense of the leg setupack, leg proceeding, leg connect, and playing music files one by one on the incoming line at the expense of the media play leg_incoming command .
The process of collecting the pressed leg collectdigit keys and the timer with the timer start command starts immediately .

And whether the working time is now checked or not by calling the GetDate function:
 proc GetDate { } { global workingtime # set houris [clock format [clock seconds] -format %H] #  set dayis [clock format [clock seconds] -format %A] #   if {$houris > 17 || $houris < 8 || $dayis=="Sunday" || $dayis=="Saturday"} { set workingtime 0 } else { set workingtime 1 } } 

Depending on the working time or not, we change the music file that will be played to the calling subscriber.

Since the starting state is set in our case as fsm define ivr_fsm CALLCOMES , 3 FSM fall into it immediately:
 set ivr_fsm(CALLCOMES,ev_setup_indication) "Play_Welcome, same_state" set ivr_fsm(CALLCOMES,ev_collectdigits_done) "CheckDestanation, same_state" set ivr_fsm(CALLCOMES,ev_named_timer) "GoToReception, same_state" 

The ev_setup_indication event will occur when a call arrives, and the Play_Welcome procedure will be launched, which describes the start of the process of collecting the pressed numbers and the start of the timer.

After the music is played to the subscriber, a reverse timer report starts, which is set by the param (initialDigitTimeout) parameter (which could have been set just above the set param line (initialDigitTimeout) 15 and set to 15 seconds), because it is not specified here, its standard value is 10 seconds, after which the script will receive the event ev_collectdigits_done , upon the occurrence of which, as we described in the FSM transition, the CheckDestanation function will be executed.

Timer running on Play_Welcome with the command:
 #  named_timer, ,    numbers(waiting_time),   t1 timer start named_timer $numbers(waiting_time) t1 

After its termination, it will generate an ev_named_timer event, which will be processed by the following FSM transition:
 set ivr_fsm(CALLCOMES,ev_named_timer) "GoToReception, same_state" 

and the procedure GoToReception will be called .

3) Check the entered number


 proc CheckDestanation { } { puts "\n\n IVR - proc CheckDestanation start \n\n" global playng_files global numbers global digit #   media stop leg_incoming #   set status [infotag get evt_status] set digit [infotag get evt_dcdigits] #     #    ,    $numbers(fast_reception), # digit      $digit   CheckCallersAndConnect, #     CALLCONNECTED, #  ,    ev_setup_done (   ) #    CallIsConnect if {$digit == $numbers(fast_reception)} { puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next reception \n\n" fsm setstate CALLCONNECTED set digit $numbers(reception) # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #    ,    $numbers(fast_ckp),    # CheckCallersAndConnect } elseif {$digit == $numbers(fast_ckp)} { puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next CKP \n\n" fsm setstate CALLCONNECTED set digit $numbers(ckp) # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #    ,    $numbers(fast_fax),    # CheckCallersAndConnect } elseif {$digit == $numbers(fast_fax)} { puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next fax \n\n" fsm setstate CALLCONNECTED set digit $numbers(fax) # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #  = cd_004 (   ) -     # CheckCallersAndConnect } elseif {$status == "cd_004"} { puts "\n\n IVR - proc CheckDestanation status = $status digit = $digit \n\n" fsm setstate CALLCONNECTED # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #  = cd_005 (  dial plan) -     # CheckCallersAndConnect } elseif {$status == "cd_005"} { puts "\n\n IVR - proc CheckDestanation status = $status digit = $digit \n\n" fsm setstate CALLCONNECTED # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #  = cd_006 (   ) -    $playng_files(noexist) #     TORECEPTION,       #ev_media_done (   )   Play_TakeNumber } elseif {$status == "cd_006"} { puts "\n\n IVR - proc CheckDestanation status = $status digit = $digit \n\n" fsm setstate TRYAGAIN media play leg_incoming $playng_files(noexist) #       TORECEPTION,    #   ev_media_done (   )  # GoToReception } else { # "    " fsm setstate TORECEPTION media play leg_incoming $playng_files(toreception) puts "\n\n IVR - proc CheckDestanation status = $status \n\n" } } 

In the CheckDestanation procedure, which will be called after the caller dials the number, we compare the digits obtained with the settings with the settings and translate the script into the appropriate state using the fsm setstate command .

All states in the function fall under the following FSM transitions:
 set ivr_fsm(CALLCONNECTED,ev_setup_done) "CallIsConnect, same_state" set ivr_fsm(TORECEPTION,ev_media_done) "GoToReception, same_state" set ivr_fsm(TRYAGAIN,ev_media_done) "Play_TakeNumber, TRYING" set ivr_fsm(TRYING,ev_collectdigits_done) "CheckDestanation, same_state" set ivr_fsm(TRYING,ev_named_timer) "GoToReception, same_state" 

Let's take it in order.

1) So, initially, the CheckDestanation function is called after the end of the keystroke collection procedure.
2) We write the information about the keystrokes into the digit variable using the set digit [infotag get evt_dcdigits] command
Similarly, write the state of the line in the status variable
3) Then we compare the results obtained with the given variables and change the state of the script if it matches:
 if {$digit == $numbers(fast_reception)} { puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next reception \n\n" fsm setstate CALLCONNECTED leg setup $numbers(reception) callinfo leg_incoming } 


4) Check the caller's number


 proc CheckCallersAndConnect {digit} { puts "\n\n IVR - proc CheckCallersAndConnect start \n\n" set callernumber [infotag get leg_ani] switch $callernumber { "9120000000" {set callInfo(displayInfo) "Director(mobile)"} "9130000000" {set callInfo(displayInfo) "Buhgalter(mobile)"} default {} } puts "\n\n IVR - caller is $callernumber connect with $digit\n\n" leg setup $digit callInfo leg_incoming } 

This feature allows you to change the field responsible for writing the name of the caller. Just for the sake of aesthetics, it will be more pleasant when not only the number but also the subscriber ID is written on the phone. After changing the subscriber ID the line is connected to the required number.

5) Connecting the number


 proc CallIsConnect { } { puts "\n\n IVR - proc CallIsConnect start \n\n" global playng_files #   status set status [infotag get evt_status] #   ls_000 (    ),    CALLACTIVE if {$status == "ls_000"} { fsm setstate CALLACTIVE #   ls_002 (    ),     } elseif {$status == "ls_002"} { fsm setstate TRYAGAIN media play leg_incoming $playng_files(noanswer) #  -  ,     } elseif {$status == "ls_004" || $status == "ls_005" || $status == "ls_006"} { fsm setstate TRYAGAIN media play leg_incoming $playng_files(noexist) #   ls_007 ( ),     } elseif {$status == "ls_007"} { fsm setstate TRYAGAIN media play leg_incoming $playng_files(busy) } } 

This function is called by the following FSM transition:
 set ivr_fsm(CALLCONNECTED,ev_setup_done) "CallIsConnect, same_state" 

The ev_setup_done event occurs after the caller is connected to the desired line.

6) Repeat number request


 proc Play_TakeNumber { } { puts "\n\n IVR - proc Play_TakeNumber start \n\n" global playng_files global numbers global param global pattern #       if {$numbers(cur_try) <= $numbers(max_try)} { puts "\n\n IVR - proc Play_TakeNumber current try is: $numbers(cur_try) \n\n" incr numbers(cur_try) #        leg collectdigits leg_incoming param pattern #   media play leg_incoming $playng_files(takenumber) # ,      ev_named_timer timer start named_timer $numbers(waiting_time) t1 #    $numbers(max_try) -  } else { fsm setstate CALLDISCONNECTED media play leg_incoming $playng_files(callafter) } } 

This function checks if the caller is wrong once, and if the value is less than $ numbers (max_try) asks to enter the number again.

This function is called by the following FSM :
 set ivr_fsm(TRYAGAIN,ev_media_done) "Play_TakeNumber, TRYING" set ivr_fsm(TRYING,ev_collectdigits_done) "CheckDestanation, same_state" set ivr_fsm(TRYING,ev_named_timer) "GoToReception, same_state" 


7) Disconnection


 proc AbortCall { } { puts "\n\n IVR - proc AbortCall start \n\n" call close } 

Called by the following FSM :
 set ivr_fsm(any_state,ev_disconnected) "AbortCall, same_state" set ivr_fsm(CALLACTIVE,ev_disconnected) "AbortCall, CALLDISCONNECTED" set ivr_fsm(CALLDISCONNECTED,ev_disconnected) "AbortCall, same_state" set ivr_fsm(CALLDISCONNECTED,ev_media_done) "AbortCall, same_state" set ivr_fsm(CALLDISCONNECTED,ev_disconnect_done) "AbortCall, same_state" 


8) Script connection


Connecting to a Cisco router runs in 2 steps.
The first thing to do is define an application :
 application service voicemunu flash:voicemenu.tcl param allowed_pattern 5[5-7].. param fastto_reception 1 param reception_number 5501 param fastto_ckp 2 param ckp_number 5604 param fastto_fax 3 param fax_number 5555 param waiting_time 20 param max_try 3 param file_noanswer flash:en_noanswer.au param file_after flash:en_after.au param file_noexist flash:en_noexist.au param file_busy flash:en_busy.au param file_welcome flash:en_welcome.au param file_onhold flash:music-on-hold.au param file_noworking flash:en_takenumber2.au param file_takenumber flash:en_takenumber2.au 

Second , connect service to dial-peer :
 dial-peer voice 200 pots description -= ISP Beeline - INcoming call to number 3300100 =- service voicemunu incoming called-number 3300100 

Thus, when you receive a call to the number 3300100, our voice menu voicemunu will be called.

9) Full version of the script


Above only the main functions of the script were considered, then the full text, keep in mind, this is practically the simplest option:
 ####################################################### # Cisco IVR TCL script by Konovalov DA v.2 ####################################################### # #    # debug voip application script #    ( ,    ) # debug voip ivr # #       : # param allowed_pattern 5[5-7].. # param fastto_reception 1 # param reception_number 5501 # param fastto_ckp 2 # param ckp_number 5604 # param fastto_fax 3 # param fax_number 5555 # param waiting_time 20 # param max_try 3 # param file_welcome flash:en_welcome.au # param file_takenumber flash:en_takenumber.au # param file_after flash:en_after.au # param file_busy flash:en_busy.au # param file_noexist flash:en_noexist.au # param file_noanswer flash:en_noanswer.au # param file_onhold flash:music-on-hold.au # param file_noworking flash:music-on-hold.au #   proc init { } { puts "\n proc Init start" global param } #   proc init_perCallVars { } { global pattern global numbers global playng_files #####  #       ,    .... - 4   if {[infotag get cfg_avpair_exists allowed_pattern]} { set pattern(1) [string trim [infotag get cfg_avpair allowed_pattern]] puts "\n\n IVR - Allowed pattern set as: $pattern(1) \n\n" } else { set pattern(1) .... puts "\n\n IVR - Allowed pattern set as DEFAULT: $pattern(1) \n\n" } ##### #.        ,     0000 if {[infotag get cfg_avpair_exists reception_number]} { set numbers(reception) [string trim [infotag get cfg_avpair reception_number]] puts "\n\n IVR - reception number set as: $numbers(reception) \n\n" } else { set numbers(reception) 0000 puts "\n\n IVR - reception number set as DEFAULT: $numbers(reception) \n\n" } # if {[infotag get cfg_avpair_exists ckp_number]} { set numbers(ckp) [string trim [infotag get cfg_avpair ckp_number]] puts "\n\n IVR - ckp number set as: $numbers(ckp) \n\n" } else { set numbers(ckp) 0000 puts "\n\n IVR - ckp number set as DEFAULT: $numbers(ckp) \n\n" } # if {[infotag get cfg_avpair_exists fax_number]} { set numbers(fax) [string trim [infotag get cfg_avpair fax_number]] puts "\n\n IVR - fax number set as: $numbers(fax) \n\n" } else { set numbers(fax) 0000 puts "\n\n IVR - fax number set as DEFAULT: $numbers(fax) \n\n" } #    if {[infotag get cfg_avpair_exists fastto_reception]} { set numbers(fast_reception) [string trim [infotag get cfg_avpair fastto_reception]] puts "\n\n IVR - fast to reception set as: $numbers(fast_reception) \n\n" } else { set numbers(fast_reception) 1 puts "\n\n IVR - fast to reception set as DEFAULT: $numbers(fast_reception) \n\n" } #    if {[infotag get cfg_avpair_exists fastto_ckp]} { set numbers(fast_ckp) [string trim [infotag get cfg_avpair fastto_ckp]] puts "\n\n IVR - fast to ckp set as: $numbers(fast_ckp) \n\n" } else { set numbers(fast_ckp) 2 puts "\n\n IVR - fast to ckp set as DEFAULT: $numbers(fast_ckp) \n\n" } #    if {[infotag get cfg_avpair_exists fastto_fax]} { set numbers(fast_fax) [string trim [infotag get cfg_avpair fastto_fax]] puts "\n\n IVR - fast to fax set as: $numbers(fast_fax) \n\n" } else { set numbers(fast_fax) 3 puts "\n\n IVR - fast to fax set as DEFAULT: $numbers(fast_fax) \n\n" } #    (       ) if {[infotag get cfg_avpair_exists waiting_time]} { set numbers(waiting_time) [string trim [infotag get cfg_avpair waiting_time]] puts "\n\n IVR - wait number set as: $numbers(waiting_time) \n\n" } else { set numbers(waiting_time) 10 puts "\n\n IVR - wait number set as DEFAULT: $numbers(waiting_time) \n\n" } #    ,        if {[infotag get cfg_avpair_exists max_try]} { set numbers(max_try) [string trim [infotag get cfg_avpair max_try]] puts "\n\n IVR - max try set as: $numbers(max_try) \n\n" set numbers(cur_try) 0 } else { set numbers(max_try) 5 puts "\n\n IVR - max try set as DEFAULT: $numbers(max_try) \n\n" set numbers(cur_try) 0 } ##### ,    #  if {[infotag get cfg_avpair_exists file_welcome]} { set playng_files(welcome) [string trim [infotag get cfg_avpair file_welcome]] puts "\n\n IVR - file_welcome set as: $playng_files(welcome) \n\n" } else { #   ,       1 set playng_files(welcome) %s1 puts "\n\n IVR - file_welcome set as DEFAULT: $playng_files(welcome) \n\n" } #     if {[infotag get cfg_avpair_exists file_takenumber]} { set playng_files(takenumber) [string trim [infotag get cfg_avpair file_takenumber]] puts "\n\n IVR - file_takenumber set as: $playng_files(takenumber) \n\n" } else { #   ,       1 set playng_files(takenumber) %s1 puts "\n\n IVR - file_takenumber set as DEFAULT: $playng_files(takenumber) \n\n" } # "  " if {[infotag get cfg_avpair_exists file_after]} { set playng_files(callafter) [string trim [infotag get cfg_avpair file_after]] puts "\n\n IVR - file_after set as: $playng_files(callafter) \n\n" } else { #   ,       1 set playng_files(callafter) %s1 puts "\n\n IVR - file_after set as DEFAULT: $playng_files(callafter) \n\n" } # " " if {[infotag get cfg_avpair_exists file_busy]} { set playng_files(busy) [string trim [infotag get cfg_avpair file_busy]] puts "\n\n IVR - file_busy set as: $playng_files(busy) \n\n" } else { #   ,       1 set playng_files(busy) %s1 puts "\n\n IVR - file_busy set as DEFAULT: $playng_files(busy) \n\n" } # "  " if {[infotag get cfg_avpair_exists file_noexist]} { set playng_files(noexist) [string trim [infotag get cfg_avpair file_noexist]] puts "\n\n IVR - file_noexist set as: $playng_files(noexist) \n\n" } else { #   ,       1 set playng_files(noexist) %s1 puts "\n\n IVR - file_noexist set as DEFAULT: $playng_files(noexist) \n\n" } # "  /" if {[infotag get cfg_avpair_exists file_toreception]} { set playng_files(toreception) [string trim [infotag get cfg_avpair file_toreception]] puts "\n\n IVR - file_toreception set as: $playng_files(toreception) \n\n" } else { #   ,       1 set playng_files(toreception) %s1 puts "\n\n IVR - file_toreception set as DEFAULT: $playng_files(toreception) \n\n" } # "  ,  " if {[infotag get cfg_avpair_exists file_noanswer]} { set playng_files(noanswer) [string trim [infotag get cfg_avpair file_noanswer]] puts "\n\n IVR - file_noanswer set as: $playng_files(noanswer) \n\n" } else { #   ,       1 set playng_files(noanswer) %s1 puts "\n\n IVR - file_noanswer set as DEFAULT: $playng_files(noanswer) \n\n" } # ,      if {[infotag get cfg_avpair_exists file_onhold]} { set playng_files(onhold) [string trim [infotag get cfg_avpair file_onhold]] puts "\n\n IVR - file_onhold set as: $playng_files(onhold) \n\n" } else { #   ,       1 set playng_files(onhold) %s1 puts "\n\n IVR - file_onhold set as DEFAULT: $playng_files(onhold) \n\n" } # ,       if {[infotag get cfg_avpair_exists file_noworking]} { set playng_files(noworking) [string trim [infotag get cfg_avpair file_noworking]] puts "\n\n IVR - file_noworking set as: $playng_files(noworking) \n\n" } else { #   ,       1 set playng_files(noworking) %s1 puts "\n\n IVR - file_noworking set as DEFAULT: $playng_files(noworking) \n\n" } } proc GetDate { } { global workingtime # set houris [clock format [clock seconds] -format %H] #  set dayis [clock format [clock seconds] -format %A] #   if {$houris > 17 || $houris < 8 || $dayis=="Sunday" || $dayis=="Saturday"} { set workingtime 0 } else { set workingtime 1 } } #   proc Play_Welcome { } { puts "\n\n IVR - proc Play_Welcome start \n\n" global playng_files global param global pattern global numbers global workingtime # ,     init_perCallVars #  GetDate #      ,   if {$workingtime} { set after_welcome $playng_files(takenumber) } else { set after_welcome $playng_files(noworking) } #     set param(interruptPrompt) true set param(abortKey) * set param(terminationKey) # #   leg setupack leg_incoming leg proceeding leg_incoming leg connect leg_incoming #        leg collectdigits leg_incoming param pattern #    ,     #  param(interDigitTimeout),    #  ev_collectdigits_done media play leg_incoming %s500 $playng_files(welcome) $after_welcome $playng_files(onhold) # ,      ev_named_timer timer start named_timer $numbers(waiting_time) t1 } #    proc Play_TakeNumber { } { puts "\n\n IVR - proc Play_TakeNumber start \n\n" global playng_files global numbers global param global pattern #       if {$numbers(cur_try) <= $numbers(max_try)} { puts "\n\n IVR - proc Play_TakeNumber current try is: $numbers(cur_try) \n\n" incr numbers(cur_try) #        leg collectdigits leg_incoming param pattern #   media play leg_incoming $playng_files(takenumber) # ,      ev_named_timer timer start named_timer $numbers(waiting_time) t1 #    $numbers(max_try) -  } else { fsm setstate CALLDISCONNECTED media play leg_incoming $playng_files(callafter) } } #     proc GoToReception { } { puts "\n\n IVR - proc GoToReception start \n\n" global numbers #   media stop leg_incoming #  fsm setstate CALLCONNECTED set digit $numbers(reception) # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit } #        proc CheckDestanation { } { puts "\n\n IVR - proc CheckDestanation start \n\n" global playng_files global numbers global digit #   media stop leg_incoming #   set status [infotag get evt_status] set digit [infotag get evt_dcdigits] #     #    ,    $numbers(fast_reception), # digit      $digit   CheckCallersAndConnect, #     CALLCONNECTED, #  ,    ev_setup_done (   ) #    CallIsConnect if {$digit == $numbers(fast_reception)} { puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next reception \n\n" fsm setstate CALLCONNECTED set digit $numbers(reception) # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #    ,    $numbers(fast_ckp),    # CheckCallersAndConnect } elseif {$digit == $numbers(fast_ckp)} { puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next CKP \n\n" fsm setstate CALLCONNECTED set digit $numbers(ckp) # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #    ,    $numbers(fast_fax),    # CheckCallersAndConnect } elseif {$digit == $numbers(fast_fax)} { puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next fax \n\n" fsm setstate CALLCONNECTED set digit $numbers(fax) # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #  = cd_004 (   ) -     # CheckCallersAndConnect } elseif {$status == "cd_004"} { puts "\n\n IVR - proc CheckDestanation status = $status digit = $digit \n\n" fsm setstate CALLCONNECTED # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #  = cd_005 (  dial plan) -     # CheckCallersAndConnect } elseif {$status == "cd_005"} { puts "\n\n IVR - proc CheckDestanation status = $status digit = $digit \n\n" fsm setstate CALLCONNECTED # $digit   CheckCallersAndConnect CheckCallersAndConnect $digit #  = cd_006 (   ) -    $playng_files(noexist) #    TRYAGAIN,       ev_media_done #(   )   Play_TakeNumber } elseif {$status == "cd_006"} { puts "\n\n IVR - proc CheckDestanation status = $status digit = $digit \n\n" fsm setstate TRYAGAIN media play leg_incoming $playng_files(noexist) #       TORECEPTION,     #  ev_media_done (   )   GoToReception } else { # "    " fsm setstate TORECEPTION media play leg_incoming $playng_files(toreception) puts "\n\n IVR - proc CheckDestanation status = $status \n\n" } } # ,  ,     proc CheckCallersAndConnect {digit} { puts "\n\n IVR - proc CheckCallersAndConnect start \n\n" set callernumber [infotag get leg_ani] switch $callernumber { "9120000000" {set callInfo(displayInfo) "Director(mobile)"} "9130000000" {set callInfo(displayInfo) "Buhgalter(mobile)"} default {} } leg setup $digit callInfo leg_incoming } #          proc CallIsConnect { } { puts "\n\n IVR - proc CallIsConnect start \n\n" global playng_files #   status set status [infotag get evt_status] #   ls_000 (    ),    CALLACTIVE if {$status == "ls_000"} { fsm setstate CALLACTIVE #   ls_002 (    ),     } elseif {$status == "ls_002"} { fsm setstate TRYAGAIN media play leg_incoming $playng_files(noanswer) #  -  ,     } elseif {$status == "ls_004" || $status == "ls_005" || $status == "ls_006"} { fsm setstate TRYAGAIN media play leg_incoming $playng_files(noexist) #   ls_007 ( ),     } elseif {$status == "ls_007"} { fsm setstate TRYAGAIN media play leg_incoming $playng_files(busy) } } #   proc AbortCall { } { puts "\n\n IVR - proc AbortCall start \n\n" call close } #  init #init_perCallVars #         #        #       ev_disconnected,  AbortCall set ivr_fsm(any_state,ev_disconnected) "AbortCall, same_state" #   CALLCOMES   ev_setup_indication ( ) # Play_Welcome,     same_state (..  ) set ivr_fsm(CALLCOMES,ev_setup_indication) "Play_Welcome, same_state" #   CALLCOMES   ev_collectdigits_done (  ) # CheckDestanation,     set ivr_fsm(CALLCOMES,ev_collectdigits_done) "CheckDestanation, same_state" #   CALLCOMES   ev_named_timer (    ) # GoToReception,     set ivr_fsm(CALLCOMES,ev_named_timer) "GoToReception, same_state" #   TORECEPTION   ev_media_done (  ) # GoToReception,     set ivr_fsm(TORECEPTION,ev_media_done) "GoToReception, same_state" #         set ivr_fsm(TRYAGAIN,ev_media_done) "Play_TakeNumber, TRYING" set ivr_fsm(TRYING,ev_collectdigits_done) "CheckDestanation, same_state" set ivr_fsm(TRYING,ev_named_timer) "GoToReception, same_state" #   CALLCONNECTED   ev_setup_done #(/    )  CallIsConnect,     set ivr_fsm(CALLCONNECTED,ev_setup_done) "CallIsConnect, same_state" #     set ivr_fsm(CALLACTIVE,ev_disconnected) "AbortCall, CALLDISCONNECTED" set ivr_fsm(CALLDISCONNECTED,ev_disconnected) "AbortCall, same_state" set ivr_fsm(CALLDISCONNECTED,ev_media_done) "AbortCall, same_state" set ivr_fsm(CALLDISCONNECTED,ev_disconnect_done) "AbortCall, same_state" fsm define ivr_fsm CALLCOMES 

Source: https://habr.com/ru/post/265453/


All Articles