Голосове меню в Asterisk

Що таке IP-телефонія я колись пробував розповісти тут. Нещодавно мені довелося знову згадати цю тему, та ще й не просто згадати, а розібратися з побудовою голосового меню.

Прикладів голосового меню в Internet'i є чимало, але як завжди там описаний найпростіший варіант, який придатний лише для того, щоб зрозуміти основні принципи і підглянути якісь параметри. Якщо ж є реальна задача, то більшість речей Вам доведеться писати самостійно (мені довелося).

Отож припустимо, що Вам сподобаися всі ті можливості зі статті про IP-телефонію і Ви собі щось таке налаштували. Перша задача, яку хочеться реалізувати — автовідповідач.

Для цього потрібно задати час, який система буде пробувати додзвонитися на апарат, а після цього часу — програти повідомлення, що Вас немає і записати відповідь. Якщо у Вас один абонент, то все це можна описувати безпосередньо в основному контексі, але для декількох вже варто скористатися макросами.

Тому в плані набору пишемо просто

exten =>101,1,Macro(smart-dial,101)
exten =>102,1,Macro(smart-dial,102)

а всі дії будемо виконувати в макросі:
[macro-smart-dial]
exten =>s,1,Dial(SIP/${ARG1},40) 
;40 — тривалість спроб додзвону. Приблизно складає 8 гудків
exten =>s,n,Goto(s-${DIALSTATUS},1) 

;взагалі кажучи автовідповідач треба ввімкнути не тільки при відсутності відповіді, але і коли зайнято 
exten =>s-BUSY,1,Goto(s-NOANSWER,1) 
;ну і власне сам автовідповідач мав би виглядати якось так: 
exten =>s-NOANSWER,1,Answer() 
;програти щось типу «мене немає або я розмовляю, залиште повідомлення після сигналу" 
exten =>s-NOANSWER,2,Playback(/auto/invitation/${ARG1}) 
;секунду зачекати 
exten =>s-NOANSWER,3,Wait(1) 
;переконатися зайвий раз, що папка, в якій знаходяться записи все-таки існує 
exten =>s-NOANSWER,4,System(/bin/mkdir -p /auto/response/${ARG1}) 
;і записати відповідь (звуковий сигнал команда Record надсилає сама — його програвати окремо не треба) 
exten =>s-NOANSWER,5,Record(/auto/response/${ARG1}/message-%d:wav) 
;Завершити запис можна поклавши трубку або натиснувши решітку 
exten =>s-NOANSWER,6,Hangup()

Ура! Тепер всі дзвінки записані і їх можна прослухати будь-яким плеєром.

Ускладнимо задачу: припустімо, що більшість часу Вас влаштовує стандартний текст автовідповідача, але час від часу Ви хочете повідомити якусь додаткову інформацію (наприклад «Сьогодні я в відрядженні. Зателефонуйте завтра або залиште повідомлення після сигналу»).

Для цього слід запрограмувати можливість встановити своє повідомлення або відновити стандартне. Це вже буде голосове меню. На перший погляд досить просте, але навіть для його реалізації варто спочатку все намалювати на папері, а вже потім приступати до реалізації.

Давайте добре подумаємо, що ж власне ми в цьому меню дозволимо робити:
по-перше — записати власний текст (цифра 1);
по-друге — замінити самописний текст на стандартний (цифра 2);
якщо це меню лише для Вас, то необов’язково, але якщо ним будуть користуватися інші, то варто також передбачити пункт завершення роботи (цифра 0);
також слід правильно обробляти ситуації, коли користувач не робить вибору або робить неправильний вибір.

Так як пункти меню — окремі номери, то для його реалізації варто виділити окремий контекст, бо в іншому разі буде каша: з меню можна буде набрати номер, а з апарата — безпосередньо пункт меню. Тому в основному контексті пишемо:

exten =>900,1,Goto(autoresponse-menu,900,1)

і створюємо контекст з пунктами меню:
[autoresponse-menu]
exten =>900,1,Answer()
exten =>900,2,Wait(1)
;проговорюємо текст «1 — перезаписати своє повідомлення, 2 — встановити стандартне, 0 — вихід»
exten =>900,3,Background(/auto/menu-text) 
;чекаємо ще 9 секунд (asterisk має стандартні файли тривалістю 1, 2, 3..., 9 секунд) 
exten =>900,4,Background(silence/9) 
;якщо за цей час нічого не вибрано — нагадати «зробіть будь ласка вибір»
exten =>900,5,Playback(/auto/menu-noresponse) 
;і нагадати що саме 
exten =>900,6,Goto(900,2) 

;1 — записуємо повідомлення 
;проінструктуємо «продиктуйте повідомлення після сигналу, для завершення натисніть решітку»
exten =>1,1,Playback(/auto/menu-beforerecord)
exten =>1,2,Wait(1)
;з якого номера телефонують — для того і пишемо файл 
exten =>1,3,Record(/auto/invitation/${CALLERID(num)}:gsm)
exten =>1,4,Wait(1)
;дамо прослухати що вийшло, про що попередимо: «прослухайте Ваш змінений запис»
exten =>1,5,Playback(/auto/menu-yourrecord)
exten =>1,6,Wait(1)
exten =>1,7,Playback(/auto/invitation/${CALLERID(num)})
;можна б завершити, але на випадок, якщо повідомлення не сподобалося — дамо можливість поправити його
exten =>1,8,Goto(900,2)

;2 — повертаємо стандартне
;знищуємо те, що було 
exten =>2,1,System(/bin/rm -f /auto/invitation/${CALLERID(num)})
;пишемо на його місце стандартне
exten =>2,2,System(/bin/cp -a /auto/default-autoresponse.gsm /auto/invitation/${CALLERID(num)}.gsm)
;і дамо переконатися користувачу, що все в порядку
exten =>2,3,Goto(1, 4)

;0 — кладемо трубку 
exten =>0,1,Hangup() 

;не забуваємо про неправильний ввід, для нього існує спеціальне позначення i
;видаємо повідомлення «вибір невірний. Повторіть ввід» 
exten =>i,1,Playback(/auto/menu-badchoice) 
;і повертаємо на список варіантів 
exten =>i,2,Goto(900,2)

От так... На перший погляд просте меню, але для гарної і логічної реалізації довелося он скільки понаписувати.

Можна щось дописати, можна трохи скоротити (замість команд Wait і програвання silence/9 можна просто додати тишу в файли, що програються командами Playback iBackground), але загалом ідея якась отака...

Якщо маєте ідеї що ще можна придумати з IP-телефонією — пишіть — подумаємо разом.




 

Працює на AutoGenCMS 0.2.6

А чому це всі вирішили, що в сайта має бути шапка?