Я — программист-администратор в службе такси. Мы разрабатываем комплексную систему обработки заказов. Я специализируюсь главным образом на телефонии, в частности Asterisk, сайтах (заказ такси), смс. Могу рассказать про все что касается VoIP — телефонии, сопряжения с телефонными сетями в разных городах, вывода вызовов в сотовую сеть, разработку IVR- меню и сложных телефонных приложений.
Наш комплекс работает в Ижевске (такси 373, udmtaxi.ru), Казани (такси татарстан, taxitatarstan.ru), перми (такси перемен, taxiprm.ru), орле, уфе (такси сатурн), москве (такси цель), и многих других городах, названий служб в которых я просто не помню :)
Диалплан мы пишем в стандартном виде (контексты, экстеншны).
Причины на это две: легаси и нежелание писать сложный код в самом астериске.
Диалплан — правила маршрутизации звонков, общая таблица маршрутизации.
Контекст — набор команд по обработке звонков («подпрограмма»)
Экстеншн (extension) — одна команда.
Диалплан поделен на несколько файлов:
При этом фактически города различаются только первым файлом: его задача принять звонок от клиента и направить его в AGI приложение.
Статический файл — ядро диалплана. Через него проходят звонки, которые система отправляет клиентам.
Офисная телефония — IVR меню, которое слышит клиент позвонивший на «офисный» номер, и позволяющее ему ввести внутренний номер сотрудника.
Сопряжение городов — возможность бесплатно звонить между городами, службы которых принадлежат нашей организации.
Логику работы астериска можно показать на примере контекста, который позволяет позвонить по двум номерам и соединить их между собой (использую чтобы бесплатно звонить). Не смотря на то, что в нем мало строчек, он показывает многие возможности стандартного диалплана астериска.
А теперь объясню магию построчно
После ключевого слова exten и стрелки идет номер, набранный звонящей стороной.
_ означает шаблон
X — любую цифру
. — сколько угодно цифр
Из-за бага в астериске, написать просто _. нельзя.
NoOp — просто выводит сообщение в лог
${EXTEN} — подстановка номера, набранного человеком (для удобства отладки в консоли)
EXTEN в данном случае — переменная содержащая набранный номер и сопоставляемая с _X.
Set(CALLERID(num)=${party1}) — установим наш номер звонящего.
Вообще про callerid можно написать отдельный пост, столько с ним сложностей возникает.
Длинная волшебная строчка. Первый аргумент — куда надо позвонить. Local означает, что звоним куда-то на этом же сервере (не используя SIP и другие протоколы). my-phones — наш контекст, отвечающий за исходящие звонки по любым направлениям.
Второй аргумент — таймаут, пропущен.
Третий аргумент означает, что после совершения вызова надо перейти в контекст double_call на контекст 000${party2} в первый по-порядку экстен, а другая (вызванная) сторона, попадет на экстен номер 2.
Поясню подробнее. Когда совершается вызов, создаются два канала, один для вызывающей стороны, а второй для вызываемая, и соединяются между собой. Когда мы попадаем в экстеншн double_call первый раз, вызывающая сторона — консоль, вызываемая — party1. После установления соединения с party1, мы входим в double_call дважды, с номером 000{party2}. При этом вызывающая сторона (консоль) попадает на строчку
а вызываемая — на строчку
При этом создается канал, звонящий на номер party2.
Наш комплекс работает в Ижевске (такси 373, udmtaxi.ru), Казани (такси татарстан, taxitatarstan.ru), перми (такси перемен, taxiprm.ru), орле, уфе (такси сатурн), москве (такси цель), и многих других городах, названий служб в которых я просто не помню :)
Диалплан мы пишем в стандартном виде (контексты, экстеншны).
Причины на это две: легаси и нежелание писать сложный код в самом астериске.
Терминология
Диалплан — правила маршрутизации звонков, общая таблица маршрутизации.
Контекст — набор команд по обработке звонков («подпрограмма»)
Экстеншн (extension) — одна команда.
Логическая структура диалплана
Диалплан поделен на несколько файлов:
- Для входящих звонков
- Статический
- Для офисной телефонии
- Для сопряжения городов
При этом фактически города различаются только первым файлом: его задача принять звонок от клиента и направить его в 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.