На днях встала необходимость организовать сервер голосовой телефонии с выходом в мир. То есть, основная внутренняя связь будет организована на базе SIP-номеров, но для связи с некоторыми внешними клиентами необходимо будет перенаправлять вызов на внешнюю линию. Казалось бы, ничего сложного: SIP-линии организовываются за две минуты, да и chan_dongle, в общем-то, достаточно часто встречаемая тема на различных сайтах и форумах, посвященных Asterisk. Тем не менее, получилось достаточно весело. Если вам интересна эта история, то приглашаю ознакомиться с данной заметкой.
Итак, для начала нужно понимать, что основная сложность реализации заключается именно в USB-модеме. Во-первых, они далеко не все поддерживаются chan_dongle:
От теории к практике. Начнем сборку модуля chan_dongle. Сразу отмечу, что мой экспериментальный стенд оснащен сборкой Debian 8.2 с установленным комплектом пакетов для сборки приложений из исходного кода. Существует несколько репозитариев, где можно найти исходный код модуля chan_dongle, я буду говорить о репозитарии
# cd /opt
# wget https://github.com/oleg-krv/asterisk-chan-dongle/archive/master.zip
# unzip master.zip
# cd asterisk-chan-dongle
# aclocal
# autoconf
# automake -a
# DESTDIR="/usr/lib/asterisk/modules" ./configure --enable-debug
# make
# make install
# cp etc/dongle.conf /etc/asterisk/
После aclocal или autoconf у вас может возникать ошибка, но это не существенно, поскольку несмотря на это модуль успешно собирается, запускается и работает. Теперь нам нужно подключить модем и найти, куда он в системе регистрируется. У моего E153 регистрируется три порта: /dev/ttyUSB0 для считывателя карт памяти (а-ля флешка), /dev/ttyUSB1 для аудиоданных и /dev/ttyUSB2 для управления модемом. Цифры могут различаться в зависимости от того, сколько раз после перезагрузки вы подключали и отключали модем (повторно порт не используется), но суть, я думаю, ясна. Открываем /etc/asterisk/dongle.conf и находим в самом низу упоминания этих портов. Правим в соответствии с тем, что у вас отображается по команде «ls /dev/ttyUSB*», после чего комментируем знаком «;» строки «imei» и «imsi» (их мы заполним немножечко позже).
Теперь, если Asterisk у вас запущен, подключаемся к нему посредством «asterisk -rv» и набираем следующую команду:
module load chan_dongle.so
Могут возникать ошибки, но это не так существенно (если они не касаются dongle.conf). Через некоторое время запускаем в Asterisk'е команду
dongle show devices
Если она ничего не дает, попробуйте через пару минут (модем подключается не сразу). Если и дальше ничего нет, а в консоль Asterisk выводятся сообщения о том, что порт /dev/ttyUSBX не ответил на AT-запрос, то перепроверяем порты:
minicom -d /dev/ttyUSB2
Если устройство не отвечает и не дает ничего ввести, то оно либо занято другим приложением, либо у вас перепутались порты (в таком случае есть смысл перепробовать через minicom подключение и к другим портам).
У меня все подтянулось сразу и я на радостях решил позвонить себе на мобильный:
originate Dongle/dongle0/0123456789 application Playback tt-monkeys
Вместо цифр в порядке возрастания укажите свой номер так, как вы бы набирали его на мобильном телефоне. Если после этой команды вы получаете нечто вроде этого:
ERROR[10576]: at_response.c:472 at_response_error: [dongle0] AT^DDSETEX failed
Значит, у вас, как и у меня, заблокирована передача голосовых данных. Решение указываю только для Huawei E153 Kyivstar, к другим оно может не подходить, да и другие способы также существуют.
Итак, скачиваем
Теперь устройство должно нормально работать с исходящими и входящими звонками. Качество звука, кстати, будет на порядок выше, чем при использовании модуля chan_mobile. В завершение прилагаю также небольшой образец составления dialplan'а для использования с chan_dongle:
[dongle-in] #Входящая связь
exten => +380670000000,1,Set(CALLERID(all)=${CALLERID(num)})
exten => +380670000000,n,Set(CALLERID(num)=${CALLERID(num:1)})
exten => +380670000000,n,Answer
exten => +380670000000,n,Dial(SIP/0852,45,tr)
exten => +380670000000,n,Hangup
[dongle-out] #Исходящая связь
exten => _0X.,1,Dial(Dongle/dongle0/${EXTEN},45,tr)
exten => _0X.,n.Hangup
В данном примере «+380670000000» — номер той SIM-карты, которая установлена в модеме (можно не заострять на этом внимания и сделать более универсальную конструкцию по маске — это есть в примере касательно исходящей связи), «SIP/0852» — внутренний SIP-номер 0852 на который будет перенаправлен входящий из сотовой сети звонок (можно перенаправить куда угодно, и на Dongle (только не на тот же, на котором входящая линия), и на chan_mobile). В первой строке входящего правила объявляется CallerID (чтобы SIP-абонент видел, кто ему звонит) в полной форме, а во второй — без плюса (только цифры). «45» в «Dial» означает, что ждать ответа в обоих направлениях мы будем только 45 секунд, после чего соединение будет разорвано командой «Hangup». В исходящей связи вместо конкретного номера используется маска, поскольку по умолчанию мы не ограничиваем направления звонков. Согласно этой маски, разрешены любые исходящие вызовы на номера, начинающиеся с нуля. Можно корректировать так, чтобы исходящая связь была разрешена, например, только на номера сети «Киевстар». В подробностях dialplan расписывать не буду — этих материалов в Интернете итак достаточно, чего не скажешь о chan_mobile и chan_dongle.