В дистрибутив Elastix (на базе FreePBX) включена очень полезная функция, позволяющая получить имя для любого занесённого в базу данных номера и высветить это имя при входящем внешнем вызове на дисплей телефона. В данной статье я расскажу о частном случае применения данной функции.
Имеется n-ное количество IP-телефонов, поддерживающих utf-8 (это обязательное условие для возможности отображения русских CallerID) и база данных MySQL, которая содержит телефонную книгу. Требуется все это подружить с Elastix.
Я рассмотрю случай, когда даже базы данных нет в наличии и мы должны её сначала создать.
В моём конкретном случае было принято решение создать БД с двумя таблицами - Имена и Телефоны, т.к. у одного человека может быть несколько телефонных номеров. Таким образом, мы избегаем необходимости заносить одну и ту же фамилию по несколько раз.
Создаём БД
CREATE DATABASE `phonebook` CHARACTER SET utf8 COLLATE utf8_general_ci;
Таблица "Имена" (names)
CREATE TABLE IF NOT EXISTS `names` (
`name_id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`name_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
Таблица "Телефоны" (phones)
CREATE TABLE IF NOT EXISTS `phones` (
`phone_id` bigint(20) NOT NULL AUTO_INCREMENT,
`number` varchar(64) NOT NULL,
`name_id` bigint(20) NOT NULL,
PRIMARY KEY (`phone_id`),
KEY `name_id` (`name_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
Естественно, что БД надо сначала как-то заполнить для проведения тестирования.
Пример заполнения:
INSERT INTO `names` (`name_id`, `name`) VALUES (NULL, 'И.И.Иванов');
INSERT INTO `phones` (`phone_id`, `number`, `name_id`) VALUES (NULL, '79161234567', 1);
В поле name_id таблицы phones указываем полученное автоинкрементное значение из поля name_id таблицы names (в моём случае это 1). Номер телефона указываем реальный - тот, с которого будете тестировать.
Теперь идём в PBX -> PBX Configuration -> CallerID Lookup Sources.
Добавляем новый источник. Назовём его mysql-directory.
Указываем следующие параметры:
Что мы сделали. Мы заставили FreePBX стандартно генерировать нужный нам кусок конфига в его специфические файлы конфигурации. Этот метод будет железно работать до тех пор, пока вы не установите обновление модуля CID Lookup. После этого все изменения в коде придётся повторить заново.
Имеется n-ное количество IP-телефонов, поддерживающих utf-8 (это обязательное условие для возможности отображения русских CallerID) и база данных MySQL, которая содержит телефонную книгу. Требуется все это подружить с Elastix.
Я рассмотрю случай, когда даже базы данных нет в наличии и мы должны её сначала создать.
В моём конкретном случае было принято решение создать БД с двумя таблицами - Имена и Телефоны, т.к. у одного человека может быть несколько телефонных номеров. Таким образом, мы избегаем необходимости заносить одну и ту же фамилию по несколько раз.
Создаём БД
CREATE DATABASE `phonebook` CHARACTER SET utf8 COLLATE utf8_general_ci;
Таблица "Имена" (names)
CREATE TABLE IF NOT EXISTS `names` (
`name_id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`name_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
Таблица "Телефоны" (phones)
CREATE TABLE IF NOT EXISTS `phones` (
`phone_id` bigint(20) NOT NULL AUTO_INCREMENT,
`number` varchar(64) NOT NULL,
`name_id` bigint(20) NOT NULL,
PRIMARY KEY (`phone_id`),
KEY `name_id` (`name_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
Пример заполнения:
INSERT INTO `names` (`name_id`, `name`) VALUES (NULL, 'И.И.Иванов');
INSERT INTO `phones` (`phone_id`, `number`, `name_id`) VALUES (NULL, '79161234567', 1);
В поле name_id таблицы phones указываем полученное автоинкрементное значение из поля name_id таблицы names (в моём случае это 1). Номер телефона указываем реальный - тот, с которого будете тестировать.
Теперь идём в PBX -> PBX Configuration -> CallerID Lookup Sources.
Добавляем новый источник. Назовём его mysql-directory.
Указываем следующие параметры:
- Хост: IP-адрес сервера, где запущена MySQL (или localhost, если MySQL работает локально)
- База данных: Имя базы данных. В нашем случае phonebook
- Запрос: SELECT CONVERT(n.name USING utf8) FROM names as n left join phones as p using (name_id) WHERE p.number = '[NUMBER]'
- Имя пользователя: пользователь, имеющий права минимум на чтение таблиц в БД
- Пароль: пароль этого самого пользователя
Сохраняем и применяем изменения.
Далее, нужно назначить наш новый источник поиска CallerID на один или несколько входящих маршрутов (DID'ов).
Для этого идём в Inbound Routes и выбираем там DID на котором требуется функционал отображения CallerID. В группе CallerID Lookup Source в параметре Source указываем наш новый источник mysql-directory, сохраняем и применяем изменения.
После всех этих манипуляций, по идее, всё должно заработать. Но не тут-то было. По какой-то причине FreePBX упорно не воспринимает utf8 даже в том случае, если поле таблицы, откуда мы получаем CallerID хранит данные в utf8, что приводит к высвечиванию кучи вопросительных знаков на дисплее телефона и в консоли:
-- Executing [0007@from-trunk:3] Gosub("SIP/Cisco7206VXR-000005b8", "cidlookup,cidlookup_2,1") in new stack
-- Executing [cidlookup_2@cidlookup:1] MYSQL("SIP/Cisco7206VXR-000005b8", "Connect connid xxx.xxx.xxx.xxx имя_пользователя_БД пароль_пользователя_БД phonebook") in new stack
-- Executing [cidlookup_2@cidlookup:2] MYSQL("SIP/Cisco7206VXR-000005b8", "Query resultid 1 SELECT n.name FROM names as n left join phones as p using (name_id) WHERE p.number = '79161234567'") in new stack
-- Executing [cidlookup_2@cidlookup:3] MYSQL("SIP/Cisco7206VXR-000005b8", "Fetch fetchid 2 CALLERID(name)") in new stack
-- Executing [cidlookup_2@cidlookup:4] MYSQL("SIP/Cisco7206VXR-000005b8", "Clear 2") in new stack
-- Executing [cidlookup_2@cidlookup:5] MYSQL("SIP/Cisco7206VXR-000005b8", "Disconnect 1") in new stack
..................
-- Executing [s@macro-user-callerid:21] NoOp("SIP/Cisco7206VXR-000005b8", "Using CallerID "?.?.???????" <79161234567>") in new stack
Решается это вроде бы просто. Нужно в контекст cidlookup в файле extensions_additional.conf добавить:
exten => cidlookup_2,n,MYSQL(Query resultid ${connid} SET NAMES utf8)
Но это не выход, т.к. при перестроении конфигурации FreePBX затрёт изменения.
Модификация extensions_custom.conf путём добавления контекста [cidlookup-custom] также не помогла.
Выход был найден не совсем стандартный, но вполне рабочий. Это модификация кода FreePBX.
Сначала идём в /var/www/html/admin/modules/cidlookup и делаем резервную копию functions.inc.php
Далее редактируем functions.inc.php:
- Примерно в районе строки 189 найдите такой текст $ext->add('cidlookup', 'cidlookup_'.$item['cidlookup_id'], '', new ext_mysql_connect('connid', $item['mysql_host'], $item['mysql_username'], $item['mysql_password'], $item['mysql_dbname']));
- После этой строки вставляем следующее: $ext->add('cidlookup', 'cidlookup_'.$item['cidlookup_id'], '', new ext_mysql_query('resultid', 'connid', 'SET NAMES utf8'));
- Сохраняем файл и перестраиваем конфигурацию FreePBX (меняем какой-то малозначительный параметр туда-обратно и делаем Apply Configuration Changes)
Проверяем:
-- Executing [0007@from-trunk:3] Gosub("SIP/Cisco7206VXR-00000696", "cidlookup,cidlookup_2,1") in new stack
-- Executing [cidlookup_2@cidlookup:1] MYSQL("SIP/Cisco7206VXR-00000696", "Connect connid xxx.xxx.xxx.xxx имя_пользователя_БД пароль_пользователя_БД phonebook") in new stack
-- Executing [cidlookup_2@cidlookup:2] MYSQL("SIP/Cisco7206VXR-00000696", "Query resultid 1 SET NAMES utf8") in new stack
-- Executing [cidlookup_2@cidlookup:3] MYSQL("SIP/Cisco7206VXR-00000696", "Query resultid 1 SELECT CONVERT(n.name USING utf8) FROM names as n left join phones as p using (name_id) WHERE p.number = '79161234567'") in new stack
-- Executing [cidlookup_2@cidlookup:4] MYSQL("SIP/Cisco7206VXR-00000696", "Fetch fetchid 2 CALLERID(name)") in new stack
-- Executing [cidlookup_2@cidlookup:5] MYSQL("SIP/Cisco7206VXR-00000696", "Clear 2") in new stack
-- Executing [cidlookup_2@cidlookup:6] MYSQL("SIP/Cisco7206VXR-00000696", "Disconnect 1") in new stack
..................
-- Executing [s@macro-user-callerid:21] NoOp("SIP/Cisco7206VXR-00000696", "Using CallerID "И.И.Иванов" <79161234567>") in new stack
Видим результат работы добавленной строки кода. Самая последняя строка вывода консоли говорит нам о том, что всё отображается как надо.
Этот комментарий был удален автором.
ОтветитьУдалитьСпасибо! Всё отлично!
УдалитьЕдинственно что:
-я не замарачивался с такой структурой базы данных. Всёранвно в ручную я её заполнять не буду, а обработка в 1С будет сама заполнять таблицу... (правда обработка ещё не написана);
- я запрос использовал такой: SELECT name FROM callerid WHERE number LIKE CONCAT ('%',SUBSTRING('[NUMBER]',-7),'%') LIMIT 1 который позволит исключить неточности заполнения контактной информации в базе 1С и, как следствие, в разнобой написанные номера телефонов (где-то 7 знаков как обычный местный, городской, где-то с кодом города (к примеру мобильный) а где-то менеджер прикольнулся и вписал с кодом страны)... а [NUMBER] передаётся всегда с кодом страны (а если 3G модем то и с "+")... поэтому я решил из передаваемого номера брать только последние 7 цифр. Ошибка определения - почти минимальная.
К тому же можно вписывать несколько номеров телефонов в одну строку в столбце.
Благодарю за отзыв! На самом деле структура БД (и соответственно запросов) здесь больше для целостности решения. Конечно же каждый сделает её свою под собственные нужды. Я тут описал лишь саму идею.
УдалитьДобрый день.
ОтветитьУдалитьМеня очень заинтересовала информация, которую Вы доступно описали в данной статье. Я не так давно стал интересоваться Asterisk-ом, и своими силами в небольшой организации запустил данную систему. Не могу назвать себя специалистом в данной теме, поэтому когда приходится задействовать очередной функционал (в избытке имеющийся в Asteriske), у меня очень много времени уходит на то, чтобы он заработал. Благо есть много доступной информации по многим вопросам из этой темы. Часто делая что-то по инструкции, в итоге я всё равно сталкиваюсь с тем, что запустить это "что-то" так и не получается. Как и в случае с моим желанием запустить в работающей системе подстановку имени вместо входящего номера извне, которое было внесено в адресную книгу Asterisk. Каким способом можно отследить проблемное место - почему не хочет работать эта подстановка?
Во всех статьях прописаны 3 основных пункта, после выполнения которых данный функционал должен заработать.
1. Создать записи в адресной книге Asterisk.
2. В CID Lookup Soursec - создание источника с типом Internal.
3. Указать этот источник в настройках входящей маршрутизации.
Попробвал я так же и описанный Вами вариант с MySql.
1. Создал базу, таблицы и внёс в них данные.
2. В CID Lookup Soursec - создал новый источник с типом MySql и внёс данные во все поля.
3. Указал этот источник в настройках входящей маршрутизации.
Всё равно не работает.
В CID Superfecta проверил на тестируемом номере работу определения по адресной книге - показала правильный результат. Но в реальной работе не функционирует.
Что не так? Куда смотреть, чтобы понять причину?
Если весь основной функционал работает - звонки внутри сети, звонки во внешний мир, приём звонков извне, фиксируются входящие и исходящие номера - значит ли это, что связка шлюз-Астериск работает исправно, и что искать причину неисправности определения номеров в ней нет смысла?
Систему устанавливал из готового образа AsteriskNow, настройки через веб-интерфейс freepbx. На входе 1 gsm-voip шлюз (Goip 1).