Владислав Авдеев
11.07.2019
2171

Эффективное использование сервисных кодов перевода вызова в Asterisk

Многие знают о существовании в Asterisk сервисных кодов для управляемого и неуправляемого перевода вызова, далеко не все знают особенности их настройки. В этой статье будет описана настройка сервисных кодов для эффективного использования перевода вызова. Настройка параметров сервисных кодов Asterisk Настройки сервисных кодов Asterisk находятся в файле features.conf, по умолчанию, сервисные коды следующие:управляемый перевод — не […]

Многие знают о существовании в Asterisk сервисных кодов для управляемого и неуправляемого перевода вызова, далеко не все знают особенности их настройки. В этой статье будет описана настройка сервисных кодов для эффективного использования перевода вызова.

Настройка параметров сервисных кодов Asterisk

Настройки сервисных кодов Asterisk находятся в файле features.conf, по умолчанию, сервисные коды следующие:
управляемый перевод — не задан
неуправляемый перевод — #
отбой вызова — *

Как видите, управляемым переводом вообще нельзя пользоваться по умолчанию. Вносим в раздел [featuremap] файла features.conf:

[featuremap]
atxfer=*
blindxfer=##
disconnect=**

Для применения изменений в файле features.conf, нужно выполнить команду в CLI Asterisk «features reload»:

asterisk -rx "features reload"

Теперь имеем следующие сервисные коды:
управляемый перевод — *
неуправляемый перевод — ##
отбой вызова — **

Схожесть кодов управляемого перевода и отбоя вызова не является проблемой, т.к. в описываемой схеме эти коды никогда не будут доступны пользователю одновременно.
В разделе файла features.conf [general] указываются различные параметы сервисных кодов, обратите внимание на следующие:
featuredigittimeout — максимальная задержка между вводом символов при наборе сервисных кодов в миллисекундах. Значение по умолчанию — 1000, т.е. 1 секунда. Для ввода сервисных кодов, предлагаемых в этой статье, секунды должно хватить. Для ввода более сложных сервисных кодов пользователям может периодически не хватать времени, поэтому рекомендуется увеличить значение этого параметра до 2000.
transferdigittimeout — максимальная задержка в секундах между вводом символов при наборе номера адресата перевода. Значение по умолчанию — 3. Для более комфортного ввода номера, нужно увеличить это время до 4-5 секунд.
Atxferdropcall — при значении по умолчанию «no», если при упарвляемом переводе переводящий кладёт трубку не дожидаясь ответа адресата перевода и адресат перевода так и не принимает вызов до достижения таймаута вызова (значение параметраatxfernoanswertimeout), Asterisk попытается вернуть вызов переводящему. Asterisk может пытаться вызвать переводящего определённое количество раз (значение параметра atxfercallbackretries) с определённым интервалом (значение параметра atxferloopdelay). Если установить значение параметра atxferdropcall равным «yes», то Asterisk не будет пытаться вернуть вызов переводящему после неудачного управляемого перевода. Нужно установить значение «yes», если обработака вызова после неудачного перевода вызова реализована средствами диалплана.
ПРИМЕЧАНИЕ: Стандартный механизм возврата вызова после неудачного управляемого перевода не очень хорош, т.к. он не проверяет, свободен ли абонент, на которого должен вернуться вызов, не позволяет выполнять диалплан и не имеет возможности перевести вызов кому-либо другому, если абонент, совершивший перевод, не берёт трубку. Рекомендуется использовать вместо этого возврат вызова, реализованный средствами диалплана.

Для примеров, приведённых в этой статье, использовались следующие значения параметров в разделе [general] файла features.conf:

[general]
featuredigittimeout = 2000
atxferdropcall = yes
transferdigittimeout => 4

Написание диалплана Asterisk для обработки перевода вызовов

Предположим, что для совершения вызовов используется следующий несложный диалплан:

[global]
TRANSFER_CONTEXT=transfer
DIAL_OPTS=Tt
DIAL_TIME=20
OUT_DIAL_OPTS=T
OUT_DIAL_TIME=180
Q_OPTS=t
DEF_PROV_CID=78888888888
PROV1_CID=71111111111
PROV2_CID=72222222222
TRANSFER_FAILOVER=queues,600,1
[sub-mixmonitor]
exten => s,1,GotoIf($["${RECORDING_STARTED}" = "true"]?end)
same => n,Set(__RECORDING_FNAME=${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${ARG1}-${CALLERID(num)}-${UNIQUEID}.wav)
same => n,Set(__RECORDING_STARTED=true)
same => n,MixMonitor(${RECORDING_FNAME},ab)
same => n,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes)
same => n(end),Return
[local]
exten => _XXX,1,Gosub(sub-mixmonitor,s,1(${EXTEN}))
same => n,Dial(SIP/${EXTEN},${DIAL_TIME},${DIAL_OPTS})
same => n,ExecIf($["${THIS_IS_TRANSFER}" = "true"]?Return)
same => n,Hangup
exten => _XXX,hint,SIP/${EXTEN}
[queues]
exten => 600,1,Set(__PREVIOUS_QUEUE=${EXTEN})
same => n,Queue(reception,${Q_OPTS},,,600)
same => n,Hangup
exten => 601,1,Set(__PREVIOUS_QUEUE=${EXTEN})
same => n,Queue(sales,${Q_OPTS},,,600)
same => n,Hangup
[internal-default]
include => local
include => queues
exten => _8[2-689]XXXXXXXXX,1,Gosub(sub-mixmonitor,s,1(${EXTEN}))
same => n,Set(CALLERID(num)=${DEF_PROV_CID})
same => n,Set(CALLERID(name)=)
same => n,Dial(SIP/def_prov/${EXTEN},${OUT_DIAL_TIME},${OUT_DIAL_OPTS})
same => n,ExecIf($["${THIS_IS_TRANSFER}" = "true"]?Return)
same => n,Hangup
[from-10X]
include => local
include => queues
exten => _8[2-689]XXXXXXXXX,1,Gosub(sub-mixmonitor,s,1(${EXTEN}))
same => n,Set(CALLERID(num)=${PROV1_CID})
same => n,Set(CALLERID(name)=)
same => n,Dial(SIP/prov1/${EXTEN},${OUT_DIAL_TIME},${OUT_DIAL_OPTS})
same => n,ExecIf($["${THIS_IS_TRANSFER}" = "true"]?Return)
same => n,Hangup
[from-110]
include => local
include => queues
exten => _8[2-689]XXXXXXXXX,1,Gosub(sub-mixmonitor,s,1(${EXTEN}))
same => n,Set(CALLERID(num)=${PROV2_CID})
same => n,Set(CALLERID(name)=)
same => n,Dial(SIP/prov2/${EXTEN},${OUT_DIAL_TIME},${OUT_DIAL_OPTS})
same => n,ExecIf($["${THIS_IS_TRANSFER}" = "true"]?Return)
same => n,Hangup
exten => _810Z.,1,Gosub(sub-mixmonitor,s,1(${EXTEN}))
same => n,Set(CALLERID(num)=${PROV2_CID})
same => n,Set(CALLERID(name)=)
same => n,Dial(SIP/prov2/${EXTEN},${OUT_DIAL_TIME},${OUT_DIAL_OPTS})
same => n,ExecIf($["${THIS_IS_TRANSFER}" = "true"]?Return)
same => n,Hangup
[from-trunk]
exten => 78888888888,1,Set(CDR(did)=${EXTEN})
same => n,ExecIf($["${CALLERID(name)}" = ""]?Set(CALLERID(name)=${CALLERID(num)}))
same => n,Goto(queues,600,1)
exten => 71111111111,1,Set(CDR(did)=${EXTEN})
same => n,ExecIf($["${CALLERID(name)}" = ""]?Set(CALLERID(name)=${CALLERID(num)}))
same => n,Goto(queues,601,1)
exten => 72222222222,1,Set(CDR(did)=${EXTEN})
same => n,ExecIf($["${CALLERID(name)}" = ""]?Set(CALLERID(name)=${CALLERID(num)}))
same => n,Goto(local,110,1)

Пояснения к диалплану:
— вызовы пользователей 100-109 совершаются в контексте from-10X
— вызовы пользователя 110 совершаются в контексте from-110
— вызовы остальных пользователей совершаются в контексте internal-default
— входящие вызовы приходят в контекст from-trunk
— номер очереди сохраняется в переменную PREVIOUS_QUEUE перед входом в очередь — после вызова MixMonitor вызывается функция AUDIOHOOK_INHERIT, это нужно для того, чтобы запись продолжалась после перевода вызова

Для того, чтобы абоненты могли использовать сервисные коды перевода вызова, приложения, осуществляющие вызовы абонентов, должны использоваться с опциями разрешающими использование сервисных кодов для перевода вызова. В приведённом диалплане приложения Dial и Queue используются с опциями t и/или T.
Опция t позволяет вызываемой стороне перевести вызов с помощью сервисного кода.
Опция T позволяет вызывающей стороне перевести вызов с помощью сервисного кода.
Если не указать хотя бы одну из этих опций, сервисные коды перевода вызова не будут работать ни для одной из сторон вызова.

Обратите внимание на то, что исходящие вызовы пользователей 100-109 и 110 осуществляются через различных провайдеров, к тому же, пользователю 110 разрешены международные вызовы, а всем остальным пользователям — нет, эти условия должны быть соблюдены при переводе вызова.

Теперь нужно написать диалплан, который будет осуществлять сам перевод. По умолчанию перевод набирает введённый номер адресата в текущем контексте. Чтобы изменить это поведение, нужно установить значение переменной TRANSFER_CONTEXT, перевод будет выполняться в контексте имя которого указано в переменной TRANSFER_CONTEXT. Можно добавить эту переменную в раздел [globals] файла extensions.conf, тогда переменная TRANSFER_CONTEXT будет автоматически устанавливаться на каждом новом канале (в приведённом диалплане это уже сделано).
Ниже приведён сам контекст transfer, используемый для перевода вызовов:

[transfer]
exten => _X.,1,Set(DIAL_OPTS=${DIAL_OPTS}Hg)
same => n,Set(OUT_DIAL_OPTS=${OUT_DIAL_OPTS}Hg)
same => n,Set(Q_OPTS=${Q_OPTS}H)
same => n,Set(OUT_DIAL_TIME=45)
same => n,Set(TRANSFER_TO=${EXTEN})
same => n,Set(TRANSFERER=${CALLERID(num)})
same => n,GotoIf($["${BLINDTRANSFER}" = ""]?after_blindxfer_check)
same => n,Set(BL_TRANSFERER=${CUT(BLINDTRANSFER,-,1)})
same => n,Set(FIELDNUM=${FIELDQTY(BL_TRANSFERER,/)})
same => n,Set(BL_TRANSFERER=${CUT(BL_TRANSFERER,/,${FIELDNUM})})
same => n,ExecIf($["${BL_TRANSFERER}" != ""]?Set(TRANSFERER=${BL_TRANSFERER}))
same => n(after_blindxfer_check),NoOp(transferer: ${TRANSFERER})
same => n,GotoIf(${DIALPLAN_EXISTS(queues,${TRANSFER_TO},1)}?queues,${TRANSFER_TO},1)
same => n,Set(TR_CONT=${SIPPEER(${TRANSFERER},context)})
same => n,ExecIf($["${TR_CONT}" = ""]?Set(TR_CONT=internal-default))
same => n,Set(THIS_IS_TRANSFER=true)
same => n,Set(DIALSTATUS=)
same => n,Gosub(${TR_CONT},${TRANSFER_TO},1)
same => n,ExecIf($["${DIALSTATUS}" = "ANSWER"]?Hangup)
same => n,Goto(failover)
exten => failover,1,Playback(call-will-be-forwarded)
same => n,ExecIf($["${REGEX("^XFER_FAIL:" ${CALLERID(name)})}" = "0"]?Set(CALLERID(name)=XFER_FAIL: ${CALLERID(name)}))
same => n,Set(DIALSTATUS=)
same => n,GosubIf($["${EXTENSION_STATE(${TRANSFERER}@local)}" != "NOT_INUSE"]?local,${TRANSFERER},1)
same => n,ExecIf($["${DIALSTATUS}" = "ANSWER"]?Hangup)
same => n,Set(THIS_IS_TRANSFER=)
same => n,GotoIf($["${PREVIOUS_QUEUE}" != ""]?queues,${PREVIOUS_QUEUE},1)
same => n,Goto(${TRANSFER_FAILOVER})

Вкратце, контекст выполняет следующее:
— К опциям приложений Dial и Queue добавляется опция H, она позволяет завершить вызов сервисным кодом (в случае приложения Queue, опция H позволяет завершить вызов нажатием *, поэтому сервисный код отбоя вызова должен начинаться со *, чтобы его ввод работал и для приложения Dial и для приложения Queue). Выполнение этого сервисного кода во время управляемого перевода вызова позволит отменить перевод и вернуть вызов себе. В остальное время сервисный код будет недоступен, что предотвратит отбой вызоова из-за случайного ввода этого кода.
— К опциям приложения Dial добавляется опция g, она нужна для того, чтобы выполнение диалплана продолжалось после завершения приложения Dial (кроме случая, когда уничтожается канал звонящего).
— Определяется номер переводящего (переменная TRANSFERER) и его контекст (переменная TR_CONT). Перевод осуществляется в контексте пользователя, выполняющего вызов.
— Если переведённый вызов не был принят, проигрывается сообщение о том, что вызов будет переведён. Если переводящий всё ещё на линии, он поймёт, что перевод не удался и сможет вернуть вызов сервисным кодом.
— К CALLERID(name) добавляется префикс «XFER_FAIL: », чтобы пользователи видели, что это возврат после неудачного перевода.
— Если номер переводящего свободен, то производится попытка возврата вызова на номер переводящего.
— Если переводящий занят или не принял вызов, то вызов возвращается в последнюю очередь, в которую он входил.
— Если вызов ещё не был в очереди, он переводится на назначение по умолчанию (значение переменной TRANSFER_FAILOVER), в данном случае

— очередь reception.

В результате, перевод вызова осуществляется следующим образом:
неуправляемый перевод — во время разговора нужно набрать сервисный код ##, ввести номер адресата перевода и нажать # или подождать 4 секунды.
управляемый перевод — во время разговора нужно нажать *, ввести номер адресата перевода и нажать # или подождать 4 секунды. Если адресат перевода не принимает вызов, можно ввести сервисный код ** для отмены перевода и возврата вызова себе. Также можно положить трубку не дожидаясь ответа адресата, если он не ответит, вызов вернётся к переводящему или в очередь, если переводящий занят/не доступен/не взял трубку.
Если сервисный код перевода вызова был введён случайно, для возврата вызова нужно просто нажать # без ввода номера. Пользуйтесь таким переводом вызова и потери вызовов, связанные с неудачным переводом, будут сведены к минимуму.

Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

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

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

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

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

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

ONLINE

10 доводов в пользу Asterisk

Распространяется бесплатно.

Asterisk – программное обеспечение с открытым исходным кодом, распространяется по лицензии GPL. Следовательно, установив один раз Asterisk вам не придется дополнительно платить за новых абонентов, подключение новых транков, расширение функционала и прочие лицензии. Это приближает стоимость владения станцией к нулю.

Безопасен в использовании.

Любое программное обеспечение может стать объектом интереса злоумышленников, в том числе телефонная станция. Однако, сам Asterisk, а также операционная система, на которой он работает, дают множество инструментов защиты от любых атак. При грамотной настройке безопасности у злоумышленников нет никаких шансов попасть на станцию.

Надежен в эксплуатации.

Время работы серверов некоторых наших клиентов исчисляется годами. Это значит, что Asterisk работает несколько лет, ему не требуются никакие перезагрузки или принудительные отключения. А еще это говорит о том, что в районе отличная ситуация с электроэнергией, но это уже не заслуга Asterisk.

Гибкий в настройке.

Зачастую возможности Asterisk ограничивает только фантазия пользователя. Ни один конструктор шаблонов не сравнится с Asterisk по гибкости настройки. Это позволяет решать с помощью Asterisk любые бизнес задачи, даже те, в которых выбор в его пользу не кажется изначально очевидным.

Имеет огромный функционал.

Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.

Интегрируется с любыми системами.

То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.

Позволяет телефонизировать офис за считанные часы.

В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.

Отличная масштабируемость.

Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.

Повышает управляемость бизнеса.

Asterisk дает не просто набор полезных функций, он повышает управляемость организации, качества и комфортности управления, а также увеличивает прозрачность бизнеса для руководства. Достичь этого можно, например, за счет автоматизации отчетов, подключения бота в Telegram, санкционированного доступа к станции из любой точки мира.

Снижает расходы на связь.

Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.