Перевод вызовов в Asterisk
Уже написано много разного по поводу перевода вызовов, но надо объединить чужой и свой опыт в одном месте, чтобы не забылось в будущем. Есть клиент с не очень большим количеством сотрудников, но крайне требовательный. На его Astersik было развернуто много разных интересных и не очень решений. Недавно он захотел вспомнить времена, когда они пользовались офисной АТС Panasonic и попросил сделать перевод вызовов таким как они привыкли (угу, прошло всего-то 3 года).
Основными требованиями было:
- Быстрый перевод вызова
- Возможность проконсультироваться с третьей стороной
- Возврат вызова при неудачном переводе
В существующей схеме перевод осуществлялся нажатием #
или программной кнопки на телефонном аппарате.
Были осуществлены попытки сделать все необходимое через blindtransfer
. Изначально получилось следующее в extensions.conf:
[globals]
TRANSFER_CONTEXT = transfer-rb
[transfer-rb]
exten => _X.,1,NoOp(BLINDTRANSFER :: ${BLINDTRANSFER})
exten => _X.,n,Set(extenLength=${LEN(${EXTEN})})
exten => _X.,n,Dial(SIP/${EXTEN},20,Ttfg)
exten => _X.,n,NoOp(DIALSTATUS :: ${DIALSTATUS})
exten => _X.,n,GotoIf($["${DIALSTATUS}"="ANSWER"]?hu:cb)
exten => _X.,n(cb),Dial(SIP/${BLINDTRANSFER:4:${extenLength}},,Ttfg)
exten => _X.,n(hu),HangUp()
При переводе вызов попадает в контекст transfer-rb
Если вызов был переведен удачно, то HangUp()
, если не удачно, то перезвонить тому кто переводил. Особое внимание стоит обратить на переменную TRANSFER_CONTEXT
в части globals. Это пользовательская переменная, но она имеет больший приоритет над системной переменной __TRANSFER_CONTEXT
. Поэтому для избежания сюрпризов лучше использовать пользовательскую переменную.
Данный вариант имеет право на жизнь, так как найдет свою нишу у привередливого пользователя АТС. Но как быть если этот вариант не устраивает?
Был внимательно прочитан файл features.conf
со всеми комментариями. Как оказалось все было на много проще, чем придуманное решение. С версии Astersik 1.6 atxfer
(перевод с консультацией) уже имеет подобный функционал, надо было лишь его включить.
atxfernoanswertimeout
указывает время, которое понадобится для попытки осуществления перевода. По умолчанию имеет значение в 15 секунд, но в моем случае было выбрано время в 20 секунд.
atxferdropcall
указывает прекращать вызов или нет при неудачном переводе. По умолчанию выставлена в значение yes
, то есть возврата вызова не произойдет. Выставляем параметру значение no
и вызовы будут возвращаться.
atxferloopdelay
указывает время в секундах между попытками дозвониться обратно. Можно не менять и оставить со значением по умолчанию, равным 10 секунд.
atxfercallbackretries
указывает количество попыток дозвониться обратно. Это тоже можно настроить на свое усмотрение. Для меня подошло стандартное значение в 2 попытки.
Дальше просто назначаем на atxfer
свою клавишу. В моем случае получилось переназначить с blindxfer #
.
И для ускорения перевода вызова можно назначить переменной transferdigittimeout
значение в 1 секунду, вместо 3.
Итоговый вариант как теперь выглядит features.conf:
[general]
parkext => *700
parkpos => 701-720
context => parkedcalls
parkedcalltransfers = caller
transferdigittimeout => 1
xfersound = beep
xferfailsound = beeperr
atxfernoanswertimeout = 15
atxferdropcall = no
atxferloopdelay = 10
atxfercallbackretries = 2
[featuremap]
blindxfer => *
atxfer => #
Всё очень просто. И соблюдается главное правило RTFM.