Интеграция 1С:Предприятия с телефонией Asterisk — одна из самых востребованных задач при автоматизации бизнес-процессов. Использование Native API компоненты ROM-Asterisk-Native (или BROMAsteriskNative) позволяет организовать стабильное взаимодействие через интерфейс AMI (Asterisk Manager Interface). Однако при переходе на 64-битную платформу программисты часто сталкиваются с тем, что компонента либо не загружается, либо не возвращает события от АТС. В этой статье мы подробно разберем, как правильно инициализировать компоненту, пройти авторизацию и, самое главное, заставить 1С «слышать» входящие звонки.
Прежде всего, разберем особенности платформы x64. В отличие от 32-битной версии, компонента Native API для x64 требует наличия соответствующих библиотек среды выполнения Visual C++ (Redistributable) на целевой машине. Если метод ПодключитьВнешнююКомпоненту возвращает Ложь, убедитесь, что установлены пакеты VC++ 2015-2019.
Для создания объекта компоненты используем стандартный синтаксис:
Попытка
УстановитьВнешнююКомпоненту("ОбщийМакет.ROM_Asterisk_Native");
ПодключитьВнешнююКомпоненту("ОбщийМакет.ROM_Asterisk_Native", "Asterisk", ТипВнешнейКомпоненты.Native);
ОбъектКомпоненты = Новый("AddIn.Asterisk.ROM-Asterisk-Native");
Исключение
Сообщить("Ошибка загрузки компоненты: " + ОписаниеОшибки());
КонецПопытки;
Важно помнить, что в разных сборках идентификатор объекта может отличаться (например, AddIn.Test.ROM-Asterisk-Native). Проанализируем далее процесс установки соединения.
Протокол AMI работает через TCP-сокеты. Для подключения используем метод Connect, передавая IP-адрес и порт (по умолчанию 5038). Проверим успешность подключения:
IP = "10.0.0.10";
Порт = "5038";
ОбъектКомпоненты.Connect(IP, Порт);
Если ОбъектКомпоненты.Подключено Тогда
Сообщить("Сетевое соединение установлено успешно!");
Иначе
Сообщить("Не удалось подключиться к серверу Asterisk.");
Возврат;
КонецЕсли;
После установки соединения необходимо пройти авторизацию. Здесь кроется первая серьезная ошибка: многие забывают о специфике завершения команд в Asterisk. Каждая команда AMI должна заканчиваться парой символов CRLF (Возврат каретки + Перевод строки). А для того чтобы Asterisk понял, что пакет команды завершен, необходимо отправить два таких набора.
Рассмотрим правильный код формирования команды авторизации:
CRLF = Символы.ВК + Символы.ПС;
ТекстКоманды = "Action: Login" + CRLF +
"Username: " + ЛогинAMI + CRLF +
"Secret: " + ПарольAMI + CRLF + CRLF; // Важно два CRLF в конце
Флаг = ОбъектКомпоненты.ВыполнитьКоманду(ТекстКоманды);
Обратите внимание, что метод ВыполнитьКоманду часто возвращает Истина сразу, как только пакет данных был успешно отправлен в сокет. Это не означает, что логин и пароль верны. Результат авторизации придет асинхронно во «Внешнее событие».
Самая частая проблема, обсуждаемая на форумах: «Я подключился, команды отправляю, но события о входящих звонках в 1С не прилетают». Рассмотрим причину: компонента по умолчанию находится в пассивном режиме. Чтобы она начала транслировать данные из сокета в 1С, необходимо явно включить режим прослушивания и, при необходимости, настроить фильтрацию событий.
Выясним, какие методы за это отвечают:
.*.Разберем пример настройки после успешного логина:
// Устанавливаем фильтр (регистр важен в некоторых версиях!)
ОбъектКомпоненты.SetRegEx(".*");
// Включаем прослушивание событий АТС
ОбъектКомпоненты.РежимПрослушивания(Истина);
Без вызова РежимПрослушивания(Истина) компонента будет игнорировать входящий поток данных от Asterisk, и процедура ВнешнееСобытие в модуле формы или приложения никогда не будет вызвана.
Когда Asterisk фиксирует звонок, он отправляет набор событий (Event: Newchannel, Newstate, Dial и т.д.). Компонента перехватывает их и генерирует внешнее событие в 1С. Проанализируем структуру обработки:
Процедура ВнешнееСобытие(Источник, Событие, Данные)
Если Источник = "ROM-Asterisk-Native" Тогда
// Событие содержит тип сообщения от компоненты (например, "Connected" или "Event")
// Данные содержат текстовый блок от Asterisk
Если Найти(Данные, "Event: Newchannel") > 0 Тогда
// Извлекаем номер телефона
ПозицияНомера = Найти(Данные, "CallerIDNum: ");
Если ПозицияНомера > 0 Тогда
// Логика обработки входящего звонка
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рекомендуется использовать построчный разбор переменной Данные, так как Asterisk передает параметры в формате Ключ: Значение, разделенные CRLF.
Сервер Asterisk может разорвать соединение по таймауту, если в канале долго нет активности. Для предотвращения этого рассмотрим использование команды Ping. Рекомендуется настроить периодическое (раз в 30-60 секунд) выполнение следующей команды через обработчик ожидания 1С:
ТекстПинга = "Action: Ping" + CRLF + CRLF;
ОбъектКомпоненты.ВыполнитьКоманду(ТекстПинга);
Это позволит сокету оставаться активным, а компоненте — оперативно реагировать на входящие вызовы. Также не забудьте проверить настройки AMI на стороне Asterisk (файл manager.conf). У пользователя 1С должны быть права на чтение (read) событий call и system, иначе события Newchannel просто не будут отправляться сервером в сторону 1С.
Таким образом, для успешной работы на x64 платформе мы должны обеспечить три условия: наличие корректной 64-битной библиотеки, правильную терминацию команд двойным CRLF и обязательную активацию режима прослушивания после авторизации.