Friday, December 16, 2011

Dialplan that will act as a plug-in replacement for AgentCallbackLogin

This is a sample dialplan that will act as a plug-in replacement for AgentCallbackLogin

for Asterisk 1.6's.

 

It offers the following features:

- Single log-on and log-off, managing queue/agent associations centrally

- Agent pause (with pause reason) and unpause

- Managed device state - the queue will not try calling members that are busy

  on other queues or because of other calls

- Tracking of the current hot-desk extension

- Fully compatible with QueueMetrics

- Very compact and easy to expand

 

It requires Asterisk 1.6.1 or newer to run.

 

SETTING UP

----------

 

First, make sure that the extension that you plan to use in sip.conf have

 

                callconter=yes

                busylevel=1

 

so that when one call is being made or received, the telephone state is BUSY.

 

 

Then define your queues in queues.conf (see file here for an example configuration).

For this example we define two queues aclled "q1" and "q2".

 

We leave the file agents.conf completely alone (agent/queue associations are managed

in the dialplan).

 

Import the file "agent16_queuemetrics.conf" in the main extension.conf file and create

"hooks" that your agents will dial (see examples in the extensions.conf file included).

 

Edit "agent16_queuemetrics.conf" to define which agents work on which queues (see below).

 

Included hooks:

- 820 -> Agent login. It will ask you the agent code and the current extension (as in SIP/ext)

- 821 -> Agent log off. It will ask you the current agent number.

- 823 -> Agent pause. It will autodetect the current agent based on the extension and will

         ask you for a pause code. Enter # if none.

- 824 -> Agent unpause. It will autodetect the current agent.

 

Then at 827/828 you see an example of routing calls to each queue. Set up queues as you best

see fir in your dialplan.

 

Enjoy!

 

DEFINING WHICH AGENTS WORK ON WHICH QUEUES

------------------------------------------

 

Edit the file agent16_queuemetrics.conf where it says:

 

[macro-xagents-allqueues]

....

exten => s,n,Macro(xagents-associate,${ARG1},${ARG2},${ARG3},q1,100:101:103:105)

....

 

As you can see, here we say that for "q1" we have agents 100, 101, 103 and 105.

You must separate agents using a semicolon.

Add a line for each queue that you have defined in your dialplan.

 

 

 

SETTING UP QUEUEMETRICS

-----------------------

QueueMetrics requires no special setup:

1. make sure that default.rewriteLocalChannel=true (this should be the current default anyway)

2. manually assign agents to the queues

 

++++++++++++++++++++++++++++++++++++++++++++

QUEUS.CONF

++++++++++++++++++++++++++++++++++++++++++++

 

[general]

persistentmembers = yes

keepstats = no

autofill = yes

monitor-type = MixMonitor

shared_lastcall=no

 

 

[q1]

music=default

strategy=rrmemory

eventwhencalled=no

timeout=15

retry=1

wrapuptime=0

maxlen = 0

announce-frequency = 0

announce-holdtime = no

autopause=no

autofill=yes

joinempty=yes

 

[q2]

music=default

strategy=rrmemory

eventwhencalled=no

timeout=15

retry=1

wrapuptime=0

maxlen=0

announce-frequency = 0

announce-holdtime=no

autopause=no

autofill=yes

joinempty=yes

 

 

 

++++++++++++++++++++++++++++++++++++++++++++

SIP.CONF

++++++++++++++++++++++++++++++++++++++++++++

 

[tpl_grandstream](!)                ; a template

      dtmfmode=rfc2833

      context=from-internal

      type=friend

      disallow=all

      allow=gsm

      qualify=yes

      host=dynamic

 

 

[999](tpl_grandstream)

  secret=999

  callcounter=yes                  ; Enable call counter

  busylevel=1            

 

 

++++++++++++++++++++++++++++++++++++++++++++

agents16_queuemetrics.conf

++++++++++++++++++++++++++++++++++++++++++++

 

 

[xagents]

exten => _.,1,Set(realchan=${DB(Xagent/${EXTEN})})

exten => _.,n,NoOP("Trying Xagent/${EXTEN} as ${realchan}")

exten => _.,n,Dial(${realchan},60,tT)

exten => h,1,NoOp

 

 

 

[macro-xagents-associate]

;

; ARG1 : operation: ADD or REM

; ARG2 : Agent ID

, ARG3 : Device to be used as state for agent ID

; ARG4 : queue name

, ARG5 : queue members, as 100:103:104

;

exten => s,1,NoOp("Macro2")

exten => s,n,Set(queue=${ARG4})

exten => s,n,Set(agentlist=:${ARG5}:)

exten => s,n,Set(agent=${ARG2})

exten => s,n,Set(oper=${ARG1})

exten => s,n,Set(devstate=${ARG3})

exten => s,n,Set(fnd=${REGEX(":${agent}:" ${agentlist})})

exten => s,n,GotoIf(${fnd}?found)

exten => s,n,NoOP( "NOTFOUND" )

exten => s,n,MacroExit

 

exten => s,n(found),Goto(op-${oper})

exten => s,n,MacroExit

 

exten => s,n(op-ADD),AddQueueMember(${queue},Local/${agent}@xagents,,,,${devstate})

exten => s,n,MacroExit

 

exten => s,n(op-REM),RemoveQueueMember(${queue},Local/${agent}@xagents)

exten => s,n,MacroExit

 

 

 

[macro-xagents-allqueues]

; AGR1: operation: ADD or REM

; ARG2: Agent ID

; ARG3: Device to be used as a source of state

exten => s,1,NoOP("")

exten => s,n,Macro(xagents-associate,${ARG1},${ARG2},${ARG3},q1,100:101:103:105)

exten => s,n,Macro(xagents-associate,${ARG1},${ARG2},${ARG3},q2,101:100:103:105)

exten => s,n,Macro(xagents-associate,${ARG1},${ARG2},${ARG3},q3,108:101:103:105)

exten => s,n,MacroExit

 

 

 

 

[xagents-logon]

exten => s,1,Answer

exten => s,n,Read(agent,agent-user)

exten => s,n,Read(phone,agent-newlocation)

exten => s,n,Set(DB(Xagent/${agent})=SIP/${phone})

exten => s,n,Set(DB(Xagent_byphone/${phone})=${agent})

exten => s,n,QueueLog(NONE,${UNIQUEID},Local/${agent}@xagents,AGENTCALLBACKLOGIN,${phone})

exten => s,n,Macro(xagents-allqueues,ADD,${agent},SIP/${phone})

exten => s,n,Playback(agent-loginok)

exten => s,n,Hangup

 

[xagents-logoff]

exten => s,1,Answer

exten => s,n,Read(agent,agent-user)

exten => s,n,Set(chan=${DB(Xagent/${agent})})

exten => s,n,Set(DB(Xagent/${agent})=)

exten => s,n,Macro(xagents-allqueues,REM,${agent},-)

exten => s,n,QueueLog(NONE,${UNIQUEID},Local/${agent}@xagents,AGENTCALLBACKLOGOFF,)

exten => s,n,Playback(agent-loggedoff)

exten => s,n,Hangup

 

[xagents-pause]

exten => s,1,Answer

exten => s,n,Set(agent=${DB(Xagent_byphone/${CALLERID(num)}})

exten => s,n,Read(code,agent-user)

exten => s,n,PauseQueueMember(,Local/${agent}@xagents,,${code})

exten => s,n,QueueLog(NONE,${UNIQUEID},Local/${agent}@xagents,PAUSEREASON,${code})

exten => s,n,Hangup

 

[xagents-unpause]

exten => s,1,Answer

exten => s,n,Set(agent=${DB(Xagent_byphone/${CALLERID(num)}})

exten => s,n,UnpauseQueueMember(,Local/${agent}@xagents)

exten => s,n,Hangup

 

++++++++++++++++++++++++++++++++++++++++++++

EXTENSIONS.CONF

++++++++++++++++++++++++++++++++++++++++++++

 

 

 

#include "agents16_queuemetrics.conf"

 

 

 

[from-internal]

 

exten => 820,1,Dial(Local/s@xagents-logon)

 

exten => 821,1,Dial(Local/s@xagents-logoff)

 

exten => 823,1,Dial(Local/s@xagents-pause)

 

exten => 824,1,Dial(Local/s@xagents-unpause)

 

exten => 827,1,Answer

exten => 827,n,Queue(q1)

 

exten => 828,1,Answer

exten => 828,n,Queue(q2)

 

 

----------------------

 

YOU ARE DONE!!!

 

 

 

 

 

 

 

 

 

 

 

 

 

1 comment:


  1. Thanks for that awesome post, it helped a lot. The only thing that is missing is a parenthesis in the contexts of [xagents-unpause] and [xagents-pause] in the following line :
    s,n,Set(agent=${DB(Xagent_byphone/${CALLERID(num)}})

    ReplyDelete