Asterisk автодзвінок (auto-dial out) та зворотній дзвінок (callback) з використанням AGI, blog
Мережі, налаштування обладнання, мережеві послуги.
Автообзвон
Є завдання, реалізація яких можлива через автоматичний обдзвон. Наприклад?
Наприклад ви сис.адмін, у вас є локальна мережа і купа обладнання в ній, але ви ж не 24/7 на роботі, а раз так, то в мережі може щось статися, наприклад подія в системі моніторингу, а вас немає на робочому місці. Звичайно можна відправляти собі SMS, якщо така можливість є, а маючи серверAsterisk можна і зателефонувати і самому собі розповісти що ж трапилося 😉
Отже, вважаємо що у вас вже є встановлений і налаштований серверAsterisk, який має вихід у місто.
Щоб зробити автоматичний дзвінок нам знадобляться такі речі:
- сформувати call файл
- мати в діалплані (dialplan (визначається в /usr/local/etc/asterisk/extensions.conf)) контекст (context) зі списком дій
Почнемо з call файлу, його основний синтаксис:
- Channel: - Який канал використовувати для дзвінка
- CallerID: "name" - Встановити Caller ID, простіше сказати тут ми можемо виставити АОН (номер з якого ми дзвонимо).
- MaxRetries: — Максимальна кількість спроб додзвонитися, за замовчуванням 0, що є однією спробою.
- RetryTime: — Час у секундах між спробами додзвону за замовчуванням 300 (5 хвилин).
- WaitTime: — Скільки секунд очікуємо підняття трубки за промовчанням 45.
- Context: - Який контекст використовуємо з extensions.conf
- Extension: - Який екстеншн використовуємо у вибраному контексті (так само в extensions.conf).
- Priority:
— Із якого пріоритету починаємо.
Я навів не повний перелік, повний перелік доступний тут. Особисто я для кожногономери, створюю свій контекст в extensions.conf .
Відповідно знаючи синтаксис, ми тепер зможемо сформувати call файл, на прикладі дзвінка через SIP канал:
Для тих, хто в танку 🙂 розберемо call файл рядково:
- зателефонувати на SIP номер 89161112233 через провайдера sip-provider (ім'я /usr/local/etc/asterisk/sip.conf для виходу в місто)
- використовувати АОН 9998877
- Максимальна кількість спроб дозвону 2
- Пауза між спробами 20 секунд
- Чекати на підняття трубки 60 секунд
- Використовувати контекст (context) з ім'ям outgoing_to_89161112233
- Починати з екстеншену (ext) s
- І починати з пріоритету 1 в екстеншені s
Сформувавши call файл, його необхідно покласти в папку: /var/spool/asterisk/outgoing/ серверAsterisk виявивши в цій папці файл відразу спробує відпрацювати його.
Відразу скажу, що можна затримати обробку файлу, тобто. затримати вих. дзвінок і відкласти його на певний час.
СерверAsterisk дивиться на дату створення call файлу і якщо змінити дату створення на дату в майбутньому, тоAsterisk не буде відпрацьовувати call файл, доки не настане ця дата.
Як це зробити ? Дуже просто, для цього скористаємося командою touch, яка є у всіх unix системах.
Після того як створили сам call файл беремо та змінюємо дату його створення, шаблон дати такий:
РІК МІСЯЦЬ ДЕНЬ ГОДИННИХ ХВИЛИН. СЕКУНДИ ( увага: перед секундами стоїть символ точки, це так і потрібно, а не друкарська помилка ).
/usr/bin/touch -t 1007091918.55 /path/to/call/file.call
Дата створення call файлу зміниться і якщо перемістити файл у /var/spool/asterisk/outgoing/, то відповідноAsterisk його не обробить дотидоки не настане виставлена дата.
Порада: генерувати call файл краще в якійсь tmp директорії, виконувати над ними всі необхідні дії і потім мувіть (переносити) в /var/spool/asterisk/outgoing/.
Тепер подивимося на сам контекст (context), для системи моніторингу він може бути таким:
Виходячи з даного контекстуAsterisk додзвонившись до 89161112233 (людина взяв трубку) виконає таке:
- підніме трубку зі свого боку
- секунду зачекає
- програє записані вами звукові файли (повні шляхи до файлів вказані)
- повісить трубку
Як записати голосові файли (що ви будете програвати) ви можете дізнатися з цієї статті.
Після того, як Asterisk повністю відпрацює call файл, він його видаляє з директорії /var/spool/asterisk/outgoing/ .
Спеціальний екстеншен 'failed ' Якщо на виклик не відповіли, і існує стандартний екстеншен з ім'ям failed та команда з пріоритетом 1 у заданому (у .call файлі) контексті, керування буде передано цій команді.
Може з'явиться ще одне завдання, а саме: якщо при автододзвон трубку так і не підняли, то відразу набрати інший номер. Приклад такої конструкції:
- спочатку набираємо внутрішній SIP номер (6003) людини
- якщо внутрішній SIP номер не відповідає/зайнятий/недоступний – набираємо мобільний номер
Здається, що може бути простіше, написати:
А ось тут і з'ясувалося, що не все так просто. На таке дійство ви в консолі (виставивши core set verbose 3) побачите подібне повідомлення:
— Executing [failed@dialsip:1] Dial(«OutgoingSpoolFailed», «SIP/6003») у новому стику [Feb 11 16:57:44] WARNING[94371]: channel.c:3441 ast_request: No translation path exists for channeltype SIP (native 65535) to 0 [Feb 11 16:57:44] WARNING[94371]: app_dial.c:1296 == Everyone is busy/congested at this time (1:0/0/1) == Auto fallthrough, канал 'OutgoingSpoolFailed' status is 'CHANUNAVAIL' [Feb 11 16:57:54 ] NOTICE[94371]: pbx_spool.c:356 attempt_thread: Call failed to go through, reason (8) Congestion (circuits busy)
Усі… приїхали…. Лазаючи за результатами пошуку в гугле я натикався на повідомлення:
Канал виходить OutgoingSpoolFailed і саме в нього намагається дзвонити та Dial та грати Playback. Як мені в failed зробити дзвінок на SIP і програти повідомлення?
Власне таке саме питання ставив собі і я сам, але відповіді на нього ні в Інеті ні в мене не було.
Так само як і я народ намагався реалізувати подібне через failed з Goto, System і т.п., але результат виходив таким самим - ніяким 🙁
Виходить starndart extention failed зробити набір (Dial) іншого номера не вийде…..
Я вже було подумав, що не доля і мені доведеться ловити DIALSTATUS, передавати його AGI скрипту (який ще й писати доведеться) і той вже вирішуватиме що з цим робити (створювати новий call файл або ще щось), але тут народився ще один варіант:
Створюємо call-файл вже трохи іншого змісту:
Де autocaller це назва контексту, а 1 -ця пріоритет у цьому контексті. Відповідно робимо у extensions.conf цей контекст:
Тим самим ми ніби набираємо вже не номер, а конкретний exten у контексті та в ньому передаємо виклик у макро, створюємо і макро, яке використовується в цьому контексті:
Власне, цей макро дає нам можливість вже керувати куди і в якому разі піде виклик.Приклад звичайно «грубий», але головне принцип, а далі вже ваша творчість 😉
І ось таким чином ми отримуємо результат.
Callback
Він працює за тим же принципом, що і описаний вище автообзвон, за деякими винятками:
- генерація call файлу відбувається при дзвінку людини на номер, виділений підcallback.
- у контексті (context) ми не просто програємо звукові, а пропонуємо користувачеві ввести номер, на який він хоче зателефонувати
Що нам буде потрібно в цьому випадку:
- виділити номерcallback і створити контекст (context) під нього в extensions.conf .
- «передати» дзвінок уAGI скрипт, який перевірить АОН того, хто дзвонить на предмет, чи дозволено цьому номеруcallback
- якщоcallback дозволено, то сформує call файл.
AGI - цеA steriskG atewayI nterface.A steriskG atewayI nterface це можливість розширити функціоналAsterisk `а за допомогою використання скриптів на багатьох мовах програмування. Наприклад, Perl, PHP, C, Pascal, Bourne Shell.
Почнемо з номера, припустимо, це буде гір. номер 84955556677. Додамо в extensions.conf в контекст (context) куди надходять усі вхідні дзвінки:
Тобто. дзвінок на екстеншн (ext) 84955556677 буде переданийAGI скрипту callback.php , а потім дзвінок буде одразу ж завершено.
AGI скрипти дляAsterisk розташовуються в директорії /usr/local/share/asterisk/agi-bin/.
Чому скрипт на PHP? PHP було обрано дляAGI, т.к. callback є невід'ємною частиною проекту написаного на PHP + MySQL, тому вирішили і нехай на PHP буде. Сам скрипт:http://subnets.ru/files/callback.php.txt
Що відбувається зі скриптом?
- визначаємо необхідні змінні
- отримуємо дані відAsterisk `а.
- логи, куди ж без них. У лог ми помістимо все те, що отримавAGI скрипт відAsterisk `а, це для дебага, потім можна вимкнути логування.
- перевіряємо номер (АОН) телефонуючого на доступ доcallback
- чи вже немає call файлу для даного номера, якщо ні, то створюємо його
Ну і залишилося справа за малим, а саме щоб був контекст (context) під номер в extensions.conf.
Допустимо нашcallback номер 84955556677 набрали з мобільного 89105647899 і йому дозволеноcallback (номер84955556677 вказаний у масиві $permit_num у скрипті), то його контекст може виглядати ось так: