Pull to refresh

Click2Call на Mac OS X

Reading time 5 min
Views 12K


Еще до появления в инфраструктуре нашей организации Asterisk-сервера у меня регулярно возникало желание совершать звонки с помощью отдельно стоящего на столе телефона на номера, которые я вижу на экране монитора не набирая их на аппарате. Далее речь пойдет о реализации этого функционала на связке Mac OS X + Asterisk.



Читатели могут возразить: подключение гарнитуры к компьютеру и настройка программного SIP-клиента решает проблему.

Но лично для меня есть несколько причин решить задачу иначе:
  1. пока еще сильна привычка говорить по телефону держа трубку в руке (при необходимости можно включить громкую связь;
  2. был опыт использования проводной и беспроводной гарнитуры, но не прижилось из-за периодически возникающих технических неувязок;
  3. удобной фичей может быть перенаправление звонка на SIP-клиент мобильника и тогда, например, можно говорить с любимой не в кабинете при коллегах, а в коридоре или находящемся за стеной кафе (даже bluetooth гарнитура в этом сценарии не подойдет).


Теория


Первым делом я попытался найти уже существующее Asterisk совместимое Click2Call ПО, но ни один из немногих найденных проектов не заработал. Тем не менее я получил общее представление о технологии взаимодействия и будучи программистом решил освоить тему самостоятельно.

Используемые компоненты:
  • инициатор звонка — Mac OS X 10.8.2
  • веб-сервер — Apache + PHP
  • SIP сервер — Asterisk 1.6.2
  • SIP телефон — Yealink VP-2009


Процесс инициации звонка состоит из следующих этапов
  1. локальный скрипт формирует url и отправляет запрос на веб-сервер
  2. php на веб-сервере подключается к менеджеру Asterisk и формирует звонок
  3. 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)." <$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 телефона на номера которые видим на экране. Например, так у меня выглядит контекстное меню, вызванное в данной статье:



Или вот так:



Спасибо за внимание.
Tags:
Hubs:
+5
Comments 3
Comments Comments 3

Articles