Playing with queues
The company I work for, is changing the proprietary phone system to an open source one: asterisk. That is a big fat yay of course! Since I’m the only one at this company who knows his way around linux, it’s my job to set things up. Since I like goofing around in .conf files, it is no punishment. Not at all! Anyway, the reason we move to asterisk, is that we have our call-center systems working on vicidial, which, you might have guessed, works on asterisk. Besides the call-center applications, we also have “regular” telephone traffic, and that is what I’m setting up now. And the reason I’m posting this here, is that there might be somebody out there who can benefit from this info.
So, what had to be done is the following. We have two divisions at the office here (we have 3 offices in total, but this setup is only for one of them, the main office). We have a service-desk and a administration-desk. We have one main phone number, which refers to both of these divisions. The caller is presented an ivr menu, where they make their choice of needed service. The choices we have here, are only 3 different ones. At choice 1, they get redirected to another office, choice 2 takes them to the service-desk and choice 3 takes them to administration. Since the divisions we have here are not that large, we have to take into account that one of both divisions can be totally understaffed at any given time. To solve this, I have the phone ring on division X for 30 seconds and if there is no pickup, it will ring on both divisions after that. So, how do we get this done in asterisk?
First we need to have a inbound did on the incoming phone number. I use vicidial here, which has a gui to create dids and call-menus, so that works a little different, but the outcome is the same. You need to put something like this in you extensions.conf:
exten => _inboundnumber,1,Answer
exten => _inboundnumber,2,Playback(some_welcome_message)
exten => _inboundnumber,3,GoTo(MenuSecion,s,1)
exten => _inboundnumber,4,Hangup()
This will play a welcome message and then forwards the incoming number to a section in your extensions.conf, called MenuSection (just using clear names here, call it whatever you like). The MenuSection looks something like this:
[MenuSection]
exten => s,1,log_menu_call_with_agi
exten => s,n,Background(Option1)
exten => s,n,Background(Option2)
exten => s,n,Background(Option3)
exten => s,n,WaitExten(10)
exten => s,n,Background(Option1)
exten => s,n,Background(Option2)
exten => s,n,Background(Option3)
exten => s,n,WaitExten(10)
; Option1
exten => 1,1,Goto(from-internal,phone_number_of_other_office,1)
; Option2
exten => 2,1,Goto(default,666705,1)
; Option3
exten => 3,1,Goto(default,666706,1)
; Timeout
exten => t,1,Playback(no_choice_made_sound)
exten => t,n,Hangup
; Invalid
exten => i,1,Playback(invalid_choice_made_sound)
exten => i,2,Goto(MenuSection,s,1)
; hangup
exten => h,1,log_things_with_agi_or_whatever
This is your menu. First a log will be made, because well, I like to log stuff. Then the menu options will be played, after which a caller has 10 seconds to make his/her choice. No choice after 10 seconds, plays the choices again. A timeout (t) will hangup the call and an invalid (i) choice will reroute back to the start of the call-menu. A hangup will log stuff, just because I want to log that, but it is not necessary. Ok, what is the interesting part here, are the options! I’ll explain those here:
- A caller presses 1
This will forward the caller to another office. The reason it is a simple forward here, is that we make use of oldskool copper lines and there is no VoIP implemented (yet).
- A caller presses 2
The call is rerouted to extension 666705 in the default section of extensions.conf
- A caller presses 3
The call is rerouted to extension 666706 in the default section of extensions.conf
The 66670X extensions are just number I made up myself for this purpose. I start all my extensions with 666, don’t ask me why, I just do. But you can use any number you want, that does not matter. So, what happens in 666705?
exten => 666705,1,Answer
exten => 666705,n,Playback(message_hold_on_a_second)
exten => 666705,n,Queue(SD||||30)
exten => 666705,n,GoTo(VM,2,1)
exten => 666705,n,Hangup()
So, this extension gets answered, then playbacks a message stating to hold on a sec please, then goes into a queue for 30 seconds and when it gets out of the queue after 30 seconds, it goes to the VM section, extension 2. What does all this mean? Well, the caller gets thrown into a queue where he/she will hear some sexy music while waiting for an agent to pick up the call. A queue is setup in queues.conf and the queue I use here, looks something like this:
[SD]
musicclass = MOHMAIN
strategy = ringall
servicelevel = 60
timeout = 30
retry = 10
wrapuptime = 30
autofill = yes
autopause = no
maxlen = 0
joinempty = yes
announce-frequency = 0
periodic-announce-frequency = 15
announce-holdtime = no
periodic-announce = message_one_moment_please
reportholdtime = yes
ringinuse = no
memberdelay = 1
member => Sip/201
member => Sip/202
member => Sip/203
member => Sip/204
member => Sip/205
So, what does all that stuff mean? Well, here we go:
musicclass: this is the on hold music class used and contains the settings for the played music. Mine is called MOHMAIN
strategy: this is the ring strategy used. I chose the ringall, but there are more choices you can make here, eg:
- ringall – ring all available channels unil one answers
- roundrobin – take turns ringing each available interface
- leastrecent – ring interface which was least recently called by this queue
- fewestcalls – ring the one with the fewest calls from this queue
- random – ring a random interface
- rrmemory – roundrobin with memory, remember where left off last ring pass
servicelevel: only used for reporting, see how many calls got answered within the service-level
timeout: how long the phone rings before it is a timeout, in other words: the amount of seconds to keep ringing
retry: the amount of seconds before we give it another go
wrapuptime: the amount of seconds the called agent will not get another call to give them time to “wrap up”
autofill: this has to do with old behavior, just set it to yes
autopause: pauses a station if it does not answer
maxlen: maximum callers waiting in the queue, set to 0 for unlimited
joinempty: this has 3 settings, eg:
- yes: callers can join a queue with no members or only unavailable members
- no: callers cannot join a queue with no members
- strict: callers cannot join a queue with no members or only unavailable members
announce-frequency: how often to announce queue position and/or estimated holdtime to caller (0=off)
periodic-announce-frequency: number of seconds when to make a periodic announce
announce-holdtime: yes|no|once to caller
periodic-announce: sound-file to play for periodic announce
reportholdtime: report the hold-time of the caller to the callee. I find this useful. Agents can prepare for customers who have been waiting way to long and probably will be pissed.
ringinuse: send calls to “in-use” stations (only available on SIP channels)
memberdelay: the delay before a caller gets set trough to the callee after pick-up
member: members of this queue, which in this case, are the phones of the service division.
If the call does not get picked up within the 30 seconds, the call is thrown out of the queue and goes to the VM section, since that is the next step in extension 666706. The VM section looks something like this:
[VM]
exten => 1,1,Answer
exten => 1,n,Playback(message_voicemail)
exten => 1,n,Goto(85026666666667250,1)
exten => 1,n,Hangup
exten => _85026666666667.,1,Wait(1)
exten => _85026666666667.,2,Voicemail(${EXTEN:14}|s)
exten => _85026666666667.,3,Playback(message_thankyou)
exten => _85026666666667.,4,Hangup
exten => i,1,Playback(message_invalid)
exten => i,n,Goto(1)
exten => i,n,Hangup()
exten => 2,1,Background(message_you_can_wait_or_do_voicemail)
exten => 2,n,WaitExten(1)
exten => t,1,Answer
exten => t,n,Queue(WITHVM||||3600)
exten => t,n,Hangup()
Ok, so the call goes to extension 2 in the VM section. This plays a message that the caller can wait, or leave a voicemail. A caller has to press 1 to leave a voicemail, which takes him to extension 1. This routes the caller to extension 85026666666667250 where he/she can leave a voicemail. This is just an extension number I use, were 250 is the voice-mailbox number. If the caller does not make his/her choice in 1 seconds, the caller goes to the timeout extension (t), which puts it in the queue WITHVM for an hour. If nobody answered the phone within an hour, there really is something wrong in this organisation, so guess that will work out ok… Ok, queue WITHVM looks something like this:
[WITHVM]
musicclass = MOHMAIN
strategy = ringall
servicelevel = 60
timeout = 30
retry = 10
wrapuptime = 30
autofill = yes
autopause = no
maxlen = 0
joinempty = yes
announce-frequency = 0
periodic-announce-frequency = 30
announce-holdtime = no
periodic-announce = periodic_announce_message
reportholdtime = yes
ringinuse = no
context = VM
memberdelay = 1
member => Sip/201
member => Sip/202
member => Sip/203
member => Sip/204
member => Sip/205
member => Sip/101
member => Sip/102
member => Sip/103
member => Sip/104
member => Sip/105
member => Sip/106
Now, this looks almost the same as queue SD, with the difference the administration phones are members of this queue as well, so their phones will also ring! A context is also added: VM. This means, that if this queue is left, because somebody pressed a digit, it goes to the VM section, where a extension 1 will take the caller to the voicemail.
This is more or less how I fixed it for this office, The administration works almost the same, except it uses queue ADM, where only the administration stations are linked and goes to the same WITHVM queue after the 30 seconds time-out. So, this is just my way of implementing this. If anybody knows any better/cooler/faster ways of implementing this stuff, please let me know. Always eager to learn!
If you want more info on queues, take a look here, here or here.

