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.

Saturday, March 20, 2010

Asterisk Setup Part 1

This is going to be a 3-part series on setting up Asterisk.

Part 1: Asterisk installation and preliminary configuration.  Includes making first call to/from the PBX system.
Part 2: Using common features of Asterisk (ie. conferencing, IVR, voicemail, etc).
Part 3: Setting up VOIP and interconnecting Asterisk server (IAX).  And once I'm up to speed, writing AGI scripts using Python.

Reminder: Make sure to backup up configuration files before you start working on it.  This is 3-part series on how to setup Asterisk PBX system

Okay, first some heads-up. Setting-up Asterisk is as complex as it looks (if not more so). A better sysad/hacker could have done it in few days but it took me almost a month, from the time I started reading the docs to successfully connect to/from the PBX for my first phone call.

What you'll also quickly realize when you start working with Asterisk is that it is actually two set of discipline: Telephony (ie. at least basic knowledge of what FXO/FXS is) and Linux system administration. Actually, that's three discipline if you count on working with the Dialplan which implicitly expect you to have a programming background.

So yes, the entry barrier for learning and setting-up Asterisk from scratch is pretty steep. You can ease the learning curve by using GUI-based Asterisk such Trixbox but there's a trade-off. But actually, you just kept going at it, until you get the hang of it. And then as with most things, it just sink in and becomes straight-forward set-up.

Here's my Asterisk Set-up:
  • Dual-core board with 2GB memory workstation.

    You can of course use Asterisk on old Pentium-class PC for testing and that is fine if you don't mind the lagged time and general sloggishness of your system (ie. codec processing takes a lot out of your CPU).

  • 2FXO/2FXS TDM410 Analog Card.

    I'm based in Manila where POTS lines is still common in residential areas, if you don't wish to purchase an analog card, you can opt for VOIP connection which is cheaper. I opted for an analog card for a more holistic experience in setting up Asterisk. But I'll probably get a VOIP connection soon.

    If you still would like to connect to your POTS line but find the TDM400-based cards a bit pricey, you can get those dirt-cheap X100P/X101P cards from Ebay. But remember, you get what you pay for. And you'd better be an intrepid hacker who's in need of good challenge to make these cards talk.

  • Distro: Centos 5.3 or newer.

    I'm only using 5.3 because I've already have a copy and don't want to bother with the 2 to 3 days download for the latest Centos release.

    Also, I prefer Centos/Fedora because of it's yum package management tool and because these are the distros I'm most comfortable with. But use whatever Linux distros that suites you.

  • Asterisk version 1.6 release

    Almost all documentation and tutorial you'll find on building Asterisk recommend that you compile it from the source which is nice really... if you like adding more complexity to an already complex set-up. Make you life easier, use package management tool like yum or apt-get. The time spent compiling (and troubleshooting) your own software is better utilize exploring various features of Asterisk.
So briefly, if you're going through this tutorial, here's my base assumption:
  • You have a clean Centos installation.

  • You are connected to the Internet (for downloading Asterisk packages).

  • You have an analog card similar to TDM410 series that is already attached to your motherboard PCI slot.

With introduction out of the way, here are the steps.

  1. Verify that you Linux box is properly detecting your Digium PCI card. # lspci | grep d161 "d161" is the Digium's PCI vendor ID. In addition to vendor ID, it should also show you the Digium card identifier. In my case, that's 8005 for TDM410 Wildcard.

  2. Install the Asterisk packages.

    yum -y install asterisk16 asterisk16-configs asterisk16-voicemail
    dahdi-linux dahdi-tools libpri
    Set the Asterisk and DAHDI package to automatically start at boot time. chkconfig --level 345 asterisk on
    chkconfig --level 345 dahdi on
  3. Edit the /etc/dahdi/system.conf file (make sure that you backup teh config files before editing it). Here's what my config looks like: loadzone = ph
    defaultzone = ph
    fxsks = 1-2
    fxoks = 3-4
    echocanceller = mg2,1-4
    It looks straight-forward right? It's not :-) it's really quite tricky. The 'loadzone' and 'defaultzone' is simple enough. I use 'ph' because I'm in Manila (check zonedata.c for your own country settings). The 'echocanceller' settins are for those who do not have hardware echo cancellers. These cost extra, if you only have hobbyist set-up, just opt for software-based echo canceller.

    The fxsks and fxoks settings is where it gets dicey.

    First let's have q quick detour on FXO/FXS (remember, you need to read-up on this topic). FXO (Foreign Exchange Object) is basically any physical 'object' that receive phone services from your local telco. The term 'object' here refers to a phone, a fax, a modem or any objects really that can handle these services.

    FXS (Foreign Exchange Subscriber) is basically POTS services delivered from your telco to your phone. FXS provides your phone with a dial tone, battery current, and ring voltage.

    Now here is where it gets dicey. For each port on your analog card, you should use the 'signalling' that it correlates to. This of course is the opossite signal.

    An FXO port needs to use a FXS signalling. Same goes for FXS port which needs an FXO signalling. So here, a "fxoks = 1-2" simply means that port 1 and 2 is an FXS plug and that we'll use an FXO signal with kewlstart grounding. Gets? No? It's a bit confusing but you'll get the hang of it.

    So now how do we determined that a plug is an FXO or FXS (ie. they look identical). The easiest would be to use a DAHDI tool called dahdi_scan. Just run it from the command line. Here's what mine looks like:

    Even if you use VOIP, you still need FXS if you wish to use an analog phones which is far far cheaper and more readily available than an IP phone. Yes, you can use 'softphones' but it gets tiring once the novelty has worn off.

    Note: Asterisk v1.4 and below uses /ec/zaptel.conf file but the settings are the same. The renaming of configuration files and other zaptel tools was due to trademark issues, Digium decided to rename all zaptel telephony interface into DAHDI (Digium Asterisk Hardware Device Interfface).

    Actually, most of the Asterisk tutorial you'll find still refer to the older zaptel.conf and zapata.conf file. As of March 2010, there are very few updated Asterisk tutorial


  4. Edit /etc/asterisk/chan_dahdi.conf file. This is where you'll configure the features and functionality of your card.

    Actually, they could have merged this two files into one instead of maintaining two separate configuration files with overlapping settings but where's the fun in that :-)

    Include the following in your extensions.conf: echotraining = 800

    ;FXS modules
    signalling = fxo_ks
    context = default
    group = 0
    channel = 1-2

    ;FXO modules
    signalling = fxs_ks
    group = 1
    context = outgoing
    channel = 3-4
    The 'echotraining' specify the time in milliseconds to pre-train the echo canceller. The 'signalling' chooses the signalling method for your FXO/FXS ports. We have 2 'context' settings, this is how Asterisk can determined which context to put incoming/outgoing calls in. Briefly, context is how you would control a call from beginning to end. The value 'incoming' and 'internal' is defined in the extensions.conf, if you did not specify one, it would use the value 'default' (which you still have to defined in the extensions.conf).

    The 'group' settings allows you to roll over your calls. For instance, if you have two telephone lines, you do not have to specify which line to use when picking up the phone to make an outgoing calls, Asterisk will automatically use the first available line. The 'channels' is the actual port where your FXO/FXS is connected.

    Note: Asterisk v1.4 and below uses /etc/asterisk/zapata.conf but the settngs are the same.


  5. Edit /etc/asterisk/extensions.conf file.

    This is the core of our Asterisk set-up and where we start working with our Dialplan. The extensions.conf is really a rudimentary scripting language for Asterisk, so a programming background is handy. We can use a number of Dialplans applications but for the purpose, we'll just write a couple of lines to have a working Asterisk for routing incoming calls to our analog phone.

    Here's my settings: [default]
    exten => s,1,Dial(dahdi/g0)
    Reload your extensions.conf by running the following command: asterisk -rx 'dialplan reload' From another line (or mobile phone) call the number where your Asterisk is hook-up and you should now receive incoming calls!

    At this point, you should have a working PBX system that can handle incoming calls! And this calls for some tea!

    Note: extensions.ael is a newer and cleaner version of extensions.conf, but since ael is still converted into conf file and there isn't really any compelling reason to shift to ael, stick with extensions.conf file for now.

  6. Set-up your outgoing calls by editing /etc/asterisk/extensions.conf file. [globals]
    PHONE=DAHDI/1
    PHONE2=DAHDI/2
    OUTBOUNDTRUNK=dahdi/g1

    [outgoing]
    exten => _9.,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
    Reload your extensions.conf. To get a dial tone, press 9 plus the number you are trying to call. That's it!

    Congratulation! You're very own, kickass PBX system!

    Note: We'll gloss over the intricacies of extensions.conf for the moment, and come back to it later on Part 2 of this tutorial.