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

Одной из важнейших функций PBX является функция перевода вызова, которая, к сожалению в Asterisk работает не так, как, скажем, в традиционном для российского офиса Panasonic. В этом я убедился устанавливая Asterisk в компании на 60 человек, в которой эта функция была критична, но не работала как надо ни на адаптерах, ни на Asterisk. Решилось тогда административными мерами: человек, переводящий звонок, должен был дождаться ответа третьей стороны. Но это не решение, решение далее.

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

  • atxferdropcall. Допустим кто-либо осуществляет перевод вызова с согласованием и ложит трубку до того как вызов соединён. Если выбрано значение «yes», то используется старое поведение — при невозможности соединить позвонившего вызов сбрасывается. Если выбрано «no», то система вернёт вызов обратно осуществлявшему transfer.
  • atxfernoanswertimeout. Таймаут, в течении которого система пытается соединиться со третей стороной. По-молчанию 15 секунд.
  • atxferloopdelay. Задержка перед повторным возвратом вызова делавшему transfer сотруднику.
  • atxfercallbackretries. Количество попыток возврата вызова, по-умолчанию 2.

Оказывается можно сделать аналогичным образом и в 1.4 с помощью только функций и переменных диал-плана. Вот пример extensions.conf:

[globals]
XFERNOANSTIMEOUT=15
XFERRETRIES=2
XFERLOOPDELAY=10

[office]
exten => _XXX,1,Set(TRANSFER_CONTEXT=office-xfer)
exten => _XXX,n,Dial(SIP/${EXTEN},,Tt)
[office-xfer]
exten => _XXX,1,Set(RETRIES=0)
exten => _XXX,n,ChanIsAvail(SIP/${EXTEN},s)
exten => _XXX,n,GotoIf($[${LEN(${AVAILCHAN})} = 0]?ret)
exten => _XXX,n,Dial(SIP/${EXTEN},${XFERNOANSTIMEOUT},Tt)
exten => _XXX,n(ret),GotoIf($[${BRIDGEPEER} = ${TRANSFERERNAME}]?(h,1))
exten => _XXX,n,Dial(SIP/${TRANSFERERNAME:4:3},${XFERNOANSTIMEOUT},Tt)
exten => _XXX,n,Set(RETRIES=$[${RETRIES}+1])
exten => _XXX,n,GotoIf($[${RETRIES} < ${XFERRETRIES}]?ret)
exten => _XXX,n,Wait(${XFERLOOPDELAY})
exten => _XXX,n,Playback(sorry)
exten => _XXX,n,Hangup()
exten => h,1,Hangup()

Такое решение более гибко, чем настройки в features.conf, так как вы можете вместо обратного вызова припарковать клиента или отправить сообщение менеджеру на Jabber о том, что перевод вызова не удался.

В приведённом примере достаточно много шелухи, если постараться то все дополнения уместятся в три-четыре строки. Ключевым здесь является использование переменной. Вот ещё некоторые переменные, которые вы можете использовать:

  • BRIDGEPEER — переменная с именем канала, в данный момент соединённого с данным
  • BLIND_TRANSFER — переменная с именем пира, осуществившего перевод вызова в-слепую
  • TRANSFERERNAME — переменная содержащая имя канала. осуществляющего transfer (это относится только к attented transfer)
Принимаются идеи по улучшению примера :)

Похожие сообщения:

Google Bookmarks Digg del.icio.us Technorati Slashdot News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru

автор igorg \\ теги: , ,


12 комментариев к “За Transfer замолвите слово”

  1. 1. xPoison Говорит:

    Интересно, спасибо. Затронута действительно актуальная проблема с логикой трансферов в 1.2-1.4. Попробую реализовать это на AGI.

  2. 2. igorg Говорит:

    В действительности в данном примере есть пара проблем, сначала код был написан теоретически. Проверка на практике показала что не всё что задокументировано работает как надо... Буду патчить.

  3. 3. abo Говорит:

    Я поздравляю вас с 1 апреля! Почему именно вас — можно узнать в моём блоге.

  4. 4. Ю. Говорит:

    Давненько не бывал здесь... сессия началась ... и т.п.

    Такая проблема возникала и у меня... решения не нашел...

    Пример, на практике не попробовал еще... уже поздновато... нужно бежать...

    А как результаты работы на практике?.

    Спасибо

  5. 5. igorg Говорит:

    На практике: нужно исправить пару недочётов в Asterisk, найденных при разработке этого решения на моей системе.

    Один с RTP, а второй с передачей в локальный канал переменных с именем присоединённого канала. Постараюсь на этой неделе исправить, чтобы не оставлять приведённое решение полуфабрикатом.

  6. 6. Аноним Говорит:

    ну как успехи?

  7. 7. igorg Говорит:

    (указывайте имя) Остался один из двух, пока что нет времени чтобы разобраться.

  8. 8. zgen Говорит:

    судя по всему TRANSFER_CONTEXT работает только при blind transfer :( в противном случае просто игнорируется...

  9. 9. zgen Говорит:

    [officexfer]

    exten => _10XX,1,Set (RETRIES=0)

    exten => _10XX,n (ret),NoOp ()

    exten => _10XX,n,Dial (SIP/${EXTEN},40,Tt)

    exten => _10XX,n,Set (BACK=${CUT (TRANSFERERNAME, — ,1)})

    exten => _10XX,n,Dial (${BACK},,Tt)

    exten => _10XX,n,GotoIf ($[${DIALSTATUS} = "ANSWER"]?:ret)

    exten => _10XX,n,Hangup ()

    Вот так работает :) оторвал почти все, но заставил работать asterisk 1.4

  10. 10. Oleh Говорит:

    Хороший работающий пример контекста для трансфера: asterisk-support.ru/forum...90/?page=1#32555

  11. 11. igorg Говорит:

    Спасибо за ссылку, то что было мной написано в свое время — жуткий шлак

  12. 12. shurskiy Говорит:

    Решил столкнуться с такой же проблемой. Как ни странно — тоже компания на 60 человек. Блайнд трансфер они не делают, но и при аттендант трансфере ждать не хотят.

    Начал изучать вопрос. Вот, что удалось найти Ченджлог. Почти в самом конце, поиском по слову atxfernoanswertimeout можно найти.

    Или это не совсем правда?

Написать ответ