artem
05.02.2018
1104

Asterisk – имитация нахождения вызова в очереди для системы статистики

Контексты для имитации нахождения вызова в очереди

Для имитации нахождения вызова в очереди, в лог очереди будут добавляться записи с помощью приложения диалплана QueueLog. На различных этапах вызова будут вызываться различные контексты, все они приведены ниже (контексты нужно добавить в файл /etc/asterisk/extensions_custom.conf)

 

[app-fake-queue-enter]
exten => s,1,ExecIf($[“${ARG1}” = “”]?Return)
 
same  => n,Set(__FAKEQ_${ARG1}_ENTERTIME=${EPOCH})
same  => n,Set(__FAKEQ_${ARG1}_STATUS=IN QUEUE)
same  => n,Set(__FAKEQ_${ARG1}_ANSWERTIME=)
same  => n,Set(__FAKEQ_${ARG1}_UID=${UNIQUEID})
same  => n,Set(__FAKEQ_${ARG1}_CALLER=${CALLERID(num)})
same  => n,Set(__FAKEQ_${ARG1}_HOLDTIME=)
same  => n,Set(__FAKEQ_${ARG1}_RINGSTART=)
 
same  => n,QueueLog(${ARG1},${FAKEQ_${ARG1}_UID},NONE,DID,${CDR(did)})
same  => n,QueueLog(${ARG1},${FAKEQ_${ARG1}_UID},NONE,ENTERQUEUE,,${FAKEQ_${ARG1}_CALLER},1)
same  => n,Return

Контекст app-fake-queue-enter добавляет в лог очереди записи DID и ENTERQUEUE (запись DID не является стандартной и используется в FreePBX). Единственный аргумент – имя очереди.

[app-fake-queue-connect]
exten => s,1,ExecIf($[“${ARG1}” = “” | “${ARG2}” = “” | “${FAKEQ_${ARG1}_STATUS}” != “IN QUEUE” | “${FAKEQ_${ARG1}_ENTERTIME}” = “” | “${FAKEQ_${ARG1}_UID}” = “” ]?Return)
same  => n,GotoIf($[“${ARG3}” = “callee”]?callee)
same  => n,Set(__FAKEQ_${ARG1}_ANSWERTIME=${EPOCH})
same  => n,Set(__FAKEQ_${ARG1}_HOLDTIME=$[${FAKEQ_${ARG1}_ANSWERTIME} – ${FAKEQ_${ARG1}_ENTERTIME}])
same  => n,ExecIf($[${FAKEQ_${ARG1}_HOLDTIME} < 0]?Set(__FAKEQ_${ARG1}_HOLDTIME=0))
same  => n,Set(__FAKEQ_${ARG1}_STATUS=ANSWERED)
same  => n,Goto(cont1)
 
same  => n(callee),Set(MASTER_CHANNEL(__FAKEQ_${ARG1}_ANSWERTIME)=${EPOCH})
same  => n,Set(FAKEQ_${ARG1}_HOLDTIME=$[${FAKEQ_${ARG1}_ANSWERTIME} – ${FAKEQ_${ARG1}_ENTERTIME}])
same  => n,ExecIf($[${FAKEQ_${ARG1}_HOLDTIME} < 0]?Set(FAKEQ_${ARG1}_HOLDTIME=0))
same  => n,Set(MASTER_CHANNEL(__FAKEQ_${ARG1}_HOLDTIME)=${FAKEQ_${ARG1}_HOLDTIME})
same  => n,Set(MASTER_CHANNEL(__FAKEQ_${ARG1}_STATUS)=ANSWERED)
 
same  => n(cont1),QueueLog(${ARG1},${FAKEQ_${ARG1}_UID},${ARG2},CONNECT,${FAKEQ_${ARG1}_HOLDTIME},,1)
same  => n,Return

Контекст app-fake-queue-connect добавляет в лог очереди запись CONNECT. Аргументы контекста:
ARG1 – имя очереди
ARG2 – имя ответившего оператора
ARG3 – должен иметь значение callee, если Gosub в контекст app-fake-queue-connect был выполнен на канале вызванного абонента (например с помощью опции U приложения Dial). Если Gosub был выполнен на канале звонящего, ARG3 должен иметь любое другое значение (в том числе пустое)

 

[app-fake-queue-noanswer]
exten => s,1,ExecIf($[“${ARG1}” = “” | “${ARG2}” = “” | “${FAKEQ_${ARG1}_STATUS}” != “IN QUEUE” | “${FAKEQ_${ARG1}_ENTERTIME}” = “” | “${FAKEQ_${ARG1}_UID}” = “” | “${FAKEQ_${ARG1}_RINGSTART}” = “” ]?Return)
same  => n,Set(RINGNOANSWER_TIME=$[(${EPOCH} – ${FAKEQ_${ARG1}_RINGSTART})*1000])
same  => n,ExecIf($[${RINGNOANSWER_TIME} < 0]?Set(RINGNOANSWER_TIME=0))
same  => n,QueueLog(${ARG1},${FAKEQ_${ARG1}_UID},${ARG2},RINGNOANSWER,${RINGNOANSWER_TIME})
same  => n,Return

Контекст app-fake-queue-noanswer добавляет в лог очереди запись RINGNOANSWER. Аргументы контекста:
ARG1 – имя очереди
ARG2 – имя оператора, пропустившего звонок

 

[app-fake-queue-leave]
exten => s,1,ExecIf($[“${ARG1}” = “” | “${FAKEQ_${ARG1}_ENTERTIME}” = “” | “${FAKEQ_${ARG1}_UID}” = “”]?Return)
same  => n,Set(NOW=${EPOCH})
same  => n,GotoIf($[“${FAKEQ_${ARG1}_STATUS}” = “ANSWERED”]?answered)
; no answer
same  => n,GotoIf($[“${ARG2}” = “” | “${FAKEQ_${ARG1}_RINGSTART}” = “”]?no-ring)
same  => n,Gosub(app-fake-queue-noanswer,s,1(${ARG1},${ARG2}))
same  => n(no-ring),Set(ABANDON_TIME=$[${NOW} – ${FAKEQ_${ARG1}_ENTERTIME}])
same  => n,ExecIf($[${ABANDON_TIME} < 0]?Set(ABANDON_TIME=0))
same  => n,QueueLog(${ARG1},${FAKEQ_${ARG1}_UID},NONE,ABANDON,1,1,${ABANDON_TIME})
same  => n,Goto(cont1)
; answered
same  => n(answered),ExecIf($[“${ARG2}” = “” | “${FAKEQ_${ARG1}_ANSWERTIME}” = “” | “${FAKEQ_${ARG1}_HOLDTIME}” = “”]?Return)
same  => n,Set(QUEUE_EVENT=${IF($[“${ARG3}” = “COMPLETEAGENT”]?${ARG3}:COMPLETECALLER)})
same  => n,Set(CALL_TIME=$[${NOW} – ${FAKEQ_${ARG1}_ANSWERTIME}])
same  => n,ExecIf($[${CALL_TIME} < 0]?Set(CALL_TIME=0))
same  => n,QueueLog(${ARG1},${FAKEQ_${ARG1}_UID},${ARG2},${QUEUE_EVENT},${FAKEQ_${ARG1}_HOLDTIME},${CALL_TIME},1)
 
same  => n(cont1),Set(__FAKEQ_${ARG1}_ENTERTIME=)
same  => n,Set(__FAKEQ_${ARG1}_STATUS=)
same  => n,Set(__FAKEQ_${ARG1}_ANSWERTIME=)
same  => n,Set(__FAKEQ_${ARG1}_UID=)
same  => n,Set(__FAKEQ_${ARG1}_CALLER=)
same  => n,Set(__FAKEQ_${ARG1}_HOLDTIME=)
same  => n,Set(__FAKEQ_${ARG1}_RINGSTART=)
same  => n,Return

Контекст app-fake-queue-leave добавляет в лог очереди запись COMPLETECALLER/COMPLETEAGENT, если был ответ на вызов, или ABANDON, если ответа не было (также вызывает app-fake-queue-noanswer при необходимости). Аргументы контекста:
ARG1 – имя очереди
ARG2 – имя оператора, принявшего или пропустившего звонок
ARG3 – должен иметь значение COMPLETEAGENT, если вызов завершил оператор (иначе в лог будет записано COMPLETECALLER)

 

Применение сценария на примере прямого донабора в IVR

Ниже приведены параметры тестового меню IVR.

Параметры текстового меню IVR

Вызовы из IVR идут в очередь 10000, сделаем так, чтобы при наборе в IVR номера оператора очереди 10000, в лог очереди добавились все необходимые сообщения для системы статистики (для этого опция Enable Direct Dial должна быть отключена).
Порядок вызова контекстов следующий:
1) app-fake-queue-enter для записи ENTERQUEUE
2) app-fake-queue-connect для записи CONNECT (если был ответ)
3) app-fake-queue-leave для записи COMPLETECALLER/COMPLETEAGENT или RINGNOANSWER и ABANDON
(app-fake-queue-noanswer в данном сценарии вызывается только из app-fake-queue-leave)

Донабор для IVR лучше реализовать в виде отдельного контекста, чтобы можно было включать его в различные IVR (если в IVR используются разные очереди, нужно устанавливать переменную CUR_QUEUE до входа в IVR, например, через Custom Destination).

[ext-direct-dial-fakeq]
exten => _XXX,1,Set(DIAL_STR=${DB(DEVICE/${EXTEN}/dial)})
same  => n,GotoIf($[${DIALPLAN_EXISTS(ext-local,${EXTEN},1)} = 0]?invalid)
same  => n,GotoIf($[“${DIAL_STR}” = “”]?invalid)
same  => n,GotoIf($[“${EXTENSION_STATE(${EXTEN}@ext-local)}” != “NOT_INUSE”]?continue)
same  => n,Set(CUR_QUEUE=10000)
same  => n,GotoIf($[${REGEX(“(^|,)Local/${EXTEN}@from-queue/n($|,)” ${QUEUE_MEMBER_LIST(${CUR_QUEUE})})} = 0]?skip_fake_queue)
same  => n,Set(FAKEQ_NUM=${CUR_QUEUE})
same  => n,Set(FAKEQ_AGENT_NUM=${EXTEN})
same  => n,Set(FAKEQ_AGENT_NAME=${DB(AMPUSER/${FAKEQ_AGENT_NUM}/cidname)})
same  => n,Set(FAKEQ_RESULT=COMPLETECALLER)
same  => n,ExecIf($[“${FAKEQ_AGENT_NAME}” = “”]?Set(FAKEQ_AGENT_NAME=${FAKEQ_AGENT_NUM}))
same  => n,ExecIf($[“${FAKEQ_${FAKEQ_NUM}_STATUS}” = “”]?Gosub(app-fake-queue-enter,s,1(${FAKEQ_NUM})))
same  => n,Set(CHANNEL(hangup_handler_push)=app-fake-queue-leave,s,1(${FAKEQ_NUM},${FAKEQ_AGENT_NAME},${FAKEQ_RESULT}))
same  => n,Set(__FAKEQ_${FAKEQ_NUM}_RINGSTART=${EPOCH})
same  => n(skip_fake_queue),Gosub(sub-record-check,s,1(exten,${EXTEN},yes))
same  => n,Set(DIALSTATUS=)
same  => n,Dial(${DIAL_STR},15,tgU(app-fake-queue-connect^${FAKEQ_NUM}^${FAKEQ_AGENT_NAME}^callee))
same  => n,Set(FAKEQ_RESULT=COMPLETEAGENT)
same  => n,ExecIf($[“${DIALSTATUS}” = “ANSWER”]?Hangup)
same  => n(continue),Gosub(app-fake-queue-leave,s,1(${FAKEQ_NUM},${FAKEQ_AGENT_NAME}))
same  => n,Goto(t,1)
same  => n(invalid),Set(INVALID_EXTEN=${EXTEN})
same  => n,Goto(i,1)
 

Теперь нужно найти в файле /etc/asterisk/extensions_additional.conf имя контекста созданного IVR, в данном примере это контекст ivr-2. В файле /etc/asterisk/extensions_override_freepbx.conf нужно включить контекст ext-ivr-direct-dial в ivr-2.

[ivr-2]
include => ext-direct-dial-fakeq 

Настройка завершена.

 

 
avatar
  Подписаться  
Уведомление о

Остались вопросы?

Я - Першин Артём, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование

ближайшие курсы

ближайшие Вебинары

ONLINE

Why Choose HUGE?

Unlimited pre-designed elements

Each and every design element is designed for retina ready display on all kind of devices

User friendly interface and design

Each and every design element is designed for retina ready display on all kind of devices

100% editable layered PSD files

Each and every design element is designed for retina ready display on all kind of devices

Created using shape layers

Each and every design element is designed for retina ready display on all kind of devices