Computer-Telephony Integration и телефоны Grandstream

4489454b8f9a42deb58a5fbf9e2b2f6c.png

Все больше и больше современные средства связи интегрируются в окружающий нас мир, и офисная телефония не является исключением. В компании Grandstream решили не отставать и добавили поддержку специального интерфейса CTI (Computer-Telephony Integration) в свои телефоны. Изначально были обновлены аппараты серии GXP21ХХ, а чуть позже обновились устройства младшей линейки GXP16ХХ, такие как GXP1610, GXP1620 и т.д.

На самом деле, «интерфейс CTI» это громко сказано, в реальности — небольшое REST API, позволяющее управлять телефоном с помощью простых HTTP запросов. Казалось бы: инициировать звонок, отследить состояние линий, используемых телефоном, можно и на АТС, но при использовании, к примеру, облачной IP АТС это не всегда представляется возможным. В добавок к этому, CTI позволяет управлять громкой связью, громкостью динамиков, отключением микрофона и т.д., что на уровне АТС не всегда реализуемо.

Итак, что же мы можем сделать с помощью CTI? В общем-то, не очень много, нам доступно всего пять типов запросов:


Запрос Описание
api-get_line_status Состояние линий
api-get_phone_status Состояние телефона
api-send_key Нажатие какой-либо клавиши (0–9, #, *, контекстно зависимые и т.д.)
api-phone_operation Простейшие манипуляции с телефоном (принять звонок, сбросить и т.д.)
api-sys_operation Позволяет перезагрузить и сбросить аппарат к заводским настройкам

Пользоваться этим очень просто, формируем запрос вида:

"http://IP адрес телефона/cgi-bin/api-get_line_status?passcode=Пароль" // (пароль от учётки с правами администратора)

В ответ получим JSON вида:

{ 
 "response": "success", 
 "body": [ 
    { "line": 1, "state": "idle", "acct": 1, "active": 0, "remotename": "", "remotenumber": "" }, 
    { "line": 2, "state": "connected", "acct": 2, "active": 1, "remotename": "Виталик", "remotenumber": "203" }, 
    { "line": 3, "state": "idle", "acct": 1, "active": 0, "remotename": "", "remotenumber": "" }, 
    ...
    { "line": 8, "state": "idle", "acct": 1, "active": 0, "remotename": "", "remotenumber": "" } 
] }

Заменив в запросе api-get_line_status на api-get_phone_status мы получим краткую информацию по телефонному аппарату:

{ "response": "success", "body": "busy", "misc": "0" }

Такой способ удобен, когда нам требуется просто опросить состояние аппарата или телефонных линий и очень неудобен в случаях, когда мы хотим отслеживать происходящие изменения. Поступил звонок, нам бы взять входящий номер и показать пользователю уведомление, но как это сделать? Возможности подписаться на какие-либо события у нас нет, два-три раза в секунду долбить телефон запросами о состоянии не кажется хорошим решением. К сожалению, в такой ситуации CTI не помощник.

Смотрим дальше, api-send_key, как понятно из названия, служит этот запрос для отправки нажатий на клавиши телефона, передавать можно как по одной, так и сразу несколько. Фактически, инициируются нажатия на переданные клавиши с интервалом около секунды и прервать этот процесс нельзя. При этом, клавиши на телефоне не блокируются и их можно свободно нажимать, в результате исполняемое телефоном превращается в непонятную «кашу».

"http://192.168.4.118/cgi-bin/api-send_key?passcode=admin&keys=LINE2:2:0:3:SEND" 

Как видим, добавился еще один параметр keys, указывающий какие клавиши надо нажать. (Таблица со списком всех клавиш, которые можно виртуально нажать, есть в документации по CTI.)

Первое что приходит в голову: «А не написать ли расширение для браузера, которое позволяло бы инициировать звонок прямо из него?». Простейший вариант не заставил себя долго ждать. Так как у меня основной браузер Google Chrome, то написал для него, потребовалось всего-то создать два файла:

// manifest.json
{
    "manifest_version": 2,
    "name": "ArtDial",
    "version": "0.1",
    "permissions": ["contextMenus"],
    "background": {
        "scripts": ["background.js"]
    }
}
// background.js
function dial(selectedText) {
    var serviceCall = 'http://192.168.4.118/cgi-bin/api-send_key?passcode=admin&keys='+ selectedText.replace(/[^\d]/g, '').split('').join(':') +':SEND';
    var xhr = new XMLHttpRequest();
    xhr.open("GET", serviceCall, true);
    xhr.send();
}

chrome.contextMenus.create({
    title: "Набрать: %s", 
    contexts: ["selection"], 
    onclick: function(info, tab) {
        dial(info.selectionText);
    }
});

Кладем их в одну папку, на странице расширений включаем режим разработчика и подключаем наше расширение.


08f0e1769db04533af6745467569033e.gif


8cdee527026342be8b658edc22f42127.gif

Для управления вызовами предусмотрен запрос api-phone_operation, с его помощью мы можем принять или отклонить входящий вызов (acceptcall/rejectcall), поставить на удержание или завершить текущий разговор (holdcall/endcall). Так же доступна более универсальная команда cancel, позволяющая отклонять и завершать вызовы. Для отправки используем запрос вида:

"http://192.168.4.118/cgi-bin/api-phone_operation?passcode=admin&cmd=cancel"

И самое последнее: api-sys_operation, позволит нам перезагрузить телефон, либо сбросить в заводские настройки (REBOOT и RESET соответственно). Используем запросы вида:

"http://192.168.4.118/cgi-bin/api-sys_operation?passcode=admin&request=REBOOT"

Используя только Computer-Telephony Integration вряд ли удастся создать разухабистое приложение, которое будет всесторонне взаимодействовать с вашим окружением. Но как дополнительный инструмент, используемый совместно с другими API (Action URL в телефонах или AMI в Asterisk), CTI вполне имеет право на существование.

© Geektimes