最後更新: 2015-08-18
介紹
ACD (Automatic Call Distributor) distributes incoming calls in the order of arrival to the first available agent.
The system answers each call immediately and,
if necessary, holds it in a queue until it can be directed to the next available call center agent.
Balancing the workload among agents ensures that each caller receives prompt and professional service.
Queue a call for a call queue.
In addition to transferring the call, a call may be parked and then picked up by another user.
Queues consist of Incoming calls being placed in the queue
- Members that answer the queue (extensions or users that login as agents)
- A strategy for how to handle the queue and divide calls between members
- Music played while waiting in the queue
- Announcements for members and callers
目錄
- Queue() Usage
- Dialplan Example
- Configure - queues.conf
- CLI
- AMI
- Troubleshoot
- Device State
- Queue Readtime
Queue() Usage
Queue(queuename,[options,[URL,[announceoverride,[timeout,[AGI,[macro,[gosub,[rule,[position]]]]]]]]])
t - Allow the called user to transfer the calling user.
T - Allow the calling user to transfer the call.
x - Allow the called user to write the conversation to disk via MixMonitor.
X - Allow the calling user to write the conversation to disk via MixMonitor.
timeout - defaults to 300 seconds.
that a call will wait in the queue before it is routed to the next priority in the dialplan
AGI - Will setup an AGI script to be executed on the calling party's channel once they are connected to a queue member.
macro - Will run a macro on the called party's channel (the queue member) once the parties are connected.
* This application does not automatically answer and should be preceeded by an application such as
- Answer()
- Ringing()
# The status of the call as a text string
QUEUESTATUS
TIMEOUT
FULL
JOINEMPTY
LEAVEEMPTY
JOINUNAVAIL
LEAVEUNAVAIL
CONTINUE
Dialplan Example
exten => s,1,Answer exten => s,2,SetMusicOnHold(default) exten => s,3,DigitTimeout,5 exten => s,4,ResponseTimeout,10 exten => s,5,Background(welcome) exten => s,6,Queue(tech-queue)
Configure - queues.conf
# multiple call queues
queues.conf
; The first one, is the so called "static" way. For this configuration you do not need the agents.conf file. ; Created a context with the name [test]. In this context we have written the following: member => SIP/operator. Example [general] ; system to store each dynamically logged in agent, from each separate queue, in the Asterisk`s database. ; in case of restarting the Asterisk PBX, the agents will be automatically readded into their recorded queues. persistentmembers = yes ; CDR dstchannel field of a call with an agent name updatecdr = yes [queue_test1] ; will hear for how long the caller has been left on music on hold. reportholdtime=yes ; Set(CHANNEL(musicclass)=whatever) musicclass = default member => Agent/user1 member => Agent/user2 member => Agent/user3 ;context = qoutcon [queue_test2] ; monitor monitor-format=wav ; input / output mixed together in one joint file automatically monitor-join = yes ; ringall, roundrobin, leastrecent, fewestcalls, random, linear strategy = ringall member => Agent/user1 member => Agent/user2 member => Agent/user3
member 的設定
; agent member
member => Agent/8888
; agent group
member => Agent/@1
; interface/user
member => SIP/operator
Queue Template
[StandardQueue](!) ; template to provide common features musicclass=default ; play [default] music strategy=rrmemory ; use the Round Robin Memory strategy joinempty=yes ; do not join the queue when no members available leavewhenempty=no ; leave the queue when no members available ringinuse=no ; don't ring members when already InUse (prevents ; multiple calls to an agent)
# define agents
agents.conf (dynamic way)
; answer the incoming calls in our queue [agents] ; The agent number will be used in the queues.conf file agent => agentnumber,agentpassword,agentname
Agents (agents.conf)
the people (or person) that answer call(s) that have been placed into a specific Queue.
Members
those channels that are active answering the Queue.
queues.conf or in dynamic realtime
Strategies
ringall: ring all available channels until one answers (default)
# only those available members with the lowest priorities will ring.
# i.e. If 200 is busy, then only 201 and 203 will ring.
member => SIP/200,1
member => SIP/201,2
member => SIP/202,3
member => SIP/203,2
在 Queue 內錄音
exten => _X.,1,NoOp("Call from outside") ; Check Caller same => n,NoOp("Caller ID: ${CALLERID(number)}") same => n,GotoIf($[${CALLERID(number)} : "2771"]?BridgeWait) same => n,Goto(OPERATOR) ; Label OPERATOR same => n(OPERATOR),NoOp("OPERATOR") same => n,Macro(dial-sip,30) same => n,Goto(END) ; Label QUEUE same => n(QUEUE),NoOp("QUEUE") same => n,Answer() same => n,Wait(1) same => n,Queue(MyQueue) same => n,Goto(END) [MyQueue] exten => _X.,1,NoOp("Call info: ${EXTEN}") same => n,Set(myFrom=${CUT(EXTEN,,1)}) same => n,Set(myTo=${CUT(EXTEN,,2)}) same => n,NoOp("From: ${myFrom} To: ${myTo}") same = n,MixMonitor(/var/spool/asterisk/monitor/callin/${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${myFrom}-${myTo}.wav,b) same => n,Dial(pjsip/${myTo}@mytrunk_endpoint) same = n,StopMixMonitor() same => n,Hangup()
CLI
; members, all
queue reload members
; queue info.
queue show ???????
??????? has 1 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s No Members Callers: 1. PJSIP/507-0000008e (wait: 0:26, prio: 0)
queue add member interface to queuename
queue remove member interface from queuename
pause & unpause
queue unpause member pjsip/xxxxxxxx@mytrunk_endpoint
queue pause member pjsip/xxxxxxxx@mytrunk_endpoint
AMI
QueueAdd
Action: QueueAdd
Queue: MyQueue
Interface: sip/555
Penalty: 1
Paused: false
ActionID: 1111
required:
Queue, Interface
optional:
Paused: Whether or not the member should be initially paused.
Penalty: Entries with higher penalties are considered last
ActionID: 1111
QueueRemove
Action: QueueRemove
Queue: MyQueue
Interface: pjsip/????????@mytrunk_endpoint
QueueStatus
Action: QueueStatus
Response: Success Message: Queue status will follow Event: QueueParams Queue: MyQueue Max: 0 Strategy: ringall Calls: 1 Holdtime: 91 TalkTime: 1 Completed: 1 Abandoned: 2 ServiceLevel: 0 ServicelevelPerf: 0.0 Weight: 0 Event: QueueEntry Queue: MyQueue Position: 1 Channel: PJSIP/mytrunk_endpoint-0000000e Uniqueid: 1439870582.18 CallerIDNum: xxxxxxxx CallerIDName: unknown ConnectedLineNum: unknown ConnectedLineName: unknown Wait: 204 Event: QueueStatusComplete
Queues
Action: Queues
Troubleshoot
Queue members are considered INVALID, if their device status is Invalid.
queue show ???????
MyQueue has 1 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s Members: pjsip/????????@mytrunk_endpoint (ringinuse enabled) (dynamic) (Invalid) has taken no calls yet
This is a simple module loading ordering issue. You must ensure stuff is loaded in the following order if doing this:
1. pbx_config.so
2. chan_local.so
3. app_queue.so
preload => pbx_config.so preload => chan_local.so
before
load => app_queue.so
* That will ensure your dialplan is loaded so chan_local can see it, and ensures chan_local will exist before app_queue tries to query it.
Device State
queue show ???????
Members: pjsip/????????@mytrunk_endpoint (ringinuse enabled) (dynamic) (paused) (Invalid) has taken no calls yet
* Device states are controlled by the channel module
; enable device states for SIP devices
The callcounter option in sip.conf is an essential component of a properly functioning queue.
** call out trunk 係無 Device states 的 ...
DOC
http://www.asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/asterisk-DeviceStates.html
Queue Readtime
extconfig.conf
queues => mysql,general,queue_table queue_members => mysql,general,queue_member_table
Create MySQL Table
queue_table.sql
CREATE TABLE `queue_table` ( `name` varchar(128) NOT NULL, `musiconhold` varchar(128) default NULL, `announce` varchar(128) default NULL, `context` varchar(128) default NULL, `timeout` int(11) default NULL, `monitor_join` tinyint(1) default NULL, `monitor_format` varchar(128) default NULL, `queue_youarenext` varchar(128) default NULL, `queue_thereare` varchar(128) default NULL, `queue_callswaiting` varchar(128) default NULL, `queue_holdtime` varchar(128) default NULL, `queue_minutes` varchar(128) default NULL, `queue_seconds` varchar(128) default NULL, `queue_lessthan` varchar(128) default NULL, `queue_thankyou` varchar(128) default NULL, `queue_reporthold` varchar(128) default NULL, `announce_frequency` int(11) default NULL, `announce_round_seconds` int(11) default NULL, `announce_holdtime` varchar(128) default NULL, `retry` int(11) default NULL, `wrapuptime` int(11) default NULL, `maxlen` int(11) default NULL, `servicelevel` int(11) default NULL, `strategy` varchar(128) default NULL, `joinempty` varchar(128) default NULL, `leavewhenempty` varchar(128) default NULL, `eventmemberstatus` tinyint(1) default NULL, `eventwhencalled` tinyint(1) default NULL, `reportholdtime` tinyint(1) default NULL, `memberdelay` int(11) default NULL, `weight` int(11) default NULL, `timeoutrestart` tinyint(1) default NULL, `periodic_announce` varchar(50) default NULL, `periodic_announce_frequency` int(11) default NULL, `ringinuse` tinyint(1) default NULL, `setinterfacevar` tinyint(1) default NULL, PRIMARY KEY (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
queue_member_table.sql
CREATE TABLE `queue_member_table` ( `uniqueid` int(10) unsigned NOT NULL auto_increment, `membername` varchar(40) default NULL, `queue_name` varchar(128) default NULL, `interface` varchar(128) default NULL, `penalty` int(11) default NULL, `paused` int(11) default NULL, PRIMARY KEY (`uniqueid`), UNIQUE KEY `queue_interface` (`queue_name`,`interface`) ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
Inserting the new Queue and Members
New Queue
INSERT INTO `queue_table`
(`name`,`context`)
VALUES
('MyQueue2','MyQueue');
New members
INSERT INTO `queue_member_table` (`uniqueid`,`membername`,`queue_name`,`interface`,`penalty`,`paused`) VALUES (1,'SIP/1000@from-sip','my_queue','SIP/1000',NULL,0);