20. Configuring Asterisk for QueueMetrics

QueueMetrics is designed to analyze queue_log data provided by any Asterisk installation; the following guidelines will help you to make the most out of it.

20.1. Configuring queues to report exit status

In the following example:

  • all calls are monitored, i.e. saved to disk;
  • if after 60 seconds on the queue the call is unanswered, the call is routed to voicemail and this event is reported correctly by QM;
  • there are two levels of agents: agents 302 and 303 will answer the queue (level 1); only if none of them is available the call is routed to agent 301 (level 2). If nobody is available, the queue keeps trying until timeout is reached.
  • Agents can transfer the call to other extensions by pressing the "#" key;
  • Agents terminate the current call by pressing the "*" key.

Extensions.conf

[q-my-sample]
; ...queue description.....
exten => s,1,SetVar(MONITOR_FILENAME=/var/spool/asterisk/QSAMPLE-${UNIQUEID})
exten => s,2,Queue(q-sample|nt|||60)
exten => s,3,Playback(voicemail-invitation)
exten => s,4,VoiceMail,s2001

Queues.conf

[q-sample]
music = default
announce = q-sample-announce
strategy = roundrobin
timeout = 60
retry = 5
maxlen = 0
announce-frequency = 0
announce-holdtime = no
monitor-format = wav
monitor-join = yes
queue-youarenext = silence
queue-thankyou = q-sample-thankyou
member=>Agent/302,0
member=>Agent/303,0
member=>Agent/301,1

Make sure that you do not forget the explicit timeout when calling the Queue() command from extensions.conf, or queue timeouts will not be logged by Asterisk and therefore not reported by QM. A patch that corrects this Asterisk behaviour can be found at http://bugs.digium.com/view.php?id=5422 .

20.2. Configuring URLs to be launched by the agent real-time page

The URL should be embedded in the Queue() command as prescribed by Asterisk:

exten => s,7, Queue(myqueue|nt|http://mysite/app?uid=${UNIQUEID}&clid=${CALLERID}||60)

This command launches the queue "myqueue" and launches the webapp located http://site/app passing the following parametrs:

  1. uid is the Asterisk internal unique call id
  2. clid is the Caller*ID for the current call

The URL will appear on a clickable link on the Agent’s page.

If you set the property realtime.agent_autoopenurl to true, whenever the Agent’s page is reloaded, the most recent unopened URL is launched automatically.

20.3. Listening to recorded calls using QM

  • Make sure it is legal This is not strictly a QM issue, but before attempting to record all calls on a queue, you should consult a lawyer to make sure it is legal in your country. It would be probably fair enough to tell your operators their calls are being recorded and to add a voice message telling the customers their call will be recorded.
  • Tell Asterisk to record all calls To record all calls add something like this to extensions.conf:

    exten => s,1,SetVar(MONITOR_FILENAME=/var/spool/asterisk
         /q/QSAMPLE-${UNIQUEID})
    exten => s,2,Queue(q-sample|nt|||60)

    This way all sound files are stored under /var/spool/asterisk/q/ with the name of the queue (QSAMPLE) followed by the call id.

  • Tell QueueMetrics where to look for the calls You should set up the WEB-INF/configuration.property file in QM like this:

    default.monitored_calls=/var/spool/asterisk/q/

    When looking for the recording of a call, QM will explore all files contained in /var/spool/asterisk/q/ and any directories below for a file name containing the right call ID. It might find more than one file name and will display all of them. It is possible that sometimes Asterisk fails at mixing together the two files (Asterisk records separate files for the caller and the agent, and then tries to mix them together at the end of the call) so you will find two files named -in and -out instead. The search behaviour can be customized -see Section 19, “Listening to calls using Pluggable Modules (PM)”.

  • Tell QueueMetrics you have the right to listen to the calls Any user willing to listen to calls must hold the key CALLMONITOR. This is to make sure that only authorized personnel can listen to recorded calls. If you do not have this key, no sound files will be shown.
  • Make sure QueueMetrics has the right to read saved calls You should make sure that the process running QM (i.e. the servlet container, might be Tomcat, Jetty, or something else depending on your setup) has the rights to access the files where recorded calls are stored.<br> If using a separate web server, it should not be able to access those files directly, as QM will pipe out files only after enforcing security checks.
  • Debug tip: see which files QM sees There is a hidden transaction in QM made to debug call listening. To launch it, logon as an administrator and type the transaction "qm_show_files.do" in the URL bar instead of the page name. You will be lead to a page showing the filenames QM can read from the hard disk, whether the current user has the CALLMONITOR key and the search path as defined in default.monitored_calls.

20.4. Using AddQueueMember for dynamic agents

AddQueueMember is a command that lets you add dynamic agents to a queue. Its main advantage is that you can add channels, i.e. terminals, so you’ll have most of the advantages of agents without the performance and stability problems that the agents module may cost in very large systems.

Its disadvantage is that it does not log the agent login/logoff to the queue_log, and so programs that analyze the queue log data like QueueMetrics will not see agents logging on and off. This is a major organizational problem in a real-world call center, where tracking agent logons and logoffs is vital to the smooth running of the operations.

The answer is to add a fake queue_log data for each logon and logoff. For QM, it is important to avoid multiple logoff lines and to compute online permanence with logoffs.

To do the adding, you dial 422XX, where XX is your local extension; the same happens with 423XX to be logged off.

; Add Member - 422

exten => _422XX,1,Answer
exten => _422XX,2,AddQueueMember(my-queue,SIP/${EXTEN:3})
exten => _422XX,3,System( echo "${EPOCH}|${UNIQUEID}|NONE|SIP/${EXTEN:3} \
                  |AGENTLOGIN|-" >> /var/log/asterisk/queue_log )
exten => _422XX,4,DBput(dynlogin/log_Agent-${EXTEN:3}=${EPOCH})
exten => _422XX,5,Hangup

; Remove Member - 423
exten => _423XX,1,Answer
exten => _423XX,2,RemoveQueueMember(my-queue,SIP/${EXTEN:3})
exten => _423XX,3,DBget(ORGEPOCH=dynlogin/log_Agent-${EXTEN:3})
exten => _423XX,4,Set(RV=$[${EPOCH} - ${ORGEPOCH}])
exten => _423XX,5,GotoIf($["${RV}" = "0"]?8:6)
exten => _423XX,6,System( echo "${EPOCH}|${UNIQUEID}|NONE|SIP/${EXTEN:3}|\
                  AGENTLOGOFF|-|${RV}" >> /var/log/asterisk/queue_log )
exten => _423XX,7,DBdel(dynlogin/log_Agent-${EXTEN:3})
exten => _423XX,8,Hangup

With this setup, we verified that the queue_log can be analyzed by QueueMetrics and the dynamic agent shows up fine (albeit with the name of a terminal, like SIP/23, instead of the usual Agent/23 string, but you can modify it in QM itself).

This setup might even be used in a call center where agents are not actually used but queues connect straight to terminals to "fake" agent logon/logoff, in order to have such data available for reporting.

20.5. Defining outbound queues (campaigns)

Standard Asterisk queues are, by definition, inbound queues; they accept a number of incoming calls, let them wait in line and distribute them to various agents based on the queue logic.

To make it possible to analyze outbound calls with QM, we added the concept of a "campaign" or "outbound queue", that is a set of calls made by different agents that are working for the same purpouse. Of course there is no such thing as an outbound queue in Asterisk, so we have to run a special piece of dialplan or an AGI script to produce the same information on queue_log for outbound calls as it is automatically produced for inbound queues.

As this only regards the actual Dial(…) statement that Asterisk runs, it is possible to have different sources of numbers to be dialled by agents on outbound queues; they might enter the number on their keypad, or use the telephone, launch them from the Agent’s page or maybe use a predictive dialler for the task. QueueMetrics does not care, as long as the correct events are logged.

20.5.1. Placing outbound calls

If you run Asterisk 1.4 or newer and want to place outbound calls, you use an example script supplied within the extensions_queuemetrics.conf; it should be imported by the main Asterisk configuration.

After this, if you place a call directed to Local/XXXYYYYYYY@queuedial, where XXX is the code for the campaign and YYYYYY…. the number to be dialled, a call will be created and logged as Agent/ZZZ, where ZZZ is the caller-id of the extension placing the call.

You may want to tweak the following supplied piece of dialplan to adapt it to your needs:

[queuedial]
exten => _XXX.,1,Set(QDIALER_QUEUE=q-${EXTEN:0:3})
exten => _XXX.,n,Set(QDIALER_NUMBER=${EXTEN:3})
exten => _XXX.,n,Set(QDIALER_AGENT=Agent/${CALLERID(num)})
exten => _XXX.,n,Set(QDIALER_CHANNEL=SIP/${QDIALER_NUMBER})
exten => _XXX.,n,Set(QueueName=${QDIALER_QUEUE})
exten => _XXX.,n,MixMonitor(Q-${QDIALER_QUEUE}-${UNIQUEID}.WAV|b|)
exten => _XXX.,n,Goto(qm-queuedial,s,1)

You can/should modify the following variable definitions:

  • QDIALER_QUEUE is taken from the first three digits. If you have ony one campaign system-wide, you may want to hardcode this value so the user needs not input it.
  • QDIALER_AGENT is the Agent code that the call will be logged under. The simplest approach is just to use the extension’s caller-id, under the hypotesis that Agent/123 works at SIP/123. You may also look up under Asterisk who is the agent working at a given extension - an example is given in the [queuedial-loggedon] context in the same file.
  • QDIALER_CHANNEL is the channel that you have to dial to call out. Will likely be something
  • You can comment out the MixMonitor line if you don’t need call recordings.

Please note that:

  • The outbound queue should not be defined in Asterisk, but must be in QueueMetrics.
  • When running a QueueMetrics analysis, some values are their own mirrors: like, the Caller*ID of an incoming call is the number dialled of an outbound queue, while the Agent field is the caller.
  • It is possible to do live listening of outgoing calls (see Section 20.6, “Enabling ACD call attempts recording on Asterisk 1.0 and 1.2”).

20.5.2. Placing outbound calls through the AGI script

This section applies only if you run a version of Asterisk 1.0 or 1.2; for 1.4 or newer, please use the dialplan logic supplied in the file extensions_queuemetrics.conf.

The AGI script to be used instead of the Dial(…) command is available in the standard QM distribution and can be used in the following way:

exten => xxx,1,DeadAGI(queueDial.agi|Number|DialString|QueueName|Agent)

The following parameter have to be passed by dialplan logic:

  • Number: the number you are trying to dial. Needed for correct logging only.
  • DialString: the actual Asterisk dial string, like SIP/34, or maybe IAX2/usr:pass@iax.server/8885551234. If you need additional parameters in the Dial() command, modify the AGI script manually.
  • QueueName: the outbound queue to be used for accounting. Must be defined in QueueMetrics and must not exist in Asterisk!
  • Agent: the agent placing the call, e.g. Agent/123

A working example might be the following:

exten => 426,1,DeadAGI(queueDial.agi|34|SIP/34|queue-out-1|Agent/101)

The terminal SIP/34 is dialled and the resulting events are logged as if generated by Agent/101 working on queue-out-1.

Please note:

  • The outbound queue should not be defined in Asterisk, but must be in QueueMetrics.
  • When running a QueueMetrics analysis, some values are their own mirrors: like, the Caller*ID of an incoming call is the number dialled of an outbound queue.
  • When monitoring calls in real-time, it is impossible to distinguish calls waiting to be answered from calls in conversation. This is an Asterisk limitation, as the generated events are not provided in real-time. Those values are anyway correct in the reports.
  • Extensive debugging output is available at /var/log/asterisk/agi-log.txt
  • It is possible to do live listening of outgoing calls (see Section 20.6, “Enabling ACD call attempts recording on Asterisk 1.0 and 1.2”).

20.6. Enabling ACD call attempts recording on Asterisk 1.0 and 1.2

To get the AGENTATTEMPT code to work, it is necessary to patch the Asterisk module called app_queue.c in order to track down the required information. In order to perform this task, you must be confident with general Unix project patching and recompiling. It is advisable that Asterisk be shut down before applying the patch.

In order to apply the patch, just copy the file app_queue_agentattempt.patch found under WEB-INF/README/ to the apps/ directory of your Asterisk project, and then issue the following statement:

patch -p0 < app_queue_agentattempt.patch

As long as you see no errors, the patching process worked successfully. It’s now time to rebuild the app by issuing a general make statement from the main Asterisk directory.

Restart Asterisk and check that the queue system is still working fine.

To see if the patch was correct, try dialling a queue and see that Asterisk writes AGENTATTEMPT records to the queue_log file.

20.7. Enabling ACD call attempts recording on Asterisk 1.4

Asterisk 1.4 is natively able to produce the RINGNOANSWER log entry that servers the same purpose of AGENTATTEMPT, so no patching is necessary.

20.8. Listening to live calls: Unattended Call Monitoring

In order to implement this feature, QueueMetrics follows the following steps:

  • It will try to dial the channel defined in the property callfile.monitoring.channel by passing the local extension. This should make your local phone ring.
  • Once the call is picked-up, it will try to dial 11@queuemetrics (if the call is inbound) or 14@queuemetrics (if the call is outbound) in order to start the ChanSpy() monitoring and will pass along all required variables to match the requested call.

To enable unattended audio monitoring for inbound calls, you’ll have to edit the Asterisk dial-plan in order to include the [queuemetrics] context.

  • Make sure that the queuemetrics context exists and that the extensions 10, 11 and 14 are defined for it. See Appendix C, The [queuemetrics] context
  • Make sure that the channel defined in the property callfile.monitoring.channel is set to Local/$EM@from-internal/n (in this example, your telephone would be known by Asterisk as something like 105@from-intenal).
  • Make sure that the extension/context are set to 11/queuemetrics ( the unattended audio monitoring endpoint).
  • Make sure that the callfile.dir property points to a valid callfile directory, and that will be writable by QueueMetrics. As a (now preferred) alternative you may enter a Monitor URI in the format tcp:user:pass@server; in this case QM will not attempt to generate a call-file but will use the Manager command to create an equivalent call instead.
  • Make sure the callfile.monitoring.enabled configuration property is set to true
  • Make sure your users hold the MON_AUDIO key
  • Important: make sure that each agent will have their local extension set in QueueMetrics; usually entering "-" will be enough. If this is not set, the icon will not appear.
  • Now, when you click on the icon, a callfile will be generated and call snooping will start.

To enable unattended call monitoring for outgoing calls as well, you’ll have to set the piece of dial-plan referenced by the callfile.outmonitoring… properties.

Outgoing calls placed though queueDial.agi will usually be listened to by attaching to the local SIP/XXX or Local/XXX channel of the calling agent and not to the standard Agent/XXX channel used for inbound, so a different piece of dial-plan will be used. Note that in order for QueueMetrics to reference the outgoing calls, you must tell it that queue direction is Outgoing.

See also Appendix C, The [queuemetrics] context for an example of implementing Asterisk code for inbound and outbound call monitoring.

It is possible to use different PMs to handle different live audio - see Section 19, “Listening to calls using Pluggable Modules (PM)”.

20.9. Enabling VNC Monitoring

To enable VNC monitoring you will first need a VNC server that is running on each client’s machine and that will serve the current layout.

You will also have to create a web page with a VNC client that may accept a VNC URL and show a VNC client (there are a number of Java-based VNC clients that can be displayed as an applet).

Configure the VNC URL as something like: http://myserver/vncpage.php?ip=192.168.3.17

Where the PHP page will connect the VNC applet to the server located on address 192.168.3.17

Make sure that your users hold the MON_VNC key in order to be able to access this feature.

As an alternative, we have some clients that use a simpler setup with each machine having their own copy of UltraVNC - http://ultravnc.sourceforge.net/ - and each machine running a web server with the locally-configured Java viewer. The VNC url is then the address of the local machine; when a person connects to it, s/he is asked for a password and then the screen is displayed through a Java applet. They report this setup to be very simple and working very well.

20.10. Enabling Agent’s page actions

In order to enable actions on the Agent’s page:

  • Check that all actions are enabled in the properties, this means that callfile.actionname.enabled=true
  • Check that a Manager API is configured correctly for the server
  • Check that the dialplan on the server contains the appropriate commands for this action. A sample [queuemetrics] context you can include easily within a standard dialplan using call-back agents is provided as a reference.

20.11. Enabling XML-RPC call listening and streaming

It is possible to run remote audio monitoring of both completed and ongoing calls using third party monitoring tools, for example Orecx. As QueueMetrics has no way of knowing the internal details of such applications, we made it possible to call an external XML-RPC server (we offer a stub written in PHP, but it can be written in any language and reside on any server, as long as it uses an XML-RPC library) that will basically pass back to QM the URLs required to perform the required task.

In order to enable this, we first tell QueueMetrics to use the XML-RPC Pluggable Modules for both call listening and streaming:

audio.server=it.loway.app.queuemetrics.callListen.listeners.ClassicXmlRpcRecordings
audio.liveserver=it.loway.app.queuemetrics.callListen.RTlisteners.ClassicXmlRpcListenerRT

The XML-RPC server will be set by setting its URL in a configuration property, like for example:

default.audioRpcServer=http://127.0.0.1/xmlrpc/xmlrpc_audio_server.php

The server must implements three XML-RPC calls called:

  • QMAudio.findStoredFile This function is used to find and play back a stored audio file, by returning the URL of a player that will play it or the audio file itself. This function has in input the following parameters:

    • $ServerID: ignore for now
    • $AsteriskID: The Asterisk call-id, as written in the second field of queue_log
    • $QMUserID: the ID of the current QM user
    • $QMUserName: the name of the current QM user

    and it must return the following values:

    • $FILE_FOUND : If the file was found or not (maybe it was not recorded)
    • $FILE_LISTEN_URL . an URL to open up a player for this call
    • $FILE_LENGTH : size of the audio file (shown as passed)
    • $FILE_ENCODING : encoding ofthe audio file (eg mp3)
    • $FILE_DURATION : duration of the audio file
  • QMAudio.listenOngoingCall This function is used to query for an ongoing inbound call. If found, QM will launch a new popup to open the player which URL is returned. This function has in input the following parameters:

    • $ServerID: ignore for now
    • $AsteriskID: The asterisk call-id, as written in the second field of queue_log
    • $Agent: the name of the agent being monitored e.g. "agent/101"
    • $QMUserID: the ID of the current QM user
    • $QMUserName: the name of the current QM user

    and it must return the following values:

    • $CALL_FOUND: If the call was found or not
    • $CALL_LISTEN_URL : the URL of the player
    • $CALL_POPUP_WIDTH, $CALL_POPUP_HEIGHT: width and height of the popup being opened. Currently a double popup is opened.
  • QMAudio.listenOngoingCallOutgoing This function is used to query for an ongoing outgoing call. If found, QM will launch a new popup to open the player which URL is returned. The parameters are the same as for QMAudio.listenOngoingCall.

To make implementer’s life easier, we provide a simple XML-RPC stub server under WEB-INF/mysql-utils/xml-rpc that can be used as a starting point: no need to handle the XML-RPC stuff, just change the results of the two supplied functions and data goes back to QueueMetrics.

20.12. Enabling call outcomes

A call tracking code is a code to be input by a user telling the status of a call, be it inbound or outbound. This status code is a string (though we suggest to use numeric status codes, in order to make it easy to input them using a telephone keypad) and may be input either when the call is ongoing or after a short while from its end.

The queue_log entry looks like the following one:

1234|1231.1|NONE|Agent/1234|CALLSTATUS|21

This will set the CALLSTATUS to "21" for the call which Call-ID is "1231.1" it may be an open call or it may be terminated by no longer than 30 minutes.

If it is not possible to force the Call-ID, a second version of the verb is available:

1234|2222.3|NONE|Agent/1234|CALLSTATUS|21|1231.1

This has exactly the same meaning; the second Call-ID passed as a parameter will override the original one.

If you prefer, you may log the queue name instead of "NONE" field shown above; in any case QM will ignore this piece of information.

The following rules apply:

  • A CALLSTATUS row must be set after the call is started or it’s terminated; in any other case it’s simply discarded
  • There may be multiple CALLSTATUS rows for the same Call-ID; in this case, the last one overrides pervious codes.
  • The CALLSTATUS must be passed within 30 minutes from the end of a call.
  • CALLSTATUS for a non-existent Call-ID will be discarded
  • Even if a queue reset is detected, CALLSTATUS for existing Call-ID are applied

The agent may either be a fill "Agent/xxx" string or the valid name of an Asterisk channel. It is acceptable to use a generic channel name instead of the specific one, i.e. "SIP/123" and "SIP/123-abcd" are equivalent.

The sample [queuemetrics] context that comes with QueueMetrics can be used as a starting point to output such data.

20.13. Enabling pause codes

A pause reason code is a code to be input by a user telling the reason why a pause was started. It should be ideally input together with the decision to go on pause, though QueueMetrics will accept the code and will attach to the correct pause even if the pause is resumed, as long as no other pause is started. The reason code is a string - though we suggest to use numeric status codes, in order to make it easy to input it using a standard telephone keypad.

The format is the following one:

1234|1231.1|NONE|Agent/1234|PAUSEREASON|21

This will set the pause reason to "21" for the pause that is either going on or has just finished. If the code is input after over 30 minutes from the end of the last pause, it is discarded.

The following rules apply:

  • A PAUSEREASON row must be set after the agent’s pause is started or it’s terminated; in any other case it’s simply discarded
  • There may be multiple PAUSEREASON rows for the same pause; in this case, the last one overrides pervious codes.
  • The PAUSEREASON must be passed within 30 minutes from the end of a pause; otherwise it will be silently discarded.
  • PAUSEREASON for a non-existent agent pause will be discarded.
  • If a pause extends over multiple call sessions, the PAUSEREASON will be correctly set only for sessions terminating after the PAUSEREASON has been set.
  • Even if a queue reset is detected, PAUSEREASON for existing pause are applied
  • The agent may either be a fill "Agent/xxx" string or the valid name of an Asterisk channel. It is acceptable to use a generic channel name instead of the specific one, i.e. "SIP/123" and "SIP/123-abcd" are equivalent.

The sample [queuemetrics] context that comes with QueueMetrics can be used as a starting point to output such data.

20.14. Closing ongoing calls

It sometimes happens that Asterisk will not log the call termination records for a call; as QM is based on the logged events, a call missing the call closure log will linger on forever in the realtime screen (or at least the maximum time allowed by the …) and will appear as Ongoing or Not answered yet in the historical reports.

Since version 1.4.5 of QueueMetrics, it is possible to manually close a call from either the historical reports or the real-time screen. In order for this to work:

  • You must be running with MySQL storage or clustered storage
  • Your user must own key CLOSECALLS

When this is done, open calls on the reports will show a red scissor icon:

./Pictures/image201.jpg

And the same will happen for the real-time screen:

./Pictures/image203.jpg

By clicking on that icon, a popup will appear that will ask for the length the call should be closed to. This length refers to the wait duration if the call is not answered and the conversation time if the call is answered. It is possible to change that from the default 5 seconds by setting a configuration property.

If the call has already been closed in the meantime, or you’re doing this operation twice, QM will report that the call has already been closed.

[Important]Important

if you do this on calls that are still ongoing, you will risk having duplicate data on the report. So don’t use this feature unless you know what you are doing. The required security key must be manually assigned only to trusted users.

20.15. Tracking DNIS and IVR information

In order to keep track of DNIS and IVR information that relates to each call, you have to write special records on the ’queue_log’ file that QueueMetrics parses.

This is very easy to do, e.g. imagine you have a piece of dialplan where you are going to call queue ’q-sample’ and you have the DNIS code in the ’MYDNIS’ dialplan variable, and the sequence of keys pressed as ’MYIVR’:

exten => s,n,........
exten => s,n,QueueLog(q-sample,${UNIQUEID},NONE,INFO,DID|${MYDNIS})
exten => s,n,QueueLog(q-sample,${UNIQUEID},NONE,INFO,IVR|${MYIVR})
exten => s,n,Queue(q-sample|nt|||60)
exten => s,n,........

There is no predefined format for DNIS and IVR information; QueueMetrics just handles it as free-form text strings.

You can output only one record, or both, or none, depending on what you need.

20.16. Enabling Hotdesking in the agent page

Since the demise of AgentCallBackLogin, it has been hard to do "hotdesking" in Asterisk - that is, having agents that work on queues because of their competences and not because they are sitting at a given extension.

With QueueMetrics 1.6.1, hotdesking is very easy to implement and it has no downsides, because:

  • it is completely transparent to Asterisk
  • you can emulate the single-sign-on behavior of AgentCallBack and still have the flexibility of adding/removing members as needed on a queue by queue basis.
  • call recordings, agent monitoring and all other functionalities are unaffected

Requirements:

  • QueueMetrics 1.6.1 or newer
  • MySQL storage model
  • Asterisk 1.4 or 1.6

20.16.1. How it works

Set the following properties as follows:

default.queue_log_file=sql:P001         <-- change as needed
callfile.dir=tcp:admin:amp111@127.0.0.1 <-- change as needed
default.rewriteLocalChannels=true
callfile.agentlogin.enabled=false
callfile.agentlogoff.enabled=false
default.hotdesking=86400

Make sure that ’extensions_queuemetrics.conf’ is loaded in the Asterisk dialplan (you need to use the extensions_queuemetrics file that comes with QM 1.6.1 or newer).

This setup means that we access the queue_log file through the database, connect to Asterisk over AMI to send commands, rewrite agent codes, do not use Agentcallback-style agents and enable hotdesking.

Now we use a piece of dialplan like this one when we associate an agent to a queue:

Imagine we have AGENTCODE set to 200 (the agent’s login code) and AGENT_EXT set to 123 (thi sis the SIP extension code):

....
exten => 35,3,QueueLog(NONE,${UNIQUEID},Agent/${AGENTCODE},HOTDESK,SIP/${AGENT_EXT})
exten => 35,4,AddQueueMember(myqueue,SIP/${AGENT_EXT})
....

This logs on Agent/200 to queue "myqueue", tracking him as SIP/123. Note that from the point of view of Asterisk, we only see that extension 123 is made a member of the queue.

When you logoff, pause, unpause agents, you always work at the SIP level (the actual extension that is linked to the queue) so there is no need to change anything.

If you use the QueueMetrics Agent’s page, you can do logon/logoffs/pauses from the buttons by the top of the page; this lets you add an agent to all queues at once, like you used to do with AgentCallBackLogins, and still retain the flexibility to change that at runtime.

20.16.2. Example hotdesking configuration

In the following sections, we sumamrize the changes that have to be made to an existing system to enable hotdesking.

20.16.3. Changes to configuration.properties

Add/change the ’default.hotdesking’ property to 86400. This property enables hotdesking and lets the parse "look back" up to 1 day (change as needed).

default.hotdesking=86400

Add/change the sections below:

callfile.agentpause_ht.enabled=true
callfile.agentpause_ht.channel=Local/32@queuemetrics/n
callfile.agentpause_ht.extension=10
callfile.agentpause_ht.context=queuemetrics

callfile.agentunpause_ht.enabled=true
callfile.agentunpause_ht.channel=Local/33@queuemetrics/n
callfile.agentunpause_ht.extension=10
callfile.agentunpause_ht.context=queuemetrics

callfile.agentaddmember_ht.enabled=true
callfile.agentaddmember_ht.channel=Local/35@queuemetrics/n
callfile.agentaddmember_ht.extension=10
callfile.agentaddmember_ht.context=queuemetrics

callfile.agentremovemember_ht.enabled=true
callfile.agentremovemember_ht.channel=Local/37@queuemetrics/n
callfile.agentremovemember_ht.extension=10
callfile.agentremovemember_ht.context=queuemetrics

This code specifies the Asterisk extensions that QueueMetrics will call for each button present in the agent live page when hotdesking is enabled.

Change the ’realtime.agent_button_x.channel’ key to the value ’Local/[EM]@from-internal’

This last option is needed only if you use custom agents buttons to dial out extensions and should be repeated for each dial-enabled button. In the code below, a valid example for the button 4 is reported:

realtime.agent_button_4.enabled=true
realtime.agent_button_4.caption=Secretary
realtime.agent_button_4.url=
realtime.agent_button_4.channel=Local/[EM]@from-internal
realtime.agent_button_4.ext=200@queuedial

20.16.4. Changes to extensions_queuemetrics.conf

Here should be defined the Asterisk extensions used by QueueMetrics to perform actions triggered from the agent live page.

Add to this file the code reported below:

; extension 32: agent pause with hotdesking (with pause code)
exten => 32,1,Answer
exten => 32,2,NoOp( "QM: Pausing Agent/${AGENTCODE} at extension SIP/${QM_AGENT_LOGEXT} with pause reason ’${PAUSEREASON}’ made by ’${QM_LOGIN}’ " )
exten => 32,3,PauseQueueMember(,SIP/${QM_AGENT_LOGEXT})
exten => 32,4,System( echo "${EPOCH}|${UNIQUEID}|NONE|Agent/${AGENTCODE}|PAUSEREASON|${PAUSEREASON}" >> /var/log/asterisk/queue_log )
exten => 32,5,Hangup

; extension 33: agent unpause with hotdesking
exten => 33,1,Answer
exten => 33,2,NoOp( "QM: Unpausing Agent/${AGENTCODE} at extension SIP/${QM_AGENT_LOGEXT} made by ’${QM_LOGIN}’ " )
exten => 33,3,UnpauseQueueMember(,SIP/${QM_AGENT_LOGEXT})
exten => 33,4,Hangup

; extension 35: agent addqueuemember with hotdesking (for asterisk v1.4+)
exten => 35,1,Answer
exten => 35,2,NoOp( "QM: AddQueueMember (asterisk v1.4+) Agent/${AGENTCODE} at extension SIP/${QM_AGENT_LOGEXT} on queue ${QUEUENAME} made by ’${QM_LOGIN}’" )
exten => 35,3,Macro(queuelog,${EPOCH},${UNIQUEID},NONE,Agent/${AGENTCODE},HOTDESK,SIP/${QM_AGENT_LOGEXT})
exten => 35,4,AddQueueMember(${QUEUENAME},SIP/${QM_AGENT_LOGEXT})
exten => 35,5,Hangup

; extension 37: agent removequeuemember with hotdesking (for asterisk v1.4+)
exten => 37,1,Answer
exten => 37,2,NoOp( "QM: RemoveQueueMember (asterisk v1.4+) Agent/${AGENTCODE} at extension SIP/${QM_AGENT_LOGEXT} on queue ${QUEUENAME} made by ’${QM_LOGIN}’" )
exten => 37,3,RemoveQueueMember(${QUEUENAME},SIP/${QM_AGENT_LOGEXT})
exten => 37,4,Hangup

Please note that the ’extensions_queuemetrics.conf’ file that ships with 1.6.1 already has these changes embedded.

In order to have the hotdesking working a complete QueueMetrics restart and Asterisk reload should be performed.