Тема актуальная. Для меня как для корпоративного телефониста лет пять-десять назад всегда была задача настроить функцию 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'а

Комментарии (10)


  1. BoDRbI
    28.05.2015 12:57
    +1

    Спасибо за статью, интересно было прочитать. Возник вопрос, а почему Вы использовали Node.js как промежуточное звено, а не прямое обращение в Mongo из AGI скрипта?


    1. antirek Автор
      28.05.2015 13:17

      Немного не понял вопроса. Здесь нет как такового AGI-скрипта, AGI-запрос идет сразу на AGI-сервер (AGI(agi://localhost:3000)), который написан на Javascript'е для выполнения на node.js. AGI-сервер при запуске также подключается к mongodb и работает в режиме ожидания запросов от астериска. Пришел запрос из диалплана — работает сценарий — взять номер, сделать получить направления операторов из БД, найти подходящее, вернуть статусы в диалплан астериска.

      Или вопрос был: а зачем этот Node.js здесь вообще, можно написать простой AGI-скрипт, который будет работать также?


      1. BoDRbI
        28.05.2015 13:32
        +1

        Спасибо, я понял Вас. Я подумал, что из диалплана происходит обращение к AGI-скрипту, который в свою очередь обращается к сервису на Node.js.


  1. antivoland
    29.05.2015 10:46
    +1

    За статью об реализации такой возможности в астериск(хотя и не нативно) — спасибо.

    Не рекламы ради…
    Мы уже давно пользуемся freeswitch с модулем mod_lcr.


    1. antirek Автор
      29.05.2015 12:43

      вот и меня мучает вопрос: почему такой простой функционал не реализован среди стандартных модулей астериска?

      freeswitch после астериска вообще песня: )


  1. f1045
    29.05.2015 15:17
    +1

    Хочется какой-то способ временно выключать звонки через какого-то оператора. Может быть действительно через задание весов, но чтобы был способ управлять этим не только через вебинтерфейс, но и через cli/agi

    (например для ситуаций, когда у оператора авария, но звонки он не отбивает, а принимает, просто дальше они не проходят. Или для тарифных планов с каким-то количеством включённых бесплатных минут в день\месяц, чтобы выбрать их, а потом через этот пир по возможности не звонить)


    1. antirek Автор
      29.05.2015 17:09

      ок, спасибо за комментарий по теме развития lcr finder'а.

      при аварии на стороне оператора, наверное, таки удобнее веб-интерфейс: зашел, выключил кнопкой, позвонил оператору, выяснил время устранения, затем позже зашел опять, включил, проверил звонком.

      вот с тарифными планами интереснее: надо учитывать сколько минут проговорил уже, т.е. или дополнительный запрос в agi делать или cdr анализировать, получается биллинг: )

      про включение/выключение через cli/agi не понял: делать выключение оператора из команды консоли или по звонку?


      1. f1045
        29.05.2015 19:21
        +1

        Ну вот да, тащить внутрь LCR-логики статистику по звонкам — наверное излишне. Я это могу и сам в диалплане или где-то снаружи посчитать по CDR, просто чтобы были ручки для выключения\включения пиров в LCR\задания весов. Из консоли, или передавая какие-то параметры в AGI


        1. antirek Автор
          01.06.2015 08:06

          Подумал, что если добавить ручки для включения операторов в веб-интерфейс, то поскольку там используется angular, который будет дергать определенные url и получать результат в json, то эти же запросы могут быть доступны и для сторонних приложений.

          Еще можно просто передавать список требуемых операторов в параметрах AGI запроса и получать сравнение только по ним.


  1. antivoland
    29.05.2015 17:31
    +1

    или анализ параметров при звонках на направления (средняя длительность, количество не ответов и тд) с апдейтом направления для выставления «веса».
    На это все навесить уведомление админа о том что направление косячное и в итоге чтото будет похоже на VoIP Studio для Mera по функционалу.