Маршрутизация по наименьшей стоимости (LCR) в Asterisk
Тема актуальная. Для меня как для корпоративного телефониста лет пять-десять назад всегда была задача настроить функцию ARS на Panasonic TDA100/200/600 или LCR на LG LDK100/300. В общем, сделать так чтобы подешевле звонить было. Но времена меняются, и сейчас у многих компаний используется Asterisk, а я уже не настраиваю УПАТС Panasonic, LG и прочие.В Астериске, всем известно, вся маршрутизация делается в диалплане. Но если у оператора много направлений и цена на каждое из них различна, то в диалплане получаются портянки на несколько страниц. Решения разные: кто-то разбивает по разным файлам диалплана, использует макросы, кто-то подключает к работе БД, кто-то выносит на отдельный сервис.
Я хочу поделиться своим решением: вынести поиск оператора с наименьшей стоимостью заданного направления в стороннее приложение на node.js, с которым Астериск взаимодействует посредством AGI.
Задача
Получить простое и быстрое решение для определения оператора, у которого наименьшая стоимость минуты звонка, которое также быстро устанавливается и настраивается.
С одной стороны с приложением должен взаимодействовать Астериск, передавая направление звонка и запрашивая оператора с наименьшей стоимостью. С другой стороны через веб-интерфейс с приложением взаимодействует пользователь, который добавляет операторов связи, направления и их стоимость.
Схема
LCR Finder
Подробная установка в описании к проекту на гитхабе. Но мы воспользуемся заготовкой приложения lcr-finder-app (клонируем, устанавливаем зависимости и запускаем приложение).
Установленное приложение открывает два порта для соединений, одно для Астериска — запросов по AGI, другое для веб-интерфейса.
Затем настроить Астериск в файле extensions.conf достаточно выполнить запрос в AGI и сделать вызов по результату.
exten=>_X.,1, AGI (agi://localhost:3000) exten=>_X., n, Dial (SIP/${LCR_RESULT}/${EXTEN}) Также после запроса в AGI к LCR Finder’у устанавливаются переменные LCR_STATUS, LCR_RESULT, LCR_SEQUENCE. LCR_STATUS — FAILED, SUCCESS в зависимости от результата поиска, LCR_RESULT — имя оператора с наименьшей стоимостью, LCR_SEQUENCE — список всех операторов через запятую, отсортированных в порядке возрастания стоимости. LCR_SEQUENCE позволяет реализовать failover, если оператор с наименьшей стоимостью не пропускает вызов, то можно взять следующего.
В веб-интерфейсе, который на angular.js быстро сверстал мой коллега Анатолий, все достаточно лаконично: добавляем оператора, добавляем к нему направления и стоимость. Во вкладке поиска можно проверить стоимость направление у операторов.
Вопрос к астерискерам: нужно ли развивать эту систему? Стали бы вы пользоваться ей в своих инсталляциях с Астериском. Сейчас здесь нет загрузки Excel файлов с направлениями (я сначала командой в mongodb загружаю направления, т.к. у меня есть небольшой скрипт для этого, а потом в веб-интерфейсе я или заказчик меняем цены по необходимости). Есть еще задумка с весом оператора, т.к. иногда цена не единственный параметр влияющий на выбор оператора.
Есть ли подобные системы? Конечно, да. Например, знаю, что некоторые используют для A2Billing для LCR, еще есть проект LCDial.sh (не знаю, кто-нибудь им пользуется), кто-то использует такие скрипты.
Надеюсь на конструктивную критику и предложения по улучшению. Думаю, что поможет кому-нибудь сэкономить дополнительные средства для развития в наше непростое время.
P.S. Небольшое видео по установке lcr-finder’а[embedded content]