Различия
Показаны различия между двумя версиями страницы.
Следующая версия | Предыдущая версия | ||
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:// | ||