Tuesday, March 30, 2010

Asterisk Setup Part 2

So you now have a working and hand-built PBX system (albeit a rudimentary one) but you want a more full-featured, commercial-grade PBX system that you can use to impress friends, colleagues, and loved ones. Welcome to Part 2 of our Asterisk set-up!

Okay, first we need to tackle Dialplan, the heart of an Asterisk server and where most of our configuration will take place. Dialplan is configured in /etc/asterisk/extensions.conf where the logic on how calls are routed takes place and unlike most configuration file you've tackled, it's slightly more complex.

The extensions.conf can be broken down into three major parts: Context, Extensions, and variables.

  • Context - extensions.conf is divided into sections, and each sections is called context. Context is denoted by placing square brackets ([]) at the head of the section. All extensions placed after a context definition are part of that context, until the next context is defined. 
  • There are two special context called [general] and [globals].

    The [general] context is where global configuration entries resides and it defined how extensions.conf behaves. Here is an example:

    [general]
    static=no
    writeprotect=no
    • static controls how Asterisk rewrites the extensions.conf when an extension is added or deleted.
    • writeprotect enables a user to rewrite your Dialplan from the command line

    The [globals] context defined global variables. Variables are basically container for information. There are three types of Asterisk variables. Global variables applies throughout your extensions.conf, for instance: [globals]
    PHONE1=DAHDI/1
    PHONE2=DAHDI/2
    OUTBOUNDTRUNK=dahdi/g1

    PHONE1 and PHONE2 refers to your FXS module where your incoming calls are routed. The OUTBOUNDTRUNK variable refer to the FXO module use for making outbound calls (dahdi/g1 refers to group=1 in your chan_dahdi.conf file).


  • Extensions are the individual entries in your context. These are run by Asterisk and it's corresponding application every time a call is initiated in that context.

  • An extension is broken down into three components:
    • The extension number
    • The priority which control the flow of the applications to run
    • The application that perform some action.

    Extensions uses the following syntax exten => name,priority,application() exten => 123,1,Answer()

    Where '123' is the extension number, '1' is the priority number, and Answer() is the name of the application. In most extensions.conf, you will see 'n' value instead of a priority number. The 'n' value is a shortcut for 'next' and tells Asterisk to run the next step one line after the other. This is for convenience so you don't need to re-number the steps if you need to change the flow of your program.

    Here is simple Dialplan:

    [incoming]
    exten => s,1,Answer()
    exten => s,n,Playback(hello-world)
    exten => s,n,Hangup()

    You'll notice here that we have an 's' instead of an extension number. The 's' stands for 'start', this is where the call will be routed if no extension number is given. The Answer() application answer a ringing channel. After the call has been 'pick-up', it will be routed to Playback() which 'plays' a sound file (ie. hello-world) to the caller. Once the sound file has been played, Asterisk hangs up the connection via Hangup() program.

Pattern Matching are another crucial part of extensions.conf.  Basically patterns matching, allows you to match various number combination.  These are often used when trying to dial an outside number.  Pattern matching always begin with an underscore (_) character.  After the underscore, you can use one or more of the following characters:
  • X - Matches any single digit from 0 to 9
  • Z - Matches any single digit from 1 to 9
  • N - Matches any single digit from 2 to 9
  • . - Matches any one or more characters, no matter what they are.
In Part 1, you saw the following directive for making an outside call. [outgoing]
exten => _9.,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})

In this directive, you need to dial 9 before calling an outside number. The underscore (_) before it indicate that this directive will be pattern matching. The '.' character after 9 will match all the number you press after 9. The '1' indicate that this is the first priority. The Dial() will then route the call to your trunk line. The '${EXTEN:1}' will strip off the first digit (which in this case is 9) before dialling the number.

Last but not the least is the 'include' statement. Basically, it just enables you to include other contexts from within another context. It has the following form:

[default]
include => menu
include => outgoing
include => conference

Here, the [default] have access to the following context: menu, outgoing, conference.

Now that we've tackled extensions.conf, let's take a brief look at some of the common applications used on Dialplan

  • Background() is similar to Playback() application but plays the sound file in the background, while waiting for the user to enter the extension number.
  • Dial() application dials a channel using the following syntax
  • Dial(technology/resource,timeout,option)

    Where technology could be DAHDI, SIP, IAX2, etc. Timeout is the length of time in seconds the Dial() will wait until the call is answered. The common option use in Dial() is 'm' which plays music to the caller until the call is answered.

  • Goto() jumps to specified priority, extensions, and context.
  • Set() sets a variable value.
  • WaitExten() application waits for the caller to enter the extension numbers and normally called after the Background().

You should now be familiar with basics of extensions.conf, so


Feature 1: Voicemail System

Voicemail is probably one of most popular application of Asterisk, here's how we set it up.

  1. In your /etc/asterisk/voicemail.conf file, find the [zonemessages] context and add the following settings: [zonemessages]
    philippines=Asia/Manila|'vm-received' Q 'digits/at' IMp
    Note: You can find the time zone information at /usr/share/zoneinfo/ directory.

  2. In the same file, find the [default] context and configure mailboxes for your user 'Gene': 1000 => 1234,Gene Ordanza,gene@localhost,,|attach=no|tz=philippines
  3. Here the '1000' is the Voicemail ID number and '1234' is the numeric password for this mailbox. The name of the mailbox is 'Gene Ordanza' and it's email address is gene@localhos', 'attach=no' mean do not attach the voicemail to his email and timezone is Philippines.

  4. In your extensions.conf, add the following:
  5. exten => 3,1,Dial(${PHONE2},10,m)
    exten => 3,n,Voicemail(1000,u)
    exten => 3,n,Hangup()

    When a caller hit '3', it will dial the extension number of 'Gene'. When there is no response in 10 seconds, it will be routed to Voicemail ID 1000. The 'u' option plays the 'unavailable' greetings to the caller. You should try leaving a voicemail first before proceeding to the next step.

  6. To retrieve your voicemail, add the following in your extensions.conf: exten => 900,1,VoicemailMain()

    The extension 900 routes you to the Voicemail system which will then prompt you for mailbox number and password.

  7. That's it! Don't forget to restart the Asterisk service every you need to modify your extensions.conf.


Feature 2: Automated Attendant

Auto Attendant are basically call menus. It allow a caller to be automatically transferred to an extension number without going through an operator.

Auto Attendant are commonly interchange with Interactive Voice Response (IVR) since they provide a superficially similar functionality. Think of Auto Attendant as a way to automate transfer of calls to various extension numbers whereas IVRs provide more complexity and customization (ie. phone banking where IVR will prompt you to enter your account number and provide you a way to access your account balance information).

  1. First, we need to record the audio file for our background menu. In your extensions.conf, add the following:
  2. exten => 205,1,Answer()
    exten => 205,n,Wait(2) exten => 205,n,Record(mainmenu)
    exten => 205,n,Wait(5) exten => 205,n,Playback(mainmenu) exten => 205,n,Hangup()

    First, we dial 205 extension to get to the recording application. We wait for 2 seconds, then we start recording our main menu prompt. Once you're done, press '#' key, then wait for another 2 seconds, before Asterisk starts to playback our pre-recorded main menu prompt.

    By default, it should saved the audio file in /var/lib/asterisk/sounds/ you can use any of your fav music player (ie. Audacious, Amarok, Rhythmbox, etc) to manually listen to it.

  3. Once we have our audio menu, we can now redirect to caller to our Background application using the audio file we created. Find the [incoming] context from our previous settings above. Change [incoming] to [main] context and add the following directives.
  4. [menu] exten => s,1,Answer() exten => s,n,Background(mainmenu) exten => s,n,WaitExten(5) exten => s,n,Hangup()

    When a caller connects to our PBX, he gets the background audio file we recorded. Asterisk waits 5 seconds for an extension to be dialled. If no extension was dialled, the call is disconnected.

Feature 3: Call Parking

Call park is a standard feature of Asterisk. It allows a person to put a call on hold at one telephone set and continue from any other telephone set.

For instance, a caller is looking for personA who is otherwise engaged. You can 'park' the call on line '701'. Once personA is available, you can tell him that someone is waiting on line '701'. Then personA finds an available phone and dial extension '701' to get to the caller.

  1. In your /etc/asterisk/features.conf file, find the [general] context and add the following: [general] parkext => 700 parkpos => 701-720 context => parkedcalls parkingtime => 120

    The settings above means we can park calls by dialling 700, and the call will be placed in the first available extension choosen from 701 to 720. Asterisk will then announced the parking extension number. Assuming we have 20 open lines, we can parked 20 calls. The context from which can access parked calls is 'parkedcalls'. If the calls is not answered in 120 seconds, it will ring back extension number of the user who parked the call.

  2. In your extensions.conf, include the following line where the calls are being routed.
  3. include => parkedcalls
Feature 4: Conference Calls

Asterisk comes built-in with excellent conferencing system. I tried going to one of the local telco provider and ask for a ballpark figure for a PABX with concall feature. The sales guy insisted that we first set a meeting and discuss their SME 'solution'! One of those awkward "if you ask, then you can't afford" situations.

  1. In your /etc/asterisk/meetme.conf file, add the following:
  2. [rooms] conf => 810 conf => 820,1234 conf => 830,1234

    We have 3 conference room from the setup above. The conference room '810' is public conference room, meaning everybody can join in, they just need dial the '810' extension. Conference room '820' and '830' is private, the caller needs to type the password '1234' before joining the conference.

  3. In your /etc/asterisk/extensions.conf file, add the following:
  4. [default] include => conference
    [conference] exten => 810,1,Answer() exten => 810,n,MeetMeCount() exten => 810,n,MeetMe(810,i) exten => 820,1,Answer() exten => 820,n,MeetMe(820,i,1234) exten => 820,n,Hangup() exten => 830,1,Answer() exten => 830,1,MeetMe(830,i,1234) exten => 830,n,Hangup()

    When a caller dials 810, Asterisk will connect him to the public conference but before that the MeetMeCount() will announce the number of participants in the conference room. The i option in MeetMe will announce new participants and those leaving the conference room.

    Note: Conferencing is CPU extensive, more participants means higher load on your processor due to transcoding.

    Also, when setting up conferencing feature in Asterisk, you need a timing device. Fortunately, most cards (ie. analog card like TDM410 or digital cards) have built-in timing device. If you have a pure VOIP/Asterisk setup, install the ztdummy driver and load it on the kernel.

Feature 5: Music on Hold (MOH)

MOH feature of Asterisk allow you to play music for the caller while he is on hold. Like most setup above, MOH is straight-forward to configure.

  1. Download you MOH music here. Get the GSM-formatted MOH (ie. asterisk-moh-freeplay-gsm.tar)
  2. Uncompress the tar file, create MOH directory, and move the files to the new directory.
  3. # tar xzvf asterisk-moh-freeplay-gsm.tar
    # mkdir /var/lib/asterisk/sound/moh
    # mv asterisk-moh-freeplay/* /var/lib/asterisk/sound/moh
  4. In your /etc/asterisk/musiconhold.conf file, find the [default] context and add the following:
  5. [default] mode=files directory=/var/lib/asterisk/sound/moh random=yes
  6. That's it! You should now be able to use it on your system.
  7. If you wish to use your own MOH sound, make sure you that you encode it in a compatible format like ulaw. It is possible to use mp3, wav or other format, but it'll take some work.

Now, to pull it all together, here's the extensions.conf for our PBX system at home.

Currently revising the dialplan below, might be a syntax error below that I missed.

[general] static=no writeprotect=no [globals] PHONE1=DAHDI/1 PHONE2=DAHDI/2 OUTBOUNDTRUNK=dahdi/g1 [default] include => menu include => outgoing include => conference exten => s,1,Answer() exten => s,n,Goto(menu,123,1) [menu] exten => 123,1,Answer() exten => 123,n,Background(/var/lib/sounds/mainmenu) ;Paolo and CJ's extension number exten => 1,1,Dial(${PHONE2},10,m) exten => 1,n,VoiceMail(2000,u) exten => 1,n,Goto(123,1) ;Gene's extension number exten => 3,1,Set(VMNUM=1000) exten => 3,n,Dial(${PHONE2},10,m) exten => 3,n,Goto(s-${DIALSTATUS},1) exten => s-NOANSWER,1,Voicemail(${VMNUM},u) exten => s-BUSY,1,Voicemail(${VMNUM},b) exten => 2-ANSWER,1,Hangup() exten => _s-.,1,Goto(s-NOANSWER),1) exten => 0,1,Dial(${PHONE2},20,m) exten => 0,n,Playback(hello-world) exten => 0,n,Goto(123,1) ;For invalid entries exten => i,1,Playback(pbx-invalid) exten => i,n,Goto(123,1) ;For timeout entries (caller did not enter any number for 5 seconds) exten => t,1,Playback(pbx-invalid) exten => t,n,Goto(123,1) [conference] exten => 810,1,Answer() exten => 810,n,MeetMe(810) exten => 810,n,MeetMeCount(810) exten => 820,1,Answer() exten => 820,n,MeetMe(820,i,1234) exten => 830,1,Answer() exten => 830,n,MeetMe(830,i,1234) exten => 830,n,Hangup() [outgoing] exten => _9.,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})

IMPORTANT: Make sure to reload your extensions.conf for the changes to take effect. To reload your Asterisk server from command line, run the following:

# asterisk -rx 'module reload'

That's it! Next we'll setup VOIP and scripting on Part III of our Asterisk Setup.

No comments: