Предпосылки
В жизни любой крупной развивающейся компании рано или поздно встаёт вопрос о расширении возможностей телефонной станции и переходе от классической телефонии к IP.
Далёкой весной 2011 и перед нашей компанией встал такой вопрос, т. к. внешние и внутренние линии требуют постоянного расширения, а количество портов на старом Panasonic KX-TA624 было задано статично и расширению не подлежало. Открытие офисов в других городах и внедрение единой службы по работе с клиентами в других городах так же подталкивало к качественным переменам.
Техническое задание
Конечный продукт должен иметь следующие характеристики:
1) иметь большое количество (в нашем случае не менее 100) внешних и внутренних линий и быть готовым к расширению;
2) уметь приветствовать пользователей в рабочее время и сообщать о том, что они позвонили в нерабочее время, когда никого нет на месте;
3) таймауты переадресации при не ответе/занятости/недоступности должны настраиваться индивидуально;
4) должны быть предусмотрены очереди. Очередь — группа номеров, распределение звонков внутри которой происходит по определенным правилам;
5) записывать лог сообщений (как текстовый, так и аудио);
6) иметь гибкую политику распределения прав на внешние звонки. Должны быть предусмотрены пользователи, которые могут звонить только на внутренние номера; на городские номера; на любые номера;
7) в зависимости от времени суток, звонить на тот или иной номер.
Неудачный опыт
Первоначальный выбор пал на Planet ipx-1900. С характеристиками можно ознакомиться здесь:
www.planet.com.ru/en/product/product_keyf.php?id=18500
Среди прочего заявлена поддержка:
• Автоинформатор (AA)
• Интерактивные голосовые ответы (IVR)
• Детализированный отчет по вызовам (CDR)
На практике не работает ни один из этих параметров. Поддержка Planet'а вопросы игнорировала. Завести на это железо 8800 стандартными средствами не получалось.
Пришлось ковырять глубже. На этой PBX есть com-порт и telnet, при соединении с которым запрашивается логин и пароль. Техническая поддержка Planet'а сообщать реквизиты для входа отказалась… точнее проигнорировала просьбу. Страница с прошивкой для девайса можно найти здесь:
planet.com.ru/en/support/download2.php?id=18500&file_type=65&prod_model=IPX-1900
Прошивка оказалась не чем иным, как архивом:
Самым интересным оказался start_install.sh — этот скрипт выполняется сразу после загрузки прошивки на устройство. Сразу после строки:
добавляем строчку:
Пакуем все обратно в архив и загружаем прошивку на станцию.
Если всё пройдёт удачно, то можно будет логинится на станцию через com-порт или telnet.
Внутри был обнаружен μClinux с Asterix 1.4
И началось допиливание станции до рабочего состояния. Список изменений выкладывать не будем, потому как он, к настоящему времени, безвозвратно утерян.
Благодаря доступу к консоли станции, удалось реализовать п.1-4 технического задания. И добавить на станции 8800, что тоже не плохо, если бы не:
1) постоянные зависания станции и внешних портов;
2) ежедневные перезагрузки станции по ночам;
3) временами, после перезагрузки, станции не удавалось синхронизироваться с временным сервером, и она сообщала клиентам, что время не рабочее, хотя на деле время было рабочим.
Тем не менее, в таком виде телефония существовала в Регтайм около полутора лет. Тем не менее руководство продолжало «пинать» техническую поддержку (да-да, именно техническую поддержку) на тему воплощения в жизнь мечты о выполненном техническом задании, и техническая поддержка разродилась.
Железо
На момент перехода с planet на обычный сервер в распоряжении имелось:
1) несколько голосовых шлюзов planet ata-150s (2 fxs порта);
2) linksys spa-3000 (1fxo + 1 fxs порт) — 2 штуки;
3) связка аналоговых телефонов (наследие Panasonic);
4) VoIP phone dlink-dph150s, dlink-dph150se;
5) сервер с ОС Debian;
6) сетевые фильтры, витая пара, свитч :)
Субъективный отзыв о железе
VoIP dlink работают хорошо. Зависаний практически не наблюдается. Было несколько моделей с браком, но их без вопросов поменяли на новые.
Linksys — неплохо. Иногда случаются зависания, при чем зависает не сам голосовой шлюз, а порт FXO на нём. К сожалению, обнаруживается только по обращению клиентов.
Planet ata-150s — плохо. Очень часто случаются зависания, периодически появляются шумы в трубке. Помогает только перезагрузка. Были куплены пачкой — поэтому приходится работать с тем, что есть.
Установка Asterisk
К сожалению, лог установки asterisk на debian не сохранился. Поэтому для статьи будут переведены команды установки на Ubuntu 12.04. Отличий, по большому счету, должно быть очень мало, например, в основной репозитарий debian не включен Asterisk 1.8, но он есть в backports.
Для работы мы используем следующие пакеты:
1 asterisk — Asterisk 1.8
2 libasterisk-agi-perl — AGI модуль для perl. Об этом немного позже.
3 asterisk-mysql — расширение Asterisk, которое позволяет хранить статистику не в текстовом файле, а в базе данных
Настройка лога звонков
1) Из-под root'а базы данных создадим новую базу и пользователя:
2) Заходим под только что созданным пользователем:
3) Создаём таблицу:
4) Переходим в каталог конфигов астериск (все дальнейшие действия необходимо выполнять от имени супер-пользователя) и делаем копию всего содержимого на всякий случай:
У нас он имеет вид:
Конфиг cdr.conf остался без изменений.
Пользователи и контексты исходящих звонков
Для исходящих звонков пользователей у нас есть 4 контекста:
1 phone_int — дефолтное значение. Пользователи, которым разрешены звонки только на внутренние 3-х значные номера.
2 phone_local — пользователям можно звонить на 7-значные внутригородские номера;
3 phone_long_d — этим пользователям разрешены звонки внутри страны;
4 phone_too_long_d — международные звонки.
Контексты включены друг в друга, т.е. пользователям phone_too_long_d разрешено звонить и на внутренние номера сотрудников, и внутри города.
Приступим:
1) Разобьём sip.conf на несколько:
sip_general.conf — основные настройки asterisk.
sip_internal.conf — внутренние номера пользователей;
sip_trunk.conf — внешние линии;
2) Пример настройки 3-х номерв в sip_internal.conf:
Пользователю 101 разрешены звонки внутри России ( context = phone_long_d ); пользователю 112 ( phone_local ) можно звонить внутри города; 106 разрешено звонить куда угодно; пользователю 495 разрешены звонки только на внутренние номера (если контекст не задан, то используется контекст phone_int). Поле secret — пароль, который будет использован для авторизации.
Входящие линии
Пример основного конфига:
Настройка trunk'а:
Линия example_num использует авторизацию и регистрацию на удаленной станции, для совершения. Обратите внимание, для этой линии прописано:
в sip_general.conf.
Линия pstn_beeline регистрации не требует — фактически эта одна из “наземных” линий, подключенных через fxo порт linksys spa 3000, но об этом немного позже.
Линия RTK — здесь не требуется ни авторизации ни регистрации. На станции нужен только пользователь и ip (поле host), с которого будут приходить звонки. Это номер 8800 — на него осуществляется только входящая телефония. В терминах Ростелекома имя пользователя — это маршрутный номер.
Для всех входящих звонков контекст один — from_external.
Dialplan (План набора) — маршрутизация звонков
Самое интересное в работе любой АТС — это план набора. План набора маршрутизирует звонки согласно правилам, которые в нём описаны. Итак:
1) Исходящие звонки.
Разбор строки:
_0[1-79]XXXXXX — маска набранного номера. Подробнее здесь ( voip.rus.net/tiki-index.php?page=Asterisk+Dialplan+Patterns )
0 — первая цифра, которая пришла
[1-79] — второй цифрой может быть любое число кроме 8, т.к. это выход на межгород
XXXXXX — любые 7 цифр
X соответствует любому числу от 0 до 9
Z соответствует любому числу от 1 до 9
N соответствует любому числу от 2 до 9
2 — приоритет, означает, что это действие будет выполнено вторым по счету.
Dial — это из самых используемых приложений asterisk. Оно предназначено для звонка на номер через определенную линию. Подробнее об этом приложении можно прочитать здесь ( voip.rus.net/tiki-index.php?page=Asterisk+cmd+Dial )
SIP/${EXTEN:1} — некое подобие regexp’ов. Например, при наборе номера 03799039 в канал будет отправлен номер 3799039.
@pstn_beeline — канал через который будет осуществлен звонок.
&SIP/${EXTEN:1}@example_num — другой канал через который будет осуществлен звонок в случае, если линия билайна занята или недоступна.
для того, чтобы получить контекст phone_local — нужно включить в него 2 контекста — phone_int и out_local; пользователю, которому подключен такой контекст (в примере выше это пользователь 112), разрешены звонки на городские номера.
2) Входящие звонки обрабатываются так:
3) Макросы
По сути своей макросы — это функции. Макросу можно передавать параметры, которые он будет использовать в зависимости от контекста. Обратиться к макросу можно следующим образом:
_[1-9]XX — номер по которому происходит дозвон.
n — приритет;
Macro — непосредственно приложение макрос.
int-dial — название макроса.
${EXTEN} — параметр, который будет передан макросу ( в данном случае номер телефона )
Подробнее о макросах читайте здесь ( voip.rus.net/tiki-index.php?page=Asterisk+cmd+Macro&highlight=Macro() ).
Макросы, которые мы используем в плане набора:
Почти во всех контекстах используется приложение AGI. Подробнее о приложении можно прочитать здесь ( voip.rus.net/tiki-index.php?page=Asterisk+cmd+AGI&highlight=AGI() ).
О том, как это приложение используем мы — в следующем разделе.
AGI приветствие
Задача.
Реализовать меню, которое работает следующим образом:
1) Выходные дни и нерабочее время — сообщение о том, что клиент позвонил в нерабочее время; озвучить время работы.
2) Рабочее время — приветствие; в зависимости от времени, переключить клиента на
• секретаря ( если клиент попал во время работы офиса );
• тех.поддержку в остальное рабочее время
Рабочим временем считается понедельник-пятница с 9 до 21; офис работает с 9 до 13 и с 14 до 18 по будним дням (с часу до двух в офисе обед).
Инструмент решения задачи.
Для решения задачи был выбран инструмент AGI.
AGI (Asterisk Gateway Interface) — это встроенный в Asterisk метод выполнения внешних скриптов (по аналогии с CGI для http серверов), который может расширить функциональность asterisk при помощи других языков программирования.
В качестве языка разработки выбран perl — как универсальный инструмент решения любой задачи. :-)
На cpan есть модуль Asterisk::AGI search.cpan.org/~jamesgol/asterisk-perl-1.03/lib/Asterisk/AGI.pm.
Плюсы AGI — простота разработки; гибкость. Минусы — значительно возрастает нагрузка на сервер. Скрипт компилируется при каждом обращении, а не кэшируется; в интернетах пишут, что AGI глючит, но за время работы у нас ( ~ 0.5 года ) проблем с этим не наблюдалось. Проблем с вычислительными мощностями у нас также нет.
Решение задачи.
Все входящие звонки направляем сюда (смотрите предыдущий раздел):
Обработчик входящего звонка (/var/lib/asterisk/agi/ivr.pl) будет иметь следующий вид:
Файл /var/lib/asterisk/agi/schedule.conf хранит в себе «исключительное» время, т.е. время когда офис работает не как обычно, например, праздничный или сокращенный день. Пример:
# 1 — дата (день.месяц)
# 2 — какой день (параметр необязателе)
# 0-нерабочий либо пустой
# 1- обычный рабочий ( [9,13,18,21] ) либо массив
# 2.1 — время начала работы офиса (9)
# 2.2 — обед ( 13, т.е. с 13 до 14 )
# 2.3 — время окончания работы офиса (18)
# 2.4 — время окончания работы тех.поддержки
# дата вводится без нулей. 06.11 — не работает; 6.11 — работает
29.12 [9,11,17,20]
31.12
29.12 [9,11,17,20] ( 29 декабря ) — сокращенный день. Офис работает с 9 до 17; обед с 11 до 12; техническая поддержка работает до 20.
31.12 — нерабочий день.
AGI обработчик для звонков
Задача.
При звонке на номер звонок должен быть переадресован через определенный таймаут/занятости/не ответу/недоступности на другой номер (как правило, это одна из очередей). «Таймаут» и «другой номер» — переменные динамичные — для каждого номера они могут быть заданы индивидуально.
Инструмент.
Как и в прошлом разделе — AGI.
Решение задачи.
Внутренние номера сотрудников хранит база данных mysql в таблице users.
Создадим таблицу:
num — номер телефона сотрудника;
timeout — время в секундах, через которое звонок будет переадресован;
queue — номер очереди, куда будет переадресован звонок.
добавим записи для номеров:
проверим, что получилось:
SELECT * FROM users;
+-----+---------+-------+
| num | timeout | queue |
+-----+---------+-------+
| 101 | 10 | 300 |
| 106 | 20 | 0 |
| 112 | 20 | 0 |
+-----+---------+-------+
При звонке на 101 через 10 секунд звонок уйдет на 300 номер (у нас это номер технической поддержки); при звонке на 112 или 106 звонок никуда не уйдёт, а просто завершится через 20 секунд.
Обратиться к обработчику можно следующим образом( AGI(/var/lib/asterisk/agi/dial_internal.pl, ${ARG1}) ):
В dialplanе это:
Номер телефона попадает в макрос переменной ${EXTEN}, а потом передаётся обработчику /var/lib/asterisk/agi/dial_internal.pl с помощью ${ARG1}.
Код обработчика:
Аудиологи звонков
Все звонки записываются исключительно в рабочее время. В записи звонков так же используется AGI. Можно было бы обойтись и без него, но гораздо удобнее, когда логи раскладываются в отдельные директории.
Пример файла лога: ./2013/03/28/20130328.150550.9033779401.wav,
т.е. ./год/месяц/день/год_месяц_число.час_минут_секунда.номер_с_которого_осущ._звонок.wav
имя файла спроектировано таким образом, чтобы можно было бы сложить все файлы в одну директорию и grep'нуть по определенному параметру (номеру телефона/времени и т.п.)
Код обработчика /var/lib/asterisk/agi/monitor.pl:
Подробнее о приложении MixMonitor можно прочитать здесь ( www.voip-info.org/wiki/view/MixMonitor )
Очереди
С очередями всё относительно просто. Конфиг называется queues.conf. Очереди у нас 2 — техническая поддержка (номер 300) и бухгалтерия (301):
Подробнее о возможностях очередей можно прочитать здесь:
www.voip-info.org/wiki/view/Asterisk+config+queues.conf
Настройка внешних линий через linksys spa-3000
Задача.
В linksys spa-3000 есть один fxo-порт и один fxs. При звонке по номеру, подключенному к голосовому шлюзу ( далее г.ш. ), звонок нужно направить на fxs порт (там у нас стоит факс). При этом у нас должна быть возможность
1) совершать звонки через линию, подключенную к fxo порту из офиса;
2) переключать на номер факса, если звонок пришёл через другую линию;
3) звонить с факса через любую линию, подключенную к станции.
Решение.
Для того, чтобы осуществить задуманное, нужно настроить г.ш. следующим образом. Переходим на страницу Admin login->Advanced->PSTN Line:
Proxy: 10.0.0.5 # (ip станции)
Outbound Proxy: 10.0.0.5 # (ip станции)
Register: yes
User ID: pstn_beeline
Password: pass_for_beeline
# для того, чтобы звонок поступал в обход станции сразу на факс.
Dial Plan 2: (<:@gw0>)
PSTN Caller Default DP:2
Настройка внешней линии на станции описана в разделе внешние линии (pstn_beeline).
106 номер fax:
Proxy: 10.0.0.5 # (ip станции)
Outbound Proxy: 10.0.0.5 # (ip станции)
Register: yes
User ID: 106
Password: pass_for_fax
настройка внутреннего номера на станции описана в разделе пользователи и контексты исходящих звонков (106)
Полезные команды
asterisk -r — доступ к командной строке asterisk
asterisk -rx 'sip show peers' — вывести в консоль список подключенных пользователей без входа в консоль asterisk. С ключом -x можно выполнять любую команду, не заходя в консоль asterisk
Команды, консоли asterisk, которые у нас используются чаще всего:
sip reload — перезагрузить информацию из конфига sip.conf
dialplan reload — перезагрузить план набора
sip show channels — список созданных каналов
sip set debug ip ip_адрес_peer'a — включить debug конкретного канала. Показывает пакеты которые ходят между нашей станцией и удаленной станцией. Незаменимо для отладки
core set verbose 3 — включить режим отладки. Показывает какие приложения выполняются во время создания канала.