Dynamic members for queues in Asterisk

Attenzione ! Questo articolo è stato scritto più di due anni fa. Ti prego quindi di considerare che le informazioni riportate potrebbero non essere aggiornate o non più valide.

Prerequisite: confidence with Linux shell, know how to install and configure Asterisk 13 or later, know SIP protocol. 

I have a VoIP context based on OpenSIPS as B2B and an Asterisk box for multimedia services, like IVR, Voicemail and Queues.

For almost all of our offices, traditional configuration for Queues wan enough to satisfy customers relationship needs. But for one, there was the need to configure dynamic agents for queues because they decide day-per-day which had to respond to customers calls. So, my Asterisk box version is 13 and i can’t benefit on commands like AgentCallBackLogin, deprecated since 1.6, i decide to try using dialplan to create a way to add and remove agents from all queues available on my system.

Just to introduce my context and help you with this example, for some reasons (remember: i use OpenSIPS as SIP router, not Asterisk itself !) i decide to define queue agents as “MemberConnector”:

In extensions.conf i have:

; ======================================================================
 ; QUEUES Member Agent
 ; ======================================================================

[MemberConnector]
 exten => _[A-Za-z0-9].,1,Verbose(2,Connecting ${CALLERID(all)} to Agent at ${EXTEN})
 same => n,Set(QueueMember=${FILTER(A-Za-z0-9\-,${EXTEN})})
 same => n,Set(Technology=${CUT(QueueMember,-,1)})
 same => n,Set(Device=${CUT(QueueMember,-,2)})
 same => n,Noop("MemberConnector: calling queue member ${Technology}/voip-trunk/${Device}")
 same => n,Dial(${Technology}/voip-trunk/${Device},30)
 same => n,Hangup()

Note that “voip-trunk” must be defined in sip.conf as, obviously, the sip trunk that interconnects OpenSIPS with Asterisk. Also in extensions.conf, i need to define all my IVR as an introductory system for all my queues (do announcements, filter by date-time, change asserted identity and so on…). In the following few lines, how i define my test queue ‘5599’:

; ==== IVR 5599 - Test queue
 [ivr-5599]
 exten => s,1,Noop("Test queue from ${CALLERID(num)}")
 exten => s,n,SipAddHeader(P-Asserted-Identity: "Test queue - ${CALLERID(num)}" <sip:${CALLERID(num)}>)
 exten => s,n,Queue(queue-5599)
 exten => s,n,Hangup

Now it’s time to define our queue in queues.conf as follow:

[queue-5599] # 5599 Test Queue 
 music = queue-default
 strategy = ringall
 timeout = 15
 wrapuptime = 10
 announce-frequency = 30
 announce-holdtime = yes
 joinempty = yes

I define an empty queue because all its agents are defined dynamically by users itself, using its own phone and calling *40[queue number] to be added as Agent and *41[queue number] to log out. So, in default context (or wherever you choose) inside extensions.conf i add:

exten => _*40XXXX,1,Answer
exten => _*40XXXX,n,Set(AGENTID=${CALLERID(num)})
exten => _*40XXXX,n,Set(QUEUEID=${EXTEN:3})
exten => _*40XXXX,n,Noop("Add Member ${AGENTID} to Queue ${QUEUEID}")
exten => _*40XXXX,n,AddQueueMember(queue-${QUEUEID},Local/SIP-${AGENTID}@MemberConnector/n,0)
exten => _*40XXXX,n,Goto(ret-${AQMSTATUS})
exten => _*40XXXX,n(ret-ADDED),Playback(msg/queue-added)
exten => _*40XXXX,n(ret-ADDED),Hangup()
exten => _*40XXXX,n(ret-MEMBERALREADY),Playback(msg/queue-alreadyin)
exten => _*40XXXX,n(ret-MEMBERALREADY),Hangup()
exten => _*40XXXX,n(ret-NOSUCHQUEUE),Playback(msg/queue-iderror)
exten => _*40XXXX,n,Hangup()

and to be removed as Agent:

exten => _*41XXXX,1,Answer
exten => _*41XXXX,n,Set(AGENTID=${CALLERID(num)})
exten => _*41XXXX,n,Set(QUEUEID=${EXTEN:3})
exten => _*41XXXX,n,Noop("Remove Member ${AGENTID} to Queue ${QUEUEID}")
exten => _*41XXXX,n,RemoveQueueMember(queue-${QUEUEID},Local/SIP-${AGENTID}@MemberConnector/n)
exten => _*41XXXX,n,Goto(ret-${RQMSTATUS})
exten => _*41XXXX,n(ret-REMOVED),Playback(msg/queue-removed)
exten => _*41XXXX,n(ret-REMOVED),Hangup()
exten => _*41XXXX,n(ret-NOTINQUEUE),Playback(msg/queue-notin)
exten => _*41XXXX,n(ret-NOTINQUEUE),Hangup()
exten => _*41XXXX,n(ret-NOSUCHQUEUE),Playback(msg/queue-iderror)
exten => _*41XXXX,n,Hangup()

Playback of audio files just to inform users that your request was successful or not: you can omit, if you don’t need to provide any feedback.

Please note: those audio files are not included in  default audio package, so you need to create them.

Just to refresh memory, _*40XXXX is an Asterisk dialplan pattern that match *40 followed by 4 digits (XXXX: our queue id), so users simply have to call certain number to be added or removed from queue immediately.

Back to the example, in the second and third line i set AGENTID and QUEUEID variables, that will be used as arguments for AddQueueMember command. Return code was used on Goto to jump to the corresponding label and say if adding was successful or not. The second part of the example is very similar to first, except for RemoveQueueMember function and different ret codes.

Connecting to Asterisk CLI (asterisk -r):

asterisk*CLI> queue show queue-5599 
queue-5599 has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:1, SL:0.0% within 0s
 No Members
 No Callers

And now, i call #405599 from my VoIP terminal, registered as 5002:

asterisk*CLI> queue show queue-5599
queue-5599 has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:1, SL:0.0% within 0s
 Members: 
 Local/SIP-5002@MemberConnector/n (ringinuse enabled) (dynamic) (Not in use) has taken no calls yet
 No Callers

At this point, when someone call on 5599 queue, my VoIP phone (5002) will ring. To disconnect from the queue, simply call #415599.

That’s all !

Feel free to ask questions or suggestions to improve my example.

 

Michele Pinassi

Nato a Siena nel 1978, dopo aver conseguito il diploma in "Elettronica e Telecomunicazioni" e la laurea in "Storia, Tradizione e Innovazione", attualmente è Responsabile del Sistema telefonico di Ateneo presso l'Università degli Studi di Siena ed esperto di sicurezza informatica nello staff del DPO. Utilizza quasi esclusivamente software libero.

Potrebbero interessarti anche...

2 Risposte

  1. Vladi ha detto:

    ciao, molto interessante il tuo articolo. Volevo chiederti però se la funzione che descrivi aggiunge gli utenti come “dinamici” o “statici” o se c’è possibilità di scegliere. Questo perchè ho un problema con delle code e gli agenti dinamici. Ho la necessità che gli agenti possano effettuare il login e logout alla coda, ma anche che squillino con un ordine preimpostato, cosa che sembra impossibile in asterisk se non con il parametro penalty che però non è facilmente gestibile e la tua mi sembrava una buona strada per controllare gli utenti loggati ed inserirli come agenti statici nella coda (ammesso che sia possibile), grazie!

    • Michele Pinassi ha detto:

      Buonasera Vladi, con questa funzione è possibile aggiungere agenti dinamici con la medesima priorità (o penalità), che è inferiore agli agenti statici di una coda. Secondo il manuale di Asterisk, è possibile indicare singolarmente la priorità dell’agente da aggiungere:

      AddQueueMember(queuename,[interface,[penalty,[options,[membername,[stateinterface]]]]])

      che quindi puoi controllare magari con una tabella MySQL oppure direttamente in fase di aggiunta, aggiungendo un parametro.

      Buona fortuna !

Rispondi

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.

%d blogger hanno fatto clic su Mi Piace per questo: