Как стать автором
Обновить

Asterisk в такси

Я — программист-администратор в службе такси. Мы разрабатываем комплексную систему обработки заказов. Я специализируюсь главным образом на телефонии, в частности Asterisk, сайтах (заказ такси), смс. Могу рассказать про все что касается VoIP — телефонии, сопряжения с телефонными сетями в разных городах, вывода вызовов в сотовую сеть, разработку IVR- меню и сложных телефонных приложений.
Наш комплекс работает в Ижевске (такси 373, udmtaxi.ru), Казани (такси татарстан, taxitatarstan.ru), перми (такси перемен, taxiprm.ru), орле, уфе (такси сатурн), москве (такси цель), и многих других городах, названий служб в которых я просто не помню :)

Диалплан мы пишем в стандартном виде (контексты, экстеншны).
Причины на это две: легаси и нежелание писать сложный код в самом астериске.

Терминология


Диалплан — правила маршрутизации звонков, общая таблица маршрутизации.
Контекст — набор команд по обработке звонков («подпрограмма»)
Экстеншн (extension) — одна команда.

Логическая структура диалплана


Диалплан поделен на несколько файлов:
  1. Для входящих звонков
  2. Статический
  3. Для офисной телефонии
  4. Для сопряжения городов

При этом фактически города различаются только первым файлом: его задача принять звонок от клиента и направить его в AGI приложение.
Статический файл — ядро диалплана. Через него проходят звонки, которые система отправляет клиентам.
Офисная телефония — IVR меню, которое слышит клиент позвонивший на «офисный» номер, и позволяющее ему ввести внутренний номер сотрудника.
Сопряжение городов — возможность бесплатно звонить между городами, службы которых принадлежат нашей организации.

Пример контекста с магией


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

[double_call]
; console dial nomer1-nomer2@double_call
; Звонит на номер1, ждет ответа, звонит на номер2, соединяет

exten => _X.,1,NoOp(****** Dialing ${EXTEN} *****)
exten => _X.,n,Set(party1=${CUT(EXTEN,-,1)})
exten => _X.,n,Set(party2=${CUT(EXTEN,-,2)})
exten => _X.,n,Set(CALLERID(num)=${party1})
exten => _X.,n,Dial(Local/${party1}@my-phones,,G(double_call^000${party2}^1))
exten => _000.,1,Hangup
exten => _000.,2,Dial(Local/${EXTEN:3}@my-phones)


А теперь объясню магию построчно

exten => _X.,1,NoOp(****** Dialing ${EXTEN} *****)


После ключевого слова exten и стрелки идет номер, набранный звонящей стороной.

_ означает шаблон
X — любую цифру
. — сколько угодно цифр
Из-за бага в астериске, написать просто _. нельзя.
NoOp — просто выводит сообщение в лог
${EXTEN} — подстановка номера, набранного человеком (для удобства отладки в консоли)

Set(party1=${CUT(EXTEN,-,1)}) - присвоить переменной кусок набранного номера до знака -
Set(party2=${CUT(EXTEN,-,2)}) - то же самое после знака -


EXTEN в данном случае — переменная содержащая набранный номер и сопоставляемая с _X.

Set(CALLERID(num)=${party1}) — установим наш номер звонящего.
Вообще про callerid можно написать отдельный пост, столько с ним сложностей возникает.

Dial(Local/${party1}@my-phones,,G(double_call^000${party2}^1))

Длинная волшебная строчка. Первый аргумент — куда надо позвонить. Local означает, что звоним куда-то на этом же сервере (не используя SIP и другие протоколы). my-phones — наш контекст, отвечающий за исходящие звонки по любым направлениям.

Второй аргумент — таймаут, пропущен.

Третий аргумент означает, что после совершения вызова надо перейти в контекст double_call на контекст 000${party2} в первый по-порядку экстен, а другая (вызванная) сторона, попадет на экстен номер 2.

Поясню подробнее. Когда совершается вызов, создаются два канала, один для вызывающей стороны, а второй для вызываемая, и соединяются между собой. Когда мы попадаем в экстеншн double_call первый раз, вызывающая сторона — консоль, вызываемая — party1. После установления соединения с party1, мы входим в double_call дважды, с номером 000{party2}. При этом вызывающая сторона (консоль) попадает на строчку
exten => _000.,1,Hangup

а вызываемая — на строчку
exten => _000.,2,Dial(Local/${EXTEN:3}@my-phones).

При этом создается канал, звонящий на номер party2.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.