Екатерина
25.07.2019
295

Региональная маршрутизация.

Оглавление Введение func_odbc. Назначение и использование Создание задачи Наполнение таблицы номеров Соответствующее направление звонка Введение Если ваша компания крупная и насчитывает много филиалов в разных регионах РФ, не совсем удобно будет для вас обрабатываться звонки Владивостока в Москве, а все из-за разницы во времени. Поэтому была придумана идея разработать функционал для определения региона звонящего, а […]

Оглавление

  1. Введение
  2. func_odbc. Назначение и использование
  3. Создание задачи
  4. Наполнение таблицы номеров
  5. Соответствующее направление звонка

Введение

Если ваша компания крупная и насчитывает много филиалов в разных регионах РФ, не совсем удобно будет для вас обрабатываться звонки Владивостока в Москве, а все из-за разницы во времени. Поэтому была придумана идея разработать функционал для определения региона звонящего, а также направления его звонка в соответствующий филиал или региональный центр федерального округа.

Текущая разработка предназначена для телефонных номеров РФ. В дальнейшем планируется её доработать до совершенства и добавить определение страны звонящего с последующей маршрутизацией вызова.

В статье будут использоваться URL ссылки на сайт россвязи. Будьте внимательны, ссылки могут поменяться. Актуальность статьи 1 июля 2019.

func_odbc. Назначение и использование

Для понимания всех действий, которые будут использоваться в этой статье в данном разделе будет описано краткое описание модуля func_odbc. Будет разобрано его использование. А также возможные параметры использующиеся в func_odbc.conf

Модуль func_odbc предназначен для кастомизации диалплана, при использовании обращений к базам данных по средствам ODBC коннектора. Этот модуль позволяет создавать дополнительные функции диалплана ODBC_<function’s name> для обращения к БД.

По умолчанию, при подключении этого модуля в функционал диалплана астериска добавляются две функции и одно приложение:

  • ODBC_FETCH — используется  для запросов, помеченных ,как multirow. Возвращает идентификатор запроса, из которого можно получить данные. Т.о. реализуется фактическая выборка результатов.
    При использовании этой функции доступна переменная ${ODBC_FETCH_STATUS}. Она может принимать 2 значения SUCESS и FAILURE
  • SQL_ESC – позволяет передавать в SQL запрос данные, использующие в значении символ “”.
  • ODBCFinish — очищает успешно полученные данные многострочного запроса ODBC.

Далее будет дано описание параметров, используемых в файле func_odbc.conf, а также пример заполнения файла конфигурации: Первоначально оформляется название контекста в квадратных скобках. Пр. [TEST]

Далее это надвание будет использоваться как функция диалплана ODBC_TEST

readhandle – указывается список DSN имён, которые установлены в файле res_odbc.conf. Этот список используется при указанном параметре readsql. Имена перебираются последовательно, пока запрос и readsl не выполнится успешно.

Может собержать до 5 DSN имен
  • writehandle — разделенный запятыми список DSN имён из res_odbc.conf, используемых при указании параметров writesql и insertsql. Правила использования, такие же как в readhandle.
  • readsql – параметр выполняющийся при чтении из функции диалплана ODBC_TEST.
  • writesql – параметр выполняющийся при записи из функции диалплана ODBC_TEST.
  • insertql – параметр выполняющийся при добавлении из функции диалплана ODBC_TEST.
  • prefix – используется для замены префикса ODBC в имени функции, для группировки используемых функций и отделения их от других запросов
  • synopsis — позволяет оставить описание (synopsis) функции, если использовании команды «core show function ODBC_TEST»
core show function (pic1.png)

rowlimit – указывается, для ограничения количества строк возвращаемых указанной функцией.

[TEST]
prefix = TESTDB
readhandle = asteriskcdrdb
synopsis = get a name from test table by ${ARG1}, where ${ARG1} is caller num
readsql = SELECT name from test_num where num like ‘%${SQL_ESC(${ARG1})}%’
rowlimit = 1
example func_odbc.conf. (pic2.png)

Создание задачи

Предположим, что к Asterisk подключено четыре офиса. Региональное расположение филиалов — это Екатеринбург, Хабаровск, Калининград и центральный офис — это Москва. И необходимо:

  1. Вызовы из Уральского Федерального Округа (УФО) направлять в филиал в Екатеринбурге.
  2. Вызовы из Дальневосточного Федерального Округа (ДВФО) направлять в Хабаровский филиал.
  3. Вызовы поступающие из Северо-Западного Федерального Округа (СЗФО) направлять в калининградский филиал.
  4. Все остальные вызовы направлять на Москву.

Первоначально взглянув на задачу — она кажется сложной. Но если все детально рассмотреть и составить ментальную схему, то задача становится выполнимой и легкой.

Разделим процесс на несколько пунктов:

  1. Составим схему звонков
  2. Создадим таблицу регионов использую открытые данные россвязи
  3. Будем выполнять маршрутизацию

Итак приступим к созданию схемы. В данной статье было принято отталкиваться от самого удаленного региона постепенно приближаясь к МСК.

Схема вызовов (pic3.png)

Наполнение таблицы номеров

После того, как схема была создана, перейдем к наполнению таблицы с номерами и регионами. Для начала подключившись к АТС по ssh создадим директорию regions, куда будем скачивать CSV файлы россвязи. Эта директория будет находиться по следующему пути: /usr/src/

Далее все команды выполняются относительно директории /usr/src/regions
# cd /usr/src/
# mkdir regions
#  cd regions/

Теперь находясь в директории regions скачаем CSV файлы с сайта россвязи. Их можно скачать к себе на ПК перейдя по этой ссылке https://rossvyaz.ru/deyatelnost/resurs-numeracii/vypiska-iz-reestra-sistemy-i-plana-numeracii и затем перенести на АТС.

CSV файлы Россвязи. (pic4.png)

Также можно их получить из консоли АТС, используя утилиту wget.

#  wget https://rossvyaz.ru/data/ABC-3xx.csv
#  wget https://rossvyaz.ru/data/ABC-4xx.csv
#  wget https://rossvyaz.ru/data/ABC-8xx.csv
#  wget https://rossvyaz.ru/data/DEF-9xx.csv

Когда закончится скачивание файлов, нужно поменять кодировку файлов из cp1251 на UTF-8 командой iconv. И командой dos2unix заменим переносы строк на Unix-овые.

# iconv -f CP1251 -t UTF-8 "ABC-3xx.csv" > "ABC-3xx_UTF-8.csv"
# dos2unix "ABC-3xx_UTF-8.csv"

Таким образом это необходимо выполнить для всех скаченных файлов:

  • ABC-3xx.csv
  • ABC-4xx.csv
  • ABC-8xx.csv
  • DEF-9xx.csv

Далее необходимо отредактировать полученные файлы, а именно, удалим в них четвёртый столбец, чтобы осталися префикс, начало диапазона, конец диапазона, название оператора, регион. Для этого воспользуемся утилитой sed.

# sed -ri 's|^([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);([^;]+).*$|\1;\2;\3;\5;\6|' "ABC-3xx_UTF-8.csv"

Редактирование и работа с файлами закончена. Переходим к работе с Mysql. Здесь будет создана таблица где, будут храниться данные csv фалов. Также будет рассмотрен способ заполнения таблицы из скаченных файлов.

Для написания статьи используется Freepbx 13. Поэтому далее будет использоваться стандартная БД asteriscdrdb

Перейдем в консоль mysql в БД asteriskcdrdb.

# mysql -u freepbxuser -p<FREEPBXUSER_PASSWORD> asteriskcdrdb
<strong>Выше в примере используется пример подключения к mysql под учетными данными пользователя freepbxuser. Эти данные можно узнать посмотрев файл /etc/freepbx.conf, если вы используете freepbx. Если у вас нет web интерфейса, то используйте свои данные для подключения.</strong>

Используя команды Mysql CREATE TABLE создадим таблицу rossvyaz.

> CREATE TABLE `rossvyaz` (
   `prefix` smallint(3) NOT NULL,
   `num_from` int(7) NOT NULL,
   `num_to` int(7) NOT NULL,
   `operator` varchar(255) NOT NULL DEFAULT "",
   `region` varchar(255) NOT NULL DEFAULT "",
   KEY `prefix` (`prefix`),
   KEY `num_from` (`num_from`),
   KEY `num_to` (`num_to`)
 ) DEFAULT CHARSET=utf8 ENGINE=InnoDB

В целях экономии ресурсов сервера при создании таблицы используются типы данных smallint, int иvarchar.

Про типы данных используемых в mysql можно посмотреть здесь (<a href="http://artemfedorov.ru/etc/mysql/field-types/">http://artemfedorov.ru/etc/mysql/field-types/</a> )

Далее командой LOAD DATA загружаем в созданную таблицу данные из csv файлов. Разделитель полей устанавливаем «;» и переход на новую строку указываем «\n».

В значении команды INFILE указывается полный путь к csv файлам
> LOAD DATA INFILE '/usr/src/regions/ABC-3xx_UTF-8.csv' INTO TABLE `rossvyaz`
FIELDS TERMINATED BY ';'
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(`prefix`,`num_from`,`num_to`,`operator`,`region`);

Эту команду необходимо выполнить для каждого файла. После импорта данных перейдем к конфигурированию файла func_odbc.conf. Контекст назовем [REGION], а в параметр readsql укажем необходимую строку, для поиска нужного региона.

[REGION]
dsn=asteriskcdrdb
prefix=TEL
synopsis=Return name of region by prefix <variable>${ARG1}</variable> and by phone number <variable>${ARG2}</variable>
readsql=SELECT `region` FROM `rossvyaz` WHERE `prefix`=${SQL_ESC(${ARG1})} AND `num_from`<=${SQL_ESC(${ARG2})} AND `num_to`>=${SQL_ESC(${ARG2})} LIMIT 1;
Параметр dsn можно использовать вместо раздельных параметров readhandle и writehandle.

После внесения правок, сохраняем изменения и применяем настройки командой «module reload func_odbc.so» в консоле asterisk. Если у вас все выполнено правильно вы увидите применение новой функции для астериска см. скриншот ниже.

Module reload func_odbc.so (pic5.png)

Все преднастройки выполнены, теперь переходим к настройке маршрутизации.

Соответствующее направление звонка

Перед выполнением настройки маршрутизации определим регионы относящиеся к указанным ранее округам:

Теперь с указанными данными проще работать.

Определим номера очереди для каждого региона:

  • 600 — Москва
  • 601 — СЗФО
  • 602 — ДФО
  • 603 — УФО

Для обработки номера звонящего необходимо создать отдельный контекст, назовем его [from-trunk-pre]. В этом контексте будем производить действия с номером звонящего.

Чтобы как-то оперировать с созданной нами таблицей определим префикс и искомый номер, определим эти переменные, как PREFIX и NUMBER.

[from-trunk-pre]
exten => _X.,1,Set(__FROM_DID=${EXTEN})
same  => n,Set(PREFIX=${CALLERID(num):0:3})
same  => n,Set(NUMBER=${CALLERID(num):3})

После того, как были определены номер и префикс, следующей строкой обратимся к БД для поиска результата, воспользуемся зарегистрированной ранее функцией TEL_REGION. Результат будет занесен

same  => n,Set(REGION=${TEL_REGION(${PREFIX},${NUMBER})})

Определим несколько переменных, которые будут отвечать за совпадение с облостями, входящими в необходимые нам округа.

  • SZFO_MATCH – Северо-Западный федеральный округ
  • DFO_MATCH – Дальневосточный федеральный округ
  • UFO_MATCH – Уральский федеральный округ
same  => n,Set(SZFO_MATCH=0)
same  => n,Set(DFO_MATCH=0)
same  => n,Set(UFO_MATCH=0)

Далее встроенной функцией диалплана REGEX будем определять совпадение. При совпадении с указанными выше областями будем устанавливать переменную в значение 1, иначе она также останется в значении 0.

Синтаксис функции REGEX можно посмотреть командой core show function REGEX.

same  => n,ExecIf(${REGEX("Санкт - Петербург" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Ленинградская обл" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Мурманская обл" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Новгородская обл" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Республика Карелия" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Республика Коми" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Псковская обл" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Ростовская обл" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Архангельская обл" ${REGION})}?Set(SZFO_MATCH=1))
same  => n,ExecIf(${REGEX("Калининградская обл" ${REGION})}?Set(SZFO_MATCH=1))

Аналогично указанному выше примеру заполняем с другими округами, подставляя записанные выше области/республики и переменные DFO_MATCH и UFO_MATCH.

same  => n,ExecIf(${REGEX("Хабаровск" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Хабаровский край" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Приморский край" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Амурская обл" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Магаданская обл" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Республика Саха" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Сахалинская обл" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Камчатский край" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Еврейская автономная обл" ${REGION})}?Set(DFO_MATCH=1))
same  => n,ExecIf(${REGEX("Чукотский АО" ${REGION})}?Set(DFO_MATCH=1))
;--------------------------------------------------------------------
same  => n,ExecIf(${REGEX("Свердловская обл" ${REGION})}?Set(UFO_MATCH=1))
same  => n,ExecIf(${REGEX("Челябинская обл" ${REGION})}?Set(UFO_MATCH=1))
same  => n,ExecIf(${REGEX("Ямало-Ненецкий АО" ${REGION})}?Set(UFO_MATCH=1))
same  => n,ExecIf(${REGEX("Ханты - Мансийский - Югра АО" ${REGION})}?Set(UFO_MATCH=1))
same  => n,ExecIf(${REGEX("Тюменская обл" ${REGION})}?Set(UFO_MATCH=1))
same  => n,ExecIf(${REGEX("Курганская обл" ${REGION})}?Set(UFO_MATCH=1))

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

same  => n,GotoIf($[${SZFO_MATCH} = 1]?ext-queues,601,1)
same  => n,GotoIf($[${DFO_MATCH} = 1]?ext-queues,602,1)
same  => n,GotoIf($[${UFO_MATCH} = 1]?ext-queues,603,1)

Чтобы заработали эти правила, необходимо в параметрах транка с оператором связи указать context=from-trunk-pre. Применяем изменения диалплана и настроек транка кнопкой «Apply Config» и проверяем.

Заключение

Таким образом мы настроили маршрутизацию на разные филиалы в зависимости от региона звонящего. Данная реализация позволит разгрузить секретаря, избавит сотрудников от лишних переводов.

Хотелось бы дополнить, что текущая схема очень примитивна, её можно расширять добавляя различные округа, районы или же города. Плюсом ко всему будет если прикрутить базу с международными номерами. Также можно дополнить всю логику привязав все к временным зонам, что избавит от пропущенных звонков.

 
avatar
  Подписаться  
Уведомление о

Остались вопросы?

Я - Першин Артём, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование

ближайшие курсы

ближайшие Вебинары

ONLINE

Why Choose HUGE?

Unlimited pre-designed elements

Each and every design element is designed for retina ready display on all kind of devices

User friendly interface and design

Each and every design element is designed for retina ready display on all kind of devices

100% editable layered PSD files

Each and every design element is designed for retina ready display on all kind of devices

Created using shape layers

Each and every design element is designed for retina ready display on all kind of devices