IP-телефония на базе Asterisk
Введите свой номер телефона
и мы перезвоним вам
Решаем Ваши бизнес-задачи с помощью IT-технологий. Знаем, как сделать лучше, быстрее и дешевле. Наш опыт – на службе Вашего бизнеса.
Не все герои носят плащи. Сотни техических статей, написанных инженерами нашей компании. Делимся опытом и своими знаниями со всем сообществом.
Сотни функций и возможностей Asterisk помогут вывести коммуникации в Вашей компании на принципиально новый уровень. Технические ограничения – фантазия Заказчика.
Вы платите за систему, которая будет полностью соответствовать Вашим ожиданиям, требованиям и будет драйвером роста Вашего бизнеса
Идти в ногу со временем или оставаться на старых технологиях? Такой вопрос не стоит перед нашими клиентами. Решаем самые смелые задачи для Колл-Центров. Строим с нуля или работаем с существующими.
Поместите свой бизнес в эпицентр продаж. Интеграция IP-телефонии и CRM даст новый и мощный импульс Вашему Отделу Продаж и выведет компанию на три шага впереди конкурентов.
Подбираем для клиентов такие тарифы, которые ему редко получится найти на рынке самостоятельно. Работаем с 100+ операторов связи в интересах клиента.
Разработки, созданные нашей командой под запросы клиентов. Не отказывайтесь от инноваций. Мы поможем идти с ногу со временем.
Умные всю жизнь учатся, а остальные всегда все и так знают. Мы проводим обучение более 8 лет и выпустили более 1000 специалистов по Asterisk и Mikrotik. Проводим ежегодную конференцию Asterisk.
Купить наш опыт дешевле, чем набивать свои шишки. Мы реализовали более 800 проектов и накопили экспертизу для того, чтобы идеально выполнить Ваш проект.
Правильный выбор оборудования позволяет сэкономить от 20 до 50% бюджета телефонии. Мы предельно внимательно подойдем к выбору «железа» в Ваш проект.
Наши цены доступны не только для Москвы, но и для регионов. А вложения в нашу экспертизу обычно окупаются за несколько месяцев.
Работаем с 2011 года. Собрали отличную команду реальных фанатов своего дела. Подходим к работе с душой и ответственностью.
Итак, меня зовут Спиридонов Дмитрий, я директор компании Ringoline — директор, программист, техническая поддержка, ну в общем вы поняли. Мой доклад сегодня называется «Разработка офисной АТС маленькой командой». Ключевой акцент я бы хотел сделать именно на слове «маленькой», потому что, если вы часть какого-то большого конгломерата, у вас не будет тех проблем, которые возникали у меня. В худшем случае вы можете просто съездить в Алабаму, купить там Digium и заставить его на себя работать. Если же вам не так повезло, то надеюсь, мой доклад будет вам полезен — либо полностью, либо частично.
Началась моя история где-то в 2015 году. К этому моменту за плечами было 6 лет разработки на C++, был небольшой опыт в PHP, уже был опыт разработки VoIP-приложений: я занимался интеграцией FreePBX. Ощущения от FreePBX тогда были двоякими. С одной стороны, если клиенту FreePBX «прямо из коробки» подходил, всё получалось супер: можно было запустить проект за день, максимум за два, и результат действительно был заметен. Клиент доволен, ты тоже видишь большую сделанную работу — всё прекрасно.
Но как только клиенту требовалось что-то нестандартное — отойти от возможностей FreePBX и сделать что-то своё, необычное — всё превращалось в мучение. Стоило залезть в недра FreePBX (а напоминаю, это был 2015 год), становилось ощущение «как в Простоквашино»: каждый что-то где-то подписал, какие-то кусочки кто-то склеил, сплошные ассоциативные массивы, и это несмотря на то, что в PHP уже во всю работало объектно-ориентированное программирование. Было очевидно, что можно всё сделать гораздо лучше и удобнее.
Второе, во что мы тогда упирались, — это отчётность. Для FreePBX, как и для многих решений, есть стандартные отчёты по колл-центру, и они более-менее нормальные. Но как только речь заходила о построении отчётов для остальных отделов (всяких отделов продаж и т.д.), возникали огромные проблемы. Например, у крупного клиента руководители отделов хотели счёт разных метрик и пропущенных вызовов каждый по-своему: один говорил «пропущенным считается, если не ответили и после меня тоже не ответили», другой — что-то ещё. Нужно было учитывать не только кто позвонил и кто ответил, а то, как конкретно звонок шёл по схеме: сколько звонил на каждом этапе, где остановился, и т.д. FreePBX для этого не предлагал вообще ничего.
Следующее — отсутствие API на тот момент. Сделать его было сложно, потому что во FreePBX все настройки передаются в Asterisk «отложенно»: если вы делаете свою веб-страницу, на которую приходит запрос, и она создаёт сотрудника прямо во внутренностях Asterisk, то применить это всё всё равно нужно через скрипт, который запускается кнопкой «Apply» и заливает абсолютно все настройки. Понятно, что такой вариант — не то, что требуется при наличии сторонних интеграций.
Плюс у FreePBX тогда был громоздкий веб-интерфейс, основанный на терминах Asterisk. А у многих администраторов и технических специалистов в компаниях этих знаний попросту нет, и хотелось сделать что-то более простое для пользователя.
Набралось к FreePBX много хотелок и претензий, появилось понимание, как всё это можно переделать, и так мы начали делать свою разработку. Хотелось сделать что-то вроде «Битрикса» — некую «коробочную» версию, которую клиенты могут дорабатывать под себя. Мы создаём общий каркас, а дальше интеграторы, кому надо, допиливают специфические фичи.
Эти принципы сложились ещё до начала разработки продукта и совершенствовались в процессе:
Мы хотели сделать коробку, которую каждый сможет доработать под себя. Для этого за основу взяли:
В нашей команде нет человека со скиллами дизайнера. Сначала я хотел обратиться в веб-студию, но там только за ТЗ и дизайн одной страницы запросили 113 тысяч, из которых 100 — за само ТЗ, а 13 — за макет первой страницы. Для маленького стартапа это неподъёмно. Поэтому мы обратились к фреймворкам: Bootstrap или Semantic UI. Они позволяют сделать «просто хороший» интерфейс, не уникальный, но удобный, с продуманной системой компонентов. Для начала этого оказалось достаточно.
Сильно заморачиваться с идеальным диалпланом на старте мы не стали и взяли классический вариант, как во многих дистрибутивах Asterisk: веб-интерфейс генерирует конфиги. Можно использовать шаблонизаторы (например, Twig) или генераторы в стиле FreePBX (отдельный класс под каждую аппликацию, всё складывается в массив объектов, а потом преобразуется в текст). Мы выбрали второй подход — так удобнее для дальнейшей кастомизации и разбора генерируемых строк.
Первый релиз вышел где-то через 6–8 месяцев, в 2015 году. Те, кто давно в сфере, наверняка узнали интерфейс, похожий на Sipuni. Нам он зашёл отлично. Идея «схемы» далеко не нова: до Sipuni были и Visual Dialplan, и Octel, и другие. Но у большинства конкурентов маленькие «кирпичики» разрастаются в диалплан на несколько экранов, и читать это потом невозможно. Sipuni же использует более крупные логические блоки, и нам это понравилось. Так что внешний интерфейс взяли «как у Sipuni», диалплан — «как у FreePBX», архитектуру — свою, на базе событийной шины и ООП.
Первая продажа состоялась через год. Помню этот день отлично. Ты целый год что-то пишешь, вкладываешь деньги, время, нервы. Появился клиент, который готов это тестировать. Я несколько дней всё вылизывал, ставил нагрузочные тесты. Поставил им систему в воскресенье вечером. Ночью каждые два часа просыпался и проверял, набирая их городской номер. До шести утра всё работало… А в шесть — тишина. Второй звонок — тишина. Третий… Я в 9:30 уже стоял под дверью офиса. Мысли были самые ужасные: сервер взломали, всё украли… Оказалось, просто была «севшая» батарейка BIOS, и при каком-то моргании электричества сервер сбросил дату и встал. Так «первый блин» оказался комом. Зато дальше пошло проще. На вторую установку я уже смотрел спокойнее, четвёртую едва ли помню.
В целом, первая версия прожила 3 года, и за это время я понял:
Главный минус первой версии — зависимость скорости применения настроек от их количества и «отложенное» применение по кнопке Apply. Мы фактически повторили в этом подходе FreePBX и его проблемы: полное применение настроек, долгая генерация при большом объёме, сложность с API. Мы начали обходить это костылями (RealTime для очередей, отдельные таблицы для переадресаций), но поняли, что так продолжаться не может.
Мы решили сделать всё «по максимуму» в RealTime, чтобы никакого dialplan reload
и никаких задержек при применении. Для диалплана мы использовали func_odbc
(или точнее RealTime Hash-функции), чтобы подгружать параметры вызова из базы. Например, если в диалплан приходит звонок на 901, Asterisk идёт в базу, читает параметры: «вызвать устройство DEV59E35 20 секунд, потом мобильный 929…» и т.д. Диалплан получается универсальным и не требует изменений при любом добавлении-удалении сотрудника.
Но оставалась проблема с «конкретными» экстенами вроде exten => 101,1,Dial(...)
. Мы сначала пробовали RealTime Dialplan, но там были проблемы с Hints. В итоге пришли к тому, что стали динамически добавлять нужные строчки через AMI-команду dialplan add extension
. Так Asterisk «на лету» получал нужные экстены, а мы дублировали их в базе, используя Static RealTime (или RealTime Static mode).
Таким образом, диалплан перезагружать было не нужно — всё правилось «на лету» либо в базе, либо через AMI. Очереди, Music on Hold и многие другие модули тоже легко шли в RealTime. С PJSIP на тот момент мы сильно мучились, потому что chan_sip
плохо дружил с RealTime, но выяснилось, что PJSIP (в версии Asterisk 13.0.1 или около того) уже неплохо работал с базой. Так мы полностью избавились от кнопки «Apply» и всех задержек.
Опасались за скорость: всё-таки теперь идёт запрос к базе на каждый вызов. Но замеры показали, что задержка микроскопическая (порядка микросекунд), и на качестве это не сказывается.
Вторая версия прожила два года. За это время мы успели дописать API для всех модулей (теперь это просто запись в базу), избавились от «Apply». Боялись, что при отключении электричества база будет «крашиться», но ни разу за всё время такого не случилось.
Недостаток стал очевиден: сложность разработки диалплана. Писать объёмную логику в extensions.conf
с ограниченным синтаксисом — удовольствие сомнительное, а нам нужно было давать возможность и клиентам, и интеграторам переписывать логику. Пришло понимание, что диалплан пора переводить на нормальный язык.
Первое, что приходит в голову, — вынести логику на AGI. У нас уже было написано множество модулей на PHP, были инструменты для генерации схемы. Но простой вызов AGI при каждом звонке, когда всё окружение PHP будет инициализироваться заново, давал задержку в полторы секунды (на слабой виртуалке). Даже на более сильных серверах это полсекунды и выше, что много для реальной АТС.
Идея — написать демон на FastAGI, чтобы инициализироваться один раз. Мы попробовали AMP (асинхронный PHP), но это слишком экзотично, мало библиотек и специалистов, а нам хотелось, чтобы клиенты и интеграторы могли сами дописывать логику. Попробовали pthreads
— столкнулись с проблемами передачи сокетов и нестабильной работой расширения.
В итоге мы пошли путём создания собственного демона на C++, в который встроили библиотеку PHP (SAPI). При запуске демон инициализируется один раз (создаются объекты, связи и т.д.), затем «замораживается». Когда поступает звонок, мы «клонируем» в отдельном потоке это окружение PHP — на это уходит порядка 10 миллисекунд. Для офисной АТС это очень быстро, мы тестировали 30 CPS (30 вызовов в секунду), и всё шло нормально.
Теперь диалплан в Asterisk — это фактически заглушка, которая сразу передаёт звонок на FastAGI, а вся логика прописана на PHP с полноценными классами, методами, библиотеками, где удобно работать со строками, массивами, БД, да хоть с отладчиком ставить breakpoints. Это реально ускорило разработку примерно втрое (по моим субъективным замерам, переписывая модули со второй версии на третью). Демон на C++ и PHP живёт уже два года, ни разу не упал и не потёк.
Если сейчас делать всё с нуля, я бы, наверное, посмотрел в сторону Node.js — она теперь отлично поддерживает async/await
, там множество библиотек и решений. Но когда мы всё начинали (году в 2018), Node.js была менее «дружественной» к таким задачам.
На что мы упираемся теперь? В сами аппликации Asterisk. Например, app_queue
иногда не хватает нужных флагов, мы её патчим. То есть подход «перевести логику в AGI» вывел нас на новый уровень, и теперь нас сдерживают лишь ограничения модулей Asterisk.
За всё это время мы сделали так, что:
FreePBX писала CDR, но для нестандартных отчётов это неудобно. Мы пробовали кастомные поля, дубли CDR-записей, но, по сути, мы не управляли CDR, мы пытались «обхитрить» Asterisk. Поэтому перешли на CEL (Channel Event Logging) и написали свой парсер, который складывает историю звонка в виде иерархии: от момента входа в систему до того, кто ответил, куда перевели, сколько секуд звонили на каждом этапе и т.д.
Выглядит это примерно так (пример для одного звонка):
Вложенность шагов видна в дереве: кто ответил, кто не ответил, был ли перехват или перевод. Благодаря этому можно строить все нужные отчёты. Например, считать пропущенным вызов только если сотрудник не ответил и никто другой тоже не взял, или учитывать длительность ожидания и т.д.
Вот пример «конверсии»: синие столбики — все поступившие звонки, зелёные — отвеченные, красные — пропущенные. Но звонки могли идти на разные отделы, где-то клиенты ждут часами, где-то кладут трубку через 20 секунд, а ещё есть голосовое меню, которое смещает время. Мы учитываем, как звонок шёл по дереву: кто какую кнопку нажал, в какой момент. Всё это хранится в нашей базе в удобном формате.
Не повторяйте наших ошибок: не забивайте на обновления. Ошибки бывают у всех, и когда клиент звонит с багом, хочется быстро поправить у него и забыть. Но потом другой клиент обращается с тем же багом — а за это время структура базы уже изменилась, вышла новая версия, и совместимость ломается. В итоге вы вручную «допиливаете патчик» на старой версии. Чтобы избежать этого, мы разбили проект на релизы и предусмотрели скрипты конвертации.
А ещё вопрос безопасности: мы научены опытом FreePBX, который нередко взламывали. Поэтому в веб-интерфейсе пользователь не имеет рут-прав. С правами рута можно выполнить лишь несколько команд, в числе которых перезапуск сервисов и apt install ringapbx
(наш пакет). Мы выкладываем обновления в собственный репозиторий Debian, и при установке новый пакет обновляет систему, выполняя нужные скрипты с правами root. Это решает задачу и обновлений, и начальной инсталляции.
Билеты уже в продаже!
Я - Кондрашин Игорь, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.
Быстро узнать мобильного или городского оператора. Впишите номер