Використання webrtc для взаємодії з asterisk-сервером або як змусити рації говорити з браузером

Доброго часу доби, хабравчане.
Сьогодні я розповім вам про роботу sip-телефонії, а саме про те, як я організовував звуковий сеанс між мобільними раціями (або ИКН) про яких ви чули раніше з інших статей нашої компанії і web-клієнтом через webRTC з використанням sipML5 в якості бібліотеки і asterisk 11 в якості АТС.
image
Всім кому небайдужа ця тема — ласкаво просимо під кат.

Трохи передісторії
До нас у відділ надійшло оперативне завдання розробити sip-клієнт, який працював би на asterisk, і як мінімум на google chrome (як мобільного, так і десктопної версії). З цього і закрутилося.

У системі локального позиціонування RealTrac існують мобільні пристрої типу рація, або, як ми їх називаємо, ИКН (інтерком носиться), що забезпечує використання як дуплексного зв'язку, так і широкомовної напівдуплексного зв'язку з іншими пристроями. Ці пристрої взаємодіють з комунікаційним сервером INCPd, основне завдання якого – обробка пакетів протоколу INDD, за допомогою якого забезпечується обмін інформацією з пристроями системи RealTrac. Зокрема, даний сервер обробляє вступник голосовий трафік, і перепаковують його в sip-пакети, для подальшої роботи зі стороннім софтом.
В якості комутатора виступає asterisk.

image

Інструментарій
SipML5 був обраний нами невипадково. По-перше, дана бібліотека добре підходить для інтеграції з asterisk. По-друге, ми вже мали досвід роботи з подібними системами, однак, з-за того, що наша компанія підтримувала Debian 7 в якості ОС для нашого програмного забезпечення були певні складнощі. У дистрибутиві Debian 7 доступний тільки asterisk 1.8 в той час як webRTC без танців з бубном, у вигляді webrtc2sip, працює тільки з 11 версії asterisk, що нас несильно влаштовувало, так як це могло б стати полігоном проблем для майбутніх інсталяцій.
З релізом Debian 8 було вирішено продовжити рух у напрямку даного функціоналу.
В якості інструментарію створення ui-частини виступав React.js, так як він зручний для відображення різних динамічних об'єктів, що мають велику кількість внутрішніх станів.

Невелике введення по sipML5
В основі клієнта використовується дві основні суті, це SIPml.Stack і SIPml.Session.

SIPml.Stack є керуючим потоком даних. Даний об'єкт буде виступати в якості основного при створенні сесій з сервером.

SIPml.Session є потоком sip-сеанси з сервером. Використовується безпосередньо для передачі даних між сервером і клієнтською частиною.

Алгоритм роботи з sipML5:

Ініціалізація бібліотеки:

SIPml.init(readyCallback, errorCallback);


Створення Stack

Stack є ключовим джерелом даних для роботи клієнта.
RtlsSip.stack = new SIPml.Stack({
realm: Data.property.realm,
impi: Data.property.impi,
impu: Data.property.impu,
password: Data.property.password,
display_name: Data.property.display_name,
websocket_proxy_url: Data.property.websocket_proxy_url,
events_listener: { events: '*', listener: eventsListener },
sip_headers: [
{ name: 'User-Agent', value: 'IM client/OMA1.0 sipML5-v1.0.0.0' },
{ name: 'Organization', value: 'RTLS' }
]
})


При створенні stack необхідно вказувати велику кількість конфігураційних даних, частина з яких є необов'язковою. Повну інформацію по stack можна подивитися тут

Після створення stack-об'єкта необхідно запустити його:

RtlsSip.stack.start();


Важливо відзначити, що функція start() є асинхронною, тому, перед тим як почати здійснювати дзвінки, необхідно дочекатися події запуску stack.
Повний перелік подій представлений тут многота перераховувати їх все не має сенсу.

Після події створення stack необхідно створити сесію реєстрації:

RtlsSip.stack.newSession('register', {
events_listener: { events: '*', listener: registerListeners} });
RtlsSip.sessions.register();


В ході цієї операції відбувається sip запит для входу користувача в систему.

Після виконання цих дій ми готові здійснювати або приймати дзвінки від користувачів.

Прийом дзвінків

Вхідний дзвінок у sipML5 ініціалізує подія «i_new_call» об'єкта SIPml.Stack.
У загальному випадку обробник відповіді на дзвінок виглядає наступним чином:

var eventCallback = function(e){
RtlsSip.callSession = e.newSession;
RtlsSip.callSession.events_listener({events: '*', listener: RtlsSip.sessionEventListener})
RtlsSip.callSession.accept(
{audio_remote: document.getElementById('audio_remote'),
events_listener: { events: '*', listener: RtlsSip.sessionEventListener}})

}


e.newSession — містить у собі додатковий об'єкт сеансу зв'язку, для події «i_new_call» це буде об'єкт SIPml.Session.Call.

Функція accept() необхідна для прийняття дзвінка. В якості параметра приймає об'єкт SIPml.Session.Configuration

Ініціалізація дзвінків

Ініціалізація дзвінка зводиться до створення нової сесії типу SIPml.Session.Call

RtlsSip.callSession = RtlsSip.stack.newSession('call-audio', {
audio_remote: document.querySelector('#audio_remote'),
events_listener: { events: '*', listener: RtlsSip.sessionEventListener }
});


Після ініціалізації можна приступати до викликом абонента, через його ідентифікатор, номер або url (e.g. 'sip:johndoe@example.com' or 'johndoe' or '+33600000000').:

RtlsSip.callSession.call(number);


Керування дзвінком
Управління дзвінком це методи класу SIPml.Session.Call

Основні з них:
● .hangup() — завершення дзвінка
● .hold() / .resume() — утримання/відновлення дзвінка
● .mute(media, mute) — відключення вхідного звуку, де media — тип вмісту для відключення; mute — boolean — активація/деактивація mute.
RtlsSip.callSession.mute('audio', true);

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

Схема програми:
Схема програми має досить просту архітектуру. В якості ідеології односпрямованість даних та відсутності взаємних залежностей між елементами.

image

Інтеграція в систему
Налаштування сервера asterisk я тут описувати не буду, так як їх нескладно знайти на просторах мережі.
Для абонентів типу web-client був виділений власний список номерів. Номери з пулу встановлюються диспетчерам при створенні облікового запису користувача.
Диспетчер може здійснювати дзвінки як в напівдуплексному, так і в дуплексному режимі, а також зв'язуватися з іншими диспетчерами у разі необхідності.
Пристрій за промовчанням дзвонить в напівдуплексному режимі. Диспетчер, якому дзвонить пристрій вибирається в залежності від геосегмента в якому знаходиться пристрій в поточний момент часу.
Все це дозволяє добитися максимального комфорту у використанні системи.
Підсумки:
На даний момент, ця технологія проходить у нас процес інтеграції і тестування. Впевнений, що в процесі роботи знайдеться чимало перешкод і проблем.
Цілком можливо, що в майбутньому ми спробуємо рішення на підставі інших технологій, що надають той же функціонал.

by Sinires
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.