Computer-Telephony Integration и телефоны Grandstream
Все больше и больше современные средства связи интегрируются в окружающий нас мир, и офисная телефония не является исключением. В компании 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);
}
});
Кладем их в одну папку, на странице расширений включаем режим разработчика и подключаем наше расширение.
Для управления вызовами предусмотрен запрос 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 вполне имеет право на существование.