Еще до появления в инфраструктуре нашей организации 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: loginrn");
fputs ($oSocket, "Username: $User_strrn");
fputs ($oSocket, "Secret: $Secret_strrnrn");
$wrets = fgets ($oSocket,128);
echo $wrets;
fputs ($oSocket, "Events: offrnrn");
fputs ($oSocket, "Action: originatern");
fputs ($oSocket, "Channel: $our_extenrn");
fputs ($oSocket, "WaitTime: $WaitTimern");
fputs ($oSocket, "CallerId: $strCustdatarn");
fputs ($oSocket, "Exten: $receiverrn");
fputs ($oSocket, "Context: defaultrn");
fputs ($oSocket, "Async: yesrn");
fputs ($oSocket, "Priority: 1rnrn");
fputs ($oSocket, "Action: Logoffrnrn");
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 телефона на номера которые видим на экране. Например, так у меня выглядит контекстное меню, вызванное в данной статье:
Спасибо за внимание.
Автор: Slavon4ever