Настройка ODBC-подключения и получение данных из БД

Ранее мы научились строить логику диалплана на условиях и переходах. Но до сих пор данные были «зашиты» в конфиги. В больших системах это неудобно: любое изменение требует правки файлов. Чтобы АТС стала гибкой, она должна общаться с внешним миром.

Разберем, как подключить Asterisk к внешней базе данных (MariaDB или PostgreSQL). Это обеспечит динамическое подключение: логика звонка изменится сразу после обновления строки в таблице, без перезагрузки модулей.

Архитектура: как данные попадают в звонок

Asterisk связывается с базой через стандарт ODBC (Open Database Connectivity). Это универсальный переходник: Asterisk не важно, какая СУБД стоит «на той стороне», он общается с драйвером.

Взаимодействие устроено как иерархия уровней, показанная на Схеме 1.

  1. OS (Linux): Драйвер unixODBC и конфиг /etc/odbc.ini. Проверяем, видит ли система базу.
  2. Ресурсы Asterisk: Модуль res_odbc.conf. Создает пул соединений, чтобы не тратить время на авторизацию при каждом вызове.
  3. Функции диалплана: Модуль func_odbc. Превращает SQL-запрос в функцию, понятную Asterisk.

Шаг 1: Настройка res_odbc.conf

Допустим, в Linux уже настроен DSN (источник данных) с именем asterisk-connector. Теперь пропишем его в Asterisk.

Во FreePBX правки вносим в файлы с суффиксом _custom, чтобы интерфейс их не затер. Откройте /etc/asterisk/res_odbc_custom.conf:

[asterisk-db]
enabled => yes
dsn => asterisk-connector
username => asterisk_user
password => your_strong_password
pre-connect => yes
max_connections => 20
connect_timeout => 5
on_reconnect => SET NAMES utf8mb4 ; работаем с кириллицей корректно

⚡️ Важно: Параметр pre-connect => yes заставляет Asterisk держать соединение активным. Если база «проснется» только в момент звонка, абонент услышит тишину из-за задержки.

Проверьте статус в консоли Asterisk: odbc show. Если видите Connected — мост работает.

Шаг 2: Создание функций в func_odbc.conf

Инструмент func_odbc — это обертка. Вы описываете SQL-запрос, даете ему имя, а в диалплане используете его как переменную.

Создадим проверку статуса клиента. Если в базе стоит blocked, звонок не пройдет. В файле /etc/asterisk/func_odbc_custom.conf пишем:

[CHECK_STATUS]
dsn=asterisk-db
readsql=SELECT status FROM clients WHERE phone='${SQL_ESC(${ARG1})}'
  • readsql: запрос на чтение (SELECT).
  • ${ARG1}: первый аргумент, который мы передадим (номер телефона).
  • SQL_ESC(): 🛡 Защита. Экранирует спецсимволы, предотвращая SQL-инъекции. Всегда оборачивайте внешние переменные в эту функцию.

Шаг 3: Логика в диалплане

Теперь используем функцию в extensions_custom.conf. Код становится чище: данные живут отдельно, логика — отдельно.

[from-internal-custom]
exten => _XXXX,1,NoOp(Проверка абонента ${CALLERID(num)})
 ; Вызываем функцию и пишем результат в переменную
 same => n,Set(USER_STATUS=${ODBC_CHECK_STATUS(${CALLERID(num)})})
 
 ; Проверяем статус
 same => n,GotoIf($["${USER_STATUS}" = "blocked"]?denied:allow)
 
 same => n(denied),Playback(service-is-unavailable)
 same => n,Hangup()
 
 same => n(allow),Dial(PJSIP/${EXTEN},30)

Если менеджер в CRM заблокирует клиента, Asterisk узнает об этом мгновенно при следующем звонке.

💡 Совет эксперта: Всегда продумывайте план «Б». Если база недоступна и ${USER_STATUS} пуст, лучше пропустить звонок по стандартному пути, чем оборвать связь.

Отладка

Проверить работу можно прямо из консоли (CLI) без совершения звонка:

odbc read ODBC_CHECK_STATUS 79991234567 exec

Если запрос верный, Asterisk выведет значение из колонки status.

Мы научили систему «советоваться» с базой данных. В следующей теме применим это на практике: настроим динамическую маршрутизацию, VIP-очереди и перевод звонка на «своего» менеджера.

Понравился урок?

Сохраните прогресс и получите персональный курс по любой теме — без форм и паролей

Продолжить в Telegram