Различия
Показаны различия между двумя версиями страницы.
| Следующая версия | Предыдущая версия | ||
| work:telephony:cisco-ivr-tcl [2024/07/10 11:04] – создано rolland | work:telephony:cisco-ivr-tcl [2025/05/22 16:52] (текущий) – rolland | ||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| ====== Пишем голосовое IVR меню на языке TCL, с использованием Cisco IVR API ====== | ====== Пишем голосовое IVR меню на языке TCL, с использованием Cisco IVR API ====== | ||
| - | Сегодня речь о голосовом меню (**IVR**) для маршрутизаторов Cisco, которое мы будем писать на языке TCL, и подключать на Cisco 3845.\\ | + | Сегодня речь о голосовом меню (**IVR**) для маршрутизаторов Cisco, которое мы будем писать на языке TCL, и подключать на Cisco 3845. |
| ====== Итак, для начала давайте разберемся в азах ====== | ====== Итак, для начала давайте разберемся в азах ====== | ||
| Строка 7: | Строка 7: | ||
| Cisco начиная с версии **IOS** 12 поддерживает как **VXML** так и **TCL** скрипты для работы с голосовым меню. Однако, | Cisco начиная с версии **IOS** 12 поддерживает как **VXML** так и **TCL** скрипты для работы с голосовым меню. Однако, | ||
| \\ | \\ | ||
| - | Все документы, | + | Все документы, |
| ==== FSM ==== | ==== FSM ==== | ||
| Строка 15: | Строка 16: | ||
| Выглядит это примерно так: | Выглядит это примерно так: | ||
| < | < | ||
| - | '' | + | |
| - | '' | + | set ivr_fsm(CALLCOMES, |
| </ | </ | ||
| Строка 25: | Строка 26: | ||
| Общий синтаксис этой команды таков: | Общий синтаксис этой команды таков: | ||
| - | < | + | < |
| - | '' | + | set array(CURRSTATE, |
| </ | </ | ||
| - | где:\ | + | где:\ **array** – это имя // |
| - | **array** – это имя // | + | **CURRSTATE** – имя текущего состояния, |
| - | **CURRSTATE** – имя текущего состояния, | + | **act_proc** – имя функции, |
| - | **act_proc** – имя функции, | + | **NEXTSTATE** – имя состояния, |
| - | **NEXTSTATE** – имя состояния, | + | |
| \\ | \\ | ||
| Другими словами, | Другими словами, | ||
| \\ | \\ | ||
| - | Самое главное в этом — это то, что текущее событие и состояние сравниваются со всеми описанными **FSM** переходами **одновременно**. Т.е. для Cisco не имеет значения порядок, | + | Самое главное в этом — это то, что текущее событие и состояние сравниваются со всеми описанными **FSM** переходами **одновременно**. Т.е. для Cisco не имеет значения порядок, |
| ==== Функции ==== | ==== Функции ==== | ||
| Строка 44: | Строка 44: | ||
| Второй момент, | Второй момент, | ||
| \\ | \\ | ||
| - | Назначение всех команд и состояний подробно описано в файле tcl_ivr_2.0_programming_guide, | + | Назначение всех команд и состояний подробно описано в файле tcl_ivr_2.0_programming_guide, |
| ===== 1) Инициализация скрипта ===== | ===== 1) Инициализация скрипта ===== | ||
| \\ | \\ | ||
| - | Начало любого TCL IVR скрипта содержит процедуру // | + | Начало любого TCL IVR скрипта содержит процедуру // |
| < | < | ||
| - | '' | + | |
| + | proc init { } { | ||
| puts "\n proc Init start" | puts "\n proc Init start" | ||
| global param | global param | ||
| } | } | ||
| - | '' | ||
| </ | </ | ||
| - | Здесь по сути выполняется вывод на экран командой //**puts "..." | + | Здесь по сути выполняется вывод на экран командой //**puts "…" |
| \\ | \\ | ||
| - | Инициализация скрипта происходит после описания всех функций, | + | Инициализация скрипта происходит после описания всех функций, |
| \\ | \\ | ||
| Последней исполняемой строкой скрипта должна быть строка определения стартового **FSM** перехода и стартового состояния. В нашем случае это: | Последней исполняемой строкой скрипта должна быть строка определения стартового **FSM** перехода и стартового состояния. В нашем случае это: | ||
| - | < | + | < |
| - | '' | + | fsm define ivr_fsm CALLCOMES |
| </ | </ | ||
| - | Это значит, | + | Это значит, |
| ===== 2) Приветствие ===== | ===== 2) Приветствие ===== | ||
| - | < | + | < |
| + | proc Play_Welcome { } { | ||
| puts "\n\n IVR - proc Play_Welcome start \n\n" | puts "\n\n IVR - proc Play_Welcome start \n\n" | ||
| global playng_files | global playng_files | ||
| Строка 113: | Строка 115: | ||
| timer start named_timer $numbers(waiting_time) t1 | timer start named_timer $numbers(waiting_time) t1 | ||
| } | } | ||
| - | '' | ||
| - | </file> | + | </code> |
| - | Здесь довольно подробно все описано.\ | + | Здесь довольно подробно все описано. |
| - | Результатом выполнения данной процедуры будет подключение входящей линии к Cisco за счет команд //**leg setupack, leg proceeding, leg connect, | + | Результатом выполнения данной процедуры будет подключение входящей линии к Cisco за счет команд //**leg setupack, leg proceeding, leg connect, |
| - | Тут же запускается процесс сбора нажатых клавиш **//leg collectdigit// | + | |
| - | \\ | + | И проверяется рабочее сейчас время или нет, вызывая функцию // |
| - | И проверяется рабочее сейчас время или нет, вызывая функцию // | + | < |
| - | < | + | proc GetDate { } { |
| global workingtime | global workingtime | ||
| Строка 131: | Строка 132: | ||
| set dayis [clock format [clock seconds] -format %A] | set dayis [clock format [clock seconds] -format %A] | ||
| # | # | ||
| - | if {$houris > 17 || $houris < 8 || $dayis==" | + | if {$houris> |
| set workingtime 0 | set workingtime 0 | ||
| } else { | } else { | ||
| Строка 137: | Строка 138: | ||
| } | } | ||
| } | } | ||
| - | '' | ||
| </ | </ | ||
| - | В зависимости от того рабочее время или нет мы меняем музыкальный файл, который будет проигран звонящему абоненту.\ | + | В зависимости от того рабочее время или нет мы меняем музыкальный файл, который будет проигран звонящему абоненту. |
| - | Так как стартовое состояние задано в нашем случае как //**fsm define ivr_fsm CALLCOMES**// | + | Так как стартовое состояние задано в нашем случае как //**fsm define ivr_fsm CALLCOMES**// |
| < | < | ||
| - | '' | + | |
| + | set ivr_fsm(CALLCOMES, | ||
| set ivr_fsm(CALLCOMES, | set ivr_fsm(CALLCOMES, | ||
| set ivr_fsm(CALLCOMES, | set ivr_fsm(CALLCOMES, | ||
| - | '' | ||
| </ | </ | ||
| - | Событие // | + | Событие // |
| \\ | \\ | ||
| - | После окончания проигрывания музыки абоненту, | + | После окончания проигрывания музыки абоненту, |
| \\ | \\ | ||
| Таймер, | Таймер, | ||
| - | < | + | < |
| + | #Тип таймера named_timer, | ||
| timer start named_timer $numbers(waiting_time) t1 | timer start named_timer $numbers(waiting_time) t1 | ||
| - | '' | ||
| </ | </ | ||
| - | После своего окончания сгенерирует событие // | + | После своего окончания сгенерирует событие // |
| - | < | + | < |
| - | '' | + | set ivr_fsm(CALLCOMES, |
| </ | </ | ||
| - | и вызовется процедура **// | + | и вызовется процедура **// |
| ===== 3) Проверка введенного номера ===== | ===== 3) Проверка введенного номера ===== | ||
| - | < | + | < |
| + | proc CheckDestanation { } { | ||
| puts "\n\n IVR - proc CheckDestanation start \n\n" | puts "\n\n IVR - proc CheckDestanation start \n\n" | ||
| global playng_files | global playng_files | ||
| Строка 243: | Строка 244: | ||
| } | } | ||
| } | } | ||
| - | '' | ||
| - | </file> | + | </code> |
| - | В процедуре CheckDestanation, | + | В процедуре CheckDestanation, |
| - | \\ | + | < |
| - | Все состояния, | + | set ivr_fsm(CALLCONNECTED, |
| - | + | ||
| - | < | + | |
| set ivr_fsm(TORECEPTION, | set ivr_fsm(TORECEPTION, | ||
| set ivr_fsm(TRYAGAIN, | set ivr_fsm(TRYAGAIN, | ||
| set ivr_fsm(TRYING, | set ivr_fsm(TRYING, | ||
| set ivr_fsm(TRYING, | set ivr_fsm(TRYING, | ||
| - | '' | ||
| </ | </ | ||
| Строка 267: | Строка 264: | ||
| 3) Затем сравниваем полученные результаты с заданными переменными и изменяем состояние скрипта при совпадении: | 3) Затем сравниваем полученные результаты с заданными переменными и изменяем состояние скрипта при совпадении: | ||
| - | < | + | < |
| + | if {$digit == $numbers(fast_reception)} { | ||
| puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next reception \n\n" | puts "\n\n IVR - proc CheckDestanation digit = $digit\nGoing to next reception \n\n" | ||
| fsm setstate CALLCONNECTED | fsm setstate CALLCONNECTED | ||
| leg setup $numbers(reception) callinfo leg_incoming | leg setup $numbers(reception) callinfo leg_incoming | ||
| } | } | ||
| - | '' | ||
| </ | </ | ||
| Строка 278: | Строка 275: | ||
| ===== 4) Проверка номера звонящего абонента ===== | ===== 4) Проверка номера звонящего абонента ===== | ||
| - | < | + | < |
| + | proc CheckCallersAndConnect {digit} { | ||
| puts "\n\n IVR - proc CheckCallersAndConnect start \n\n" | puts "\n\n IVR - proc CheckCallersAndConnect start \n\n" | ||
| Строка 292: | Строка 290: | ||
| leg setup $digit callInfo leg_incoming | leg setup $digit callInfo leg_incoming | ||
| } | } | ||
| - | '' | ||
| </ | </ | ||
| - | Данная функция позволяет изменить поле, отвечающее за написание имени звонящего. Просто ради эстетики, | + | Данная функция позволяет изменить поле, отвечающее за написание имени звонящего. Просто ради эстетики, |
| ===== 5) Подключение номера ===== | ===== 5) Подключение номера ===== | ||
| - | < | + | < |
| + | proc CallIsConnect { } { | ||
| puts "\n\n IVR - proc CallIsConnect start \n\n" | puts "\n\n IVR - proc CallIsConnect start \n\n" | ||
| global playng_files | global playng_files | ||
| Строка 324: | Строка 323: | ||
| } | } | ||
| } | } | ||
| - | '' | ||
| - | </file> | + | </code> |
| Данная функция вызывается следующим FSM переходом: | Данная функция вызывается следующим FSM переходом: | ||
| < | < | ||
| - | '' | + | |
| - | '' | + | set ivr_fsm(CALLCONNECTED, |
| </ | </ | ||
| - | Событие // | + | Событие // |
| ===== 6) Повторный запрос номера ===== | ===== 6) Повторный запрос номера ===== | ||
| - | < | + | < |
| + | proc Play_TakeNumber { } { | ||
| puts "\n\n IVR - proc Play_TakeNumber start \n\n" | puts "\n\n IVR - proc Play_TakeNumber start \n\n" | ||
| global playng_files | global playng_files | ||
| Строка 365: | Строка 364: | ||
| } | } | ||
| } | } | ||
| - | '' | ||
| - | </file> | + | </code> |
| - | Данная функция проверяет какой раз ошибается звонящий, | + | Данная функция проверяет какой раз ошибается звонящий, |
| - | \\ | + | < |
| - | Данная функция вызывается следующими **FSM**: | + | set ivr_fsm(TRYAGAIN, |
| - | < | + | |
| set ivr_fsm(TRYING, | set ivr_fsm(TRYING, | ||
| set ivr_fsm(TRYING, | set ivr_fsm(TRYING, | ||
| - | '' | ||
| </ | </ | ||
| Строка 381: | Строка 377: | ||
| ===== 7) Разрыв соединения ===== | ===== 7) Разрыв соединения ===== | ||
| - | < | + | < |
| + | proc AbortCall { } { | ||
| puts "\n\n IVR - proc AbortCall start \n\n" | puts "\n\n IVR - proc AbortCall start \n\n" | ||
| call close | call close | ||
| } | } | ||
| - | '' | ||
| </ | </ | ||
| Вызывается следующими **FSM**: | Вызывается следующими **FSM**: | ||
| - | < | + | < |
| + | set ivr_fsm(any_state, | ||
| set ivr_fsm(CALLACTIVE, | set ivr_fsm(CALLACTIVE, | ||
| set ivr_fsm(CALLDISCONNECTED, | set ivr_fsm(CALLDISCONNECTED, | ||
| set ivr_fsm(CALLDISCONNECTED, | set ivr_fsm(CALLDISCONNECTED, | ||
| set ivr_fsm(CALLDISCONNECTED, | set ivr_fsm(CALLDISCONNECTED, | ||
| - | '' | ||
| </ | </ | ||
| Строка 404: | Строка 400: | ||
| Подключение на маршрутизаторе Cisco проходит в 2 этапа.\\ | Подключение на маршрутизаторе Cisco проходит в 2 этапа.\\ | ||
| **Первое**, | **Первое**, | ||
| - | < | + | < |
| + | application | ||
| | | ||
| param allowed_pattern 5[5-7].. | param allowed_pattern 5[5-7].. | ||
| Строка 423: | Строка 420: | ||
| param file_noworking flash: | param file_noworking flash: | ||
| param file_takenumber flash: | param file_takenumber flash: | ||
| - | '' | ||
| - | </file> | + | </code> |
| - | **Второе**, | + | **Второе**, |
| - | < | + | < |
| + | dial-peer voice 200 pots | ||
| | | ||
| | | ||
| | | ||
| - | '' | ||
| </ | </ | ||
| - | Таким образом, | + | Таким образом, |
| ===== 9) Полная версия скрипта ===== | ===== 9) Полная версия скрипта ===== | ||
| Строка 442: | Строка 438: | ||
| Выше были рассмотрены только основные функции скрипта, | Выше были рассмотрены только основные функции скрипта, | ||
| - | < | + | < |
| + | ####################################################### | ||
| # Cisco IVR TCL script by Konovalov D.A. v.2 | # Cisco IVR TCL script by Konovalov D.A. v.2 | ||
| ####################################################### | ####################################################### | ||
| # | # | ||
| # Для дебага скрипта | # Для дебага скрипта | ||
| - | # | + | # debug voip application script |
| # Более полный дебага (не рекомендуется, | # Более полный дебага (не рекомендуется, | ||
| # debug voip ivr | # debug voip ivr | ||
| Строка 650: | Строка 647: | ||
| set dayis [clock format [clock seconds] -format %A] | set dayis [clock format [clock seconds] -format %A] | ||
| # | # | ||
| - | if {$houris > 17 || $houris < 8 || $dayis==" | + | if {$houris> |
| set workingtime 0 | set workingtime 0 | ||
| } else { | } else { | ||
| Строка 901: | Строка 898: | ||
| fsm define ivr_fsm CALLCOMES | fsm define ivr_fsm CALLCOMES | ||
| - | '' | ||
| - | </file> | + | </code> |
| Источник [[https:// | Источник [[https:// | ||