Interactive voice response (IVR) is ubiquitous and now pervades the business and commerce milieu. Using Asterisk, IVR can be easily set up and coded. This fifth article in the series on Asterisk takes a look at how IVR is coded.
Asterisk provides a generic switching platform to run a variety of applications. IVR is commonly used today in most large corporate PBXes. Typically, these are automated voice menus what you hear when you call a bank or insurance company. The recorded voice will prompt you to input the intended transaction as a choice in the form of digits (DTMF or dual tone multi-frequency tones). The transactions requested for are executed based on the user inputs. In this session, we will look into IVR coding and then the hardware configuration required.
Lets start with a welcome menu, which is a very common feature nowadays in any Asterisk installation. The code is written in the dial plan, which is the central routing control based on pattern matching. The dial plan is generally found in /etc/asterisk/extensions.conf.
Example 1s
- Play the welcome message to the caller
- Ring the extension for 60 seconds
- If unavailable, pass the call to voicemail
- Hang up
Heres the code snippet for this example:
[from-pstn] exten => _.,1, Answer(); exten => _.,2, Playback(welcome); exten => _.,3, Dial(SIP/${EXTEN},60); exten => _.,4, Voicemail(${EXTEN},u); exten => _.,5, Hangup(); |
[from-pstn] indicates the context in which the call is processed, which is the incoming calls from the PSTN (public switched telephone network normal PRI or FXO trunk). exten => is a standard keyword to indicate a pattern matching routine. _.indicates that any extension is matched and the following actions need to be carried out. The second digit 1 after the comma indicates a sequence number. The lines that follow increase the sequence number in ascending order. Answer() indicates the call has to be answered so that the voice channels are open in both directions. This is required, so that the users can hear the greetings message and provide their inputs. Playback (welcome) instructs the system to search for a file welcome.gsm or welcome.wav in the default voice directory, and play that file for the user to hear. The file could contain a voice recording of the message, Welcome to OSFY. EXTEN saves the value of the extension dialled by the caller. Dial the EXTEN using the SIP protocol and ring for 60 seconds. The user may pick up the call and talk to the caller. If the user is unavailable, call the services voicemail with the same EXTEN extension number. After returning from the voicemail, hang up.
Example 2
The next example demonstrates how calls can be routed based on the users inputs:
[from-pstn] exten => 1234,1,Answer(); exten => 1234,n,Set(TIMEOUT(digit)=1); exten => 1234,n,Set(TIMEOUT(response)=10); exten => 1234,n,Background(welcome); exten => 1234,n,Background(ivr-options); exten => 1234,n,WaitExten(); |
The welcome message is played in the background, if the user dials the extension 1234. The function Playback() is blocked and the user will be able to provide the inputs only after the message is completed. In case ofBackground, the welcome message and ivr-options are played one after the other. The users can input their choice at any point of time. The function TIMEOUT is set for two cases: 1) if the user presses one digit, and 2) if the time exceeds 10 seconds. Also, note that the second parameter n takes away the burden of sequencing, like in Example 1, and makes the sequence dynamically next to the previous statement. The ivr-options plays the message, Please press 1 for sales, 2 for support, 3 for operator…
exten => 1,1,Dial(SIP /2000 &SIP /2001 ); exten => 1,n,Playback(sendback-to-ivr); exten => 1,n,Goto(1234,1); exten => 2,1,Dial(SIP /2002 &SIP /2003 ); exten => 2,n,Playback(sendback-to-ivr); exten => 2,n,Goto(1234,1); |
If the user presses 1, the extensions 2001 and 2002 will ring in parallel. If no one picks up, a voice file stating that, Currently, no agents are available, is played and the call is sent back to the main IVR loop. Similarly, if the user presses 2, both the extensions 2003 and 2004 in the sales department will ring.
exten => 0,1,Dial(SIP /2111 ,50); exten => 0,n,Voicemail(2111,u); exten => 0,n,Hangup(); |
If the user presses 0 to talk to the operator, the extension 2111 will ring for 50 seconds. If nobody responds, then the call is redirected to the voice mail.
exten => i,1,NOOP(wrong input received); exten => i,n,Playback(invalid); exten => i,n,Goto(1234,1); |
If the user presses anything other than 1, 2 or 0, the message file with, You have chosen an invalid input, is played and the call is sent back to the main loop.
exten => t,1,NOOP(no input received); exten => t,n,Playback(pls- select -option); exten => t,n,Goto(1234,1); |
If the user comes out of the loop without any input due to the timeout setting of 10 seconds, then another message, You have not selected any input, is played and sent back to the main loop.
The dial plan also provides the choice to query and store to an external database. In the next example, we will have students inputting their roll number. After verification, the users attendance will be reconfirmed and stored in the database.
[from-pstn] exten => 1234,1,Answer(); exten => 1234,n,Set(DID=${EXTEN}); exten => 1234,n,Playback(welcome); exten => 1234,n,Playback(pls-enter-enroll); exten => 1234,n,Read(enroll,beep,10); exten => 1234,n,SayDigits(${enroll}); exten => 1234,n,Set(TIMEOUT(digit)=1); exten => 1234,n,Set(TIMEOUT(response)=10); exten => 1234,n,Background(pls-confirm); exten => 1234,n,WaitExten() |
The welcome message and the request for inputting the roll number is played. After that, the roll number is read up to 10 digits. Then the input digits are read out loud and a confirmation is requested.
exten => 1,1,NOOP(Caller confirmed entry); exten => 1,n,Goto(autoprocess,submenu,1); exten => 2,1,NOOP(Caller wants to re-enter); exten => 2,n,Goto(1234,3); |
If the user confirms that the entry is correct, then the control proceeds to the auto-process sub-menu. Else, the control proceeds to re-enter the inputs.
[autoprocess] exten => submenu,1,Set(TIMEOUT(digit)=1); exten => submenu,n,Set(TIMEOUT(response)=1); exten => submenu,n,Background(Pls- select -frm-menu); exten => submenu,n,WaitExten(); |
A request is made to the user to input the service needed. If the user wants to check the attendance so far, 1 can be pressed.