Building an Interactive Dialplan(ASTERISK)

Building an Interactive Dialplan

The dialplan we just built was static; it will always perform the same actions on every call. Many dialplans will also need logic to perform different actions based on inputfrom the user, so let’s take a look at that now.

The Goto(), Background(), and WaitExten() Applications

As its name implies, the Goto() application is used to send a call to another part of the dialplan. The syntax for the Goto() application requires us to pass the destination context, extension, and priority on as arguments to the application,
same => n,Goto(context,extension,priority)
We’re going to create a new context called TestMenu, and create an extension in our LocalSets context that will pass calls to that  context using Goto():
exten => 201,1,Goto(TestMenu,start,1)  ;  add this to the end of the
                                                                ; [LocalSets] context
[TestMenu]
exten => start,1,Answer()
Now, whenever a device enters the LocalSets context and dials 201, the call will be passed to the start extension in the TestMenu
context (which currently won’t do anything interesting because we still have more code to write).

One of the most useful applications in an interactive Asterisk dialplan is the Back ground() 7 application. Like Playback(), it plays a recorded sound file. Unlike Playback(), however, when the caller presses a key (or series of keys) on her telephone keypad, it interrupts the playback and passes the call to the extension that corresponds with the pressed digit(s). If a caller presses 5, for example, Asterisk will stop playing the sound prompt and send control of the call to the first priority of extension 5 (assuming there is an extension 5 to send the call to).

The most common use of the Background() application is to create voice menus (often called auto attendants  or phone trees). Many companies use voice menus to direct callers to the proper extensions, thus relieving their receptionists from having to answer every
single call.
Background() has the same syntax as Playback():
[TestMenu]
exten => start,1,Answer()
same => n,Background(enter-ext-of-person)
If you want Asterisk to wait for input from the caller after the sound prompt has finished playing, you can use WaitExten(). The
WaitExten() application waits for the caller to enter DTMF digits and is used directly following the Background() application,
[TestMenu]
exten => start,1,Answer()
same => n,Background(enter-ext-of-person)
same => n,WaitExten()
If you’d like the WaitExten() application to wait a specific number of seconds for a response (instead of using the default timeout),
simply pass the number of seconds as the first argument to WaitExten(),
same => n,WaitExten(5) ; We always pass a time argument to WaitExten()
Both Background() and WaitExten() allow the caller to enter DTMF digits. Asterisk then attempts to find an extension in the current context that matches the digits that the caller entered. If Asterisk finds a match, it will send the call to that extension. Let’s demonstrate by adding a few lines to our dialplan example:
[TestMenu]
exten => start,1,Answer()
same => n,Background(enter-ext-of-person)
same => n,WaitExten(5)
exten => 1,1,Playback(digits/1)
exten => 2,1,Playback(digits/2)
After  these changes, save and reload your dialplan:
*CLI>dialplan reload
If you call into extension 201, you should hear a sound prompt that says “Enter the extension of the person you are trying to reach.” The system will then wait 5 seconds for you to enter a digit. If the digit you press is either 1 or 2, Asterisk will match the relevant extension, and read that digit back to you. Since we didn’t provide any further instructions, your call will then end. You’ll also find that if you enter a different digit (such as 3), the dialplan will be unable to proceed.
Let’s embellish things a little. We’re going to use the Goto() application to have the dialplan repeat the greeting after playing back the number:
[TestMenu]
exten => start,1,Answer()
same => n,Background(enter-ext-of-person)
same => n,WaitExten(5)
exten => 1,1,Playback(digits/1)
same => n,Goto(TestMenu,start,1)
exten => 2,1,Playback(digits/2)
same => n,Goto(TestMenu,start,1)
These new lines will send control of the call back to the start extension after playing back the selected number. This is generally considered friendlier than just hanging up.

Handling Invalid Entries and Timeouts

Now that our first voice menu is starting to come together, let’s add some additional special extensions. First, we need an extension for invalid entries. In Asterisk, when a context receives a request for an extension that is not valid within that context (e.g., pressing 9 in the preceding example), the call is sent to the i extension. We also need an extension to handle situations when the caller doesn’t give input in time (the default timeout is 10 seconds). Calls will be sent to the t extension if the caller takes too long to press a digit after WaitExten() has been called. Here is what our dialplan will look like after we’ve added these two extensions:
[TestMenu]
exten => start,1,Answer()
same => n,Background(enter-ext-of-person)
same => n,WaitExten(5)
exten => 1,1,Playback(digits/1)
same => n,Goto(TestMenu,start,1)
exten => 2,1,Playback(digits/2)
same => n,Goto(TestMenu,start,1)
exten => i,1,Playback(pbx-invalid)
same => n,Goto(TestMenu,start,1)
exten => t,1,Playback(vm-goodbye)
same => n,Hangup()
Using the i and t extensions makes our menu a little more robust and user-friendly. That being said, it is still quite limited, because outside callers still have no way of con‐ necting to a live person. To do that, we’ll need to learn about another application, called
Dial().

Using the Dial() Application

One of Asterisk’s most valuable features is its ability to connect different callers to each other. This is especially useful when callers are using different methods of communi‐ cation. For example, caller A might be communicating over the traditional analog telephone network, while user B might be sitting in a café halfway around the world and speaking on an IP telephone. Luckily, Asterisk takes much of the hard work out of connecting and translating between disparate networks. All you have to do is learn how to use the Dial() application.
The syntax of the Dial() application is more complex than that of the other applications we’ve used so far, but don’t let that scare you off. Dial() takes up to four arguments, which we’ll look at next.

Argument 1: destination

The first argument is the destination you’re attempting to call, which (in its simplest form) is made up of a technology (or transport) across which to make the call, a forwardslash, and the address of the remote endpoint or resource. Common technology types

include DAHDI (for analog and T1/E1/J1 channels), SIP, and IAX2.

For example, let’s assume that we want to call a DAHDI endpoint identified by DAHDI/1, which is an FXS channel with an analog phone plugged into it. The technology is DAHDI, and the resource (or channel identifier) is 1. Similarly, a call to a SIP device (as defined in sip.conf) might have a destination of SIP/0004F2001122, and a call to an IAX device (defined in iax.conf

) might have a destination of IAX2/Softphone. 11 If we wanted Asterisk to ring the DAHDI/1 channel when extension 105 is reached in the dialplan, we’d add the following extension:
exten => 105,1,Dial(DAHDI/1)
We can also dial multiple channels at the same time, by concatenating the destinations with an ampersand
exten => 105,1,Dial(DAHDI/1&SIP/0004F2001122&IAX2/Softphone)
The Dial() application will ring all of the specified destinations simultaneously, and bridge the inbound call with whichever destination channel answers first (the other channels will immediately stop ringing). If the Dial() application can’t contact any of
the destinations, Asterisk will set a variable called DIALSTATUS with the reason that it couldn’t dial the destinations, and continue with the next priority in the extension.
The Dial() application also allows you to connect to a remote VoIP endpoint not previously defined in one of the channel configuration files. The full syntax is:
Dial(technology/user[:password]@remote_host[:port][/remote_extension])
As an example, you can dial into a demonstration server at Digium using the IAX2 protocol by using the following extension:
exten => 500,1,Dial(IAX2/guest@misery.digium.com/s)
The full syntax for the Dial() application is slightly different for DAHDI channels:
Dial(DAHDI/[gGrR]channel_or_group[/remote_extension])
For example, here is how you would dial1-800-555-1212on DAHDI channel number
exten => 501,1,Dial(DAHDI/4/18005551212)

Argument 2: timeout

The second argument to the Dial() application is a timeout, specified in seconds. If a timeout is given, Dial() will attempt to call the specified destination(s) for that number of seconds before giving up and moving on to the next priority in the extension. If no timeout is specified, Dial() will continue to dial the called channel(s) until someone answers or the caller hangs up. Let’s add a timeout of 10 seconds to our extension:
exten => 502,1,Dial(DAHDI/1,10)
If the call is answered before the timeout, the channels are bridged and the dialplan is done. If the destination simply does not answer, is busy, or is otherwise unavailable, Asterisk will set a variable called DIALSTATUS and then continue on with the next priority in the extension.
Let’s put what we’ve learned so far into another example:
exten => 502,1,Dial(DAHDI/1,10)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
As you can see, this example will play the vm-nobodyavail.gsm sound file if the call goes unanswered.

Argument 3: option

The third argument to Dial() is an option string. It may contain one or more characters that modify the behavior of the Dial()
application. While the list of possible options is too long to cover here, one of the most popular is the m option. If you place the letter m as the third argument, the calling party will hear hold music instead of ringing while the destination channel is being called (assuming, of course, that music on hold has been configured correctly). To add the m option to our last example, we simply change
the first line:
exten => 502,1,Dial(DAHDI/1,10,m)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()

Argument 4: URI

The fourth and final argument to the Dial() application is a URI. If the destination channel supports receiving a URI at the time of the call, the specified URI will be sent (for example, if you have an IP telephone that supports receiving a URI, it will appear on the phone’s display; likewise, if you’re using a softphone, the URI might pop up on your computer screen). This argument is very rarely used.

Updating the dialplan

Let’s modify extensions 1 and 2 in our menu to use the Dial() application:
[TestMenu]
exten => start,1,Answer()
same => n,Background(enter-ext-of-person)
same => n,WaitExten(5)
exten => 1,1,Dial(SIP/0000FFFF0001,10) ; Replace 0000FFFF0001 with your device name
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
exten => 2,1,Dial(SIP/0000FFFF0002,10) ; Replace 0000FFFF0002 with your device name
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
exten => i,1,Playback(pbx-invalid
same => n,Goto(TestMenu,start,1)
exten => t,1,Playback(vm-goodbye)
same => n,Hangup()

Blank arguments

Note that the second, third, and fourth arguments may be left blank; only the first argument is required. For example, if you want to specify an option but not a timeout, simply leave the timeout argument blank, like this:
exten => 1,1,Dial(DAHDI/1,,m)

Using Variables

Variables can be used in an Asterisk dialplan to help reduce typing, improve clarity, or add logic. If you have some computer programming experience, you already understand what a variable is. If not, we’ll briefly explain what variables are and how they are used. They are a vitally important Asterisk dialplan concept (and something you will not find in the dialplan of any proprietary PBX)
A variable is a named container that can hold a value. The advantage of a variable is that its contents may change, but its name does not, which means you can write code that references the variable name and not worry about what the value will be. So, for example, we might create a variable called TECHNO and assign it the value of DAHDI/1 . This way, when we’re writing our dialplan we can refer to Techno channel by name, instead of remembering that Techno is using the channel named DAHDI/1. If at some point we change Techno channel to something else, we don’t have to change any of our code that references  the TECHNO variable; we only have to change the value assigned to the variable.

There are two ways to reference a variable. To reference the variable’s name, simply type the name of the variable, such as LEIF. If, on the other hand, you want to reference the value of the variable, you must type a dollar sign, an opening curly brace, the name of

the variable, and a closing curly brace (in the case of LEIF, we would reference the value of the variable with ${LEIF}). Here’s how we might use a variable inside the Dial() application:
exten => 301,1,Set(LEIF=SIP/0000FFFF0001)
same => n,Dial(${LEIF})
In dialplan, whenever we refer to ${LEIF} , Asterisk will automatically replace it with whatever value has been assigned to the variable named LEIF.
There are three types of variables we can use in our dialplan: global variables, channel variables, and environment variables. Let’s take a moment to look at each type.

Global variables

As their name implies, global variables are visible to all channels at all times. Global variables are useful in that they can be used anywhere within a dialplan to increase readability and manageability. Suppose for a moment that you had a large dialplan and
several hundred references to the SIP/0000FFFF0001 channel. Now imagine you had to go through your dialplan and change all of those references to SIP/0000FFFF0002. It would be a long and error-prone process, to say the least.
On the other hand, if you had defined a global variable that contained the value SIP/ 0000FFFF0001 at the beginning of your dialplan and then referenced that instead, you would have to change only one line of code to affect all places in the dialplan where that channel was used.
Global variables should be declared in the [globals] context at the beginning of the extensions.conf file. As an example, we will create a global variable named LEIF with a value of SIP/0000FFFF0001. This variable is set at the time Asterisk parses the dialplan:
[globals]
LEIF=SIP/0000FFFF0001

Channel variables

A channel variable is a variable that is associated only with a particular call. Unlike global variables, channel variables are defined only for the duration of the current call and are available only to the channels participating in that call.
There are many predefined channel variables available for use within the dialplan, which are explained in the Asterisk wiki . Channel variables are set via the Set() application:
exten => 202,1,Set(MagicNumber=42)
same => n,SayNumber(${MagicNumber})
You’re going to be seeing a lot more channel variables. Read on.

Environment variables

Environment variables are a way of accessing Unix environment variables from within Asterisk. These are referenced using the ENV() dialplan function. 14 The syntax looks like ${ENV(var)}, where var is the Unix environment variable you wish to reference. Environment variables aren’t commonly used in Asterisk dialplans, but they are available should you need them.

 Adding variables to our dialplan

Now that we’ve learned about variables, let’s put them to work in our dialplan. We’re going to add three global variables that will associate a variable name to a channel name:
[globals]
LEIF=SIP/0000FFFF0001
JIM=SIP/0000FFFF0002
RUSSELL=SIP/0000FFFF0003
[LocalSets]
exten => 101,1,Dial(${LEIF})
exten => leif,1,Dial(${LEIF})
exten => 102,1,Dial(${JIM})
exten => jim,1,Dial(${JIM})
exten => 103,1,Dial(${RUSSELL})
exten => russell,1,Dial(${RUSSELL})
exten => 201,1,Goto(TestMenu,start,1) ; access the TestMenu context
[TestMenu]
exten => start,1,Answer()
same => n,Background(enter-ext-of-person)
same => n,WaitExten()
exten => 1,1,Dial(DAHDI/1,10)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
exten => 2,1,Dial(SIP/Jane,10)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
exten => i,1,Playback(pbx-invalid)
same => n,Goto(TestMenu,start,1)
exten => t,1,Playback(vm-goodbye)
same => n,Hangup()
In our test menu we’ve simply picked a couple of random endpoints to dial, such as DAHDI/1 and SIP/Jane. These could be replaced with any available endpoints that you wish. Our TestMenu context has been built to start giving you an idea as to what an
Asterisk dialplan looks like.