Еще до появления в инфраструктуре нашей организации Asterisk-сервера у меня регулярно возникало желание совершать звонки с помощью отдельно стоящего на столе телефона на номера, которые я вижу на экране монитора не набирая их на аппарате. Далее речь пойдет о реализации этого функционала на связке Mac OS X + Asterisk.
Читатели могут возразить: подключение гарнитуры к компьютеру и настройка программного SIP-клиента решает проблему.
Но лично для меня есть несколько причин решить задачу иначе:
- пока еще сильна привычка говорить по телефону держа трубку в руке (при необходимости можно включить громкую связь;
- был опыт использования проводной и беспроводной гарнитуры, но не прижилось из-за периодически возникающих технических неувязок;
- удобной фичей может быть перенаправление звонка на SIP-клиент мобильника и тогда, например, можно говорить с любимой не в кабинете при коллегах, а в коридоре или находящемся за стеной кафе (даже bluetooth гарнитура в этом сценарии не подойдет).
Теория
Первым делом я попытался найти уже существующее Asterisk совместимое Click2Call ПО, но ни один из немногих найденных проектов не заработал. Тем не менее я получил общее представление о технологии взаимодействия и будучи программистом решил освоить тему самостоятельно.
Используемые компоненты:
- инициатор звонка — Mac OS X 10.8.2
- веб-сервер — Apache + PHP
- SIP сервер — Asterisk 1.6.2
- SIP телефон — Yealink VP-2009
Процесс инициации звонка состоит из следующих этапов
- локальный скрипт формирует url и отправляет запрос на веб-сервер
- php на веб-сервере подключается к менеджеру Asterisk и формирует звонок
- Asterisk звонит на SIP номер моего телефона и после ответа соединяет с вызовом удалённого абонента
Поскольку я основывался на примерах настройки возможности заказа обратного звонка через сайт, то в схеме присутствует необязательный элемент — отдельный веб-сервер с PHP. Необязательный он еще и по той причине, что в текущей версии скрипта я вынужден использовать интерпретатор PHP на стороне своего Mac и, следовательно, при необходимости можно перенести весь функционал подключения к менеджеру Asterisk на локальную машину. Тем не менее я оставил 3х компонентную схему для возможности инициации звонка из браузера мобильного телефона, а не с компьютера.
Практика
Процесс настройки всех трех компонентов буду излагать в таком порядке: Asterisk, WEB, Mac OS.
1. Настраиваем Asterisk
Прежде всего нужно добиться от Asterisk возможности вызывать локального абонента А и соединять его с вызовом абонента Б. Автоматизировать этот процесс можно помещая файл с нужными параметрами вызова в папку /var/spool/asterisk/outgoing сервера Asterisk или передавая эти параметры через менеджер процессу Asterisk.
Например файл вызова может быть таким
Channel: Local/7777 MaxRetries: 1 RetryTime: 60 WaitTime: 30 Context: default Extension: +79201234567 Priority: 1
Важно правильно указать параметр Context, который в конфигурации Asterisk соответствует, например, контексту для исходящих вызовов.
Тестирование я проводил первым способом — файловым, а боевую систему настроил с использованием второго. Для этого включаем на SIP сервере менеджер Asterisk
manager.conf
[general] enabled = yes webenabled = yes port = 5038 [asterisk] secret=mysecretpassword deny=0.0.0.0 permit=A.B.C.0 ; адрес подсети вебсервера read=system,call,log,verbose,command,agent,user,originate write=system,call,log,verbose,command,agent,user,originate
Не забываем в межсетевом экране открыть доступ к порту 5038 для вебсервера.
2. Готовим web
На вебсервере создаем php-скрипт
<?php $receiver = str_replace(array(" ","(", ")", "-", "."), "", $receiver); switch (strlen($receiver)) { case 0: exit; break; case 6: $receiver="84722".$receiver; break; case 10: $receiver="8".$receiver; break; } // IP сервера с Asterisk $sys_ip = "1.2.3.4"; // имя пользователя для менеджера $User_str = "asterisk"; // ... и его пароль $Secret_str = "mysecretpassword"; $our_exten = "Local/$sender"; $WaitTime = "10"; $domain = "127.0.0.1"; // это будет отображено в sip-клиенте, если звонок пойдёт куда-либо на SIP/xxx $strCustdata = "Call to ".($name!=""?$name:$receiver); $oSocket = fsockopen ($sys_ip, 5038, $errnum, $errdesc) or die ("Connection to host failed"); sleep (1); fputs ($oSocket, "Action: login\r\n"); fputs ($oSocket, "Username: $User_str\r\n"); fputs ($oSocket, "Secret: $Secret_str\r\n\r\n"); $wrets = fgets ($oSocket,128); echo $wrets; fputs ($oSocket, "Events: off\r\n\r\n"); fputs ($oSocket, "Action: originate\r\n"); fputs ($oSocket, "Channel: $our_exten\r\n"); fputs ($oSocket, "WaitTime: $WaitTime\r\n"); fputs ($oSocket, "CallerId: $strCustdata\r\n"); fputs ($oSocket, "Exten: $receiver\r\n"); fputs ($oSocket, "Context: default\r\n"); fputs ($oSocket, "Async: yes\r\n"); fputs ($oSocket, "Priority: 1\r\n\r\n"); fputs ($oSocket, "Action: Logoff\r\n\r\n"); sleep (2); fclose ($oSocket); ?>
Важными параметрами при формировании вызова, как я уже говорил, являются Channel, Exten и Context.
3. Готовим инициатор звонков
Создаём в Apple Script Editor и сохраняем в папку ~/Library/Address Book Plug-Ins/ скрипт
using terms from application "Contacts" on action property return "phone" end action property on action title for p with e return "Dial from Yealink" end action title on should enable action for p with e if value of e is missing value then return false else return true end if end should enable action on perform action for p with e set theName to name of p set telephone to the value of e tell application "Terminal" set param to "`echo \"<?php echo 'http://webserver/click2call/call.php?sender=7777&receiver='.urlencode('" & telephone & "').'&name='.urlencode('" & theName & "')?>\" | php`" do shell script "/opt/local/bin/wget -q -O - " & param & " >/dev/null 2>&1 & sleep 1" quit saving no end tell end perform action end using terms from
Скрипт формирует URL, обращается к нему через wget и затем закрывает терминальное приложение. Мне пришлось использовать локальный PHP для кодирования UTF8 строк в URL. Все найденные функции AppleScript не справлялись с задачей в полном объёме. Если вы постоянно держите открытым Terminal.app для работы, то возможно прийдется убрать команду закрытия приложения.
Теперь в приложении Contacts в контекстном меню появится пункт «Dial from Yealink». Замечу, что после внесения правок в скрипт и его сохранения нужно каждый раз перезагружать приложение Contacts для тестирования этих правок.
Для добавления пункта в контекстное меню Services любого приложения нужно создать сервис через Automator. Добавляем блок Run Shell Script, вводим сам скрипт
/opt/local/bin/wget -q -O - "http://webserver/click2call/call.php?sender=7777&receiver=$1" > /dev/null 2>&1
Настраиваем передачу входных данных в качестве аргументов, а не на стандартный ввод.
Итог.
Получаем возможность звонить со стационарного SIP телефона на номера которые видим на экране. Например, так у меня выглядит контекстное меню, вызванное в данной статье:
Спасибо за внимание.
ссылка на оригинал статьи http://habrahabr.ru/post/170315/
Добавить комментарий