Asterisk mysql налаштування російської кирилиці таблиці cdr. Набір основних функцій Asterisk. Створення додаткових функцій

Виконання маніпуляцій з базою даних MySQL Інсталяція Команда є частиною пакета доповнень, який доступний в Asterisk CVS. Це ДОДАТОК до asterisk, даний пакетне встановлюється за замовчуванням і повинен бути завантажений і встановлений з пакета доповнень. Опис MYSQL(): Виконання маніпуляцій з базою даних MySQL

З'єднання з базою даних. У аргументах містяться стандартні параметри для з'єднання з базою MySQL, які передадуть функції mysql_real_connect. Ідентифікатор з'єднання буде повернутий до змінної $(connid)

MYSQL(Query resultid $(connid) query-string)

Виконує стандартний запит до бази даних MySQL, запит міститься у параметрі query-string, використовується ідентифікатор з'єднання визначений $(connid). Результат запиту буде збережено у змінній $(resultid).

MYSQL(Fetch fetchid $(resultid) var1 var2 ... varN)

Якщо доступні для вибірки записи в результаті запиту до бази даних, $(fetchid) встановлюється в 1 і один запис буде вибраний з повернутий результат, що зберігається в $(resultid). Отримані значення полів будуть призначені змінним $(var1), $(var2)... $(varN) згідно з вказаним у запиті порядку.

Якщо немає доступних записів, змінну $(fetchid) буде скинуто в 0 і $(var1), $(var2) ... $(varN) буде повернуто без змін.

MYSQL(Clear $(resultid))

Очищає пам'ять та структури даних, пов'язаних з результатом запиту.

MYSQL(Disconnect $(connid))

Зупиняє з'єднання з базою MySQL з цим ідентифікатором.

Приклади

exten => _X.,1,MYSQL(Connect connid localhost dbuser dbpass dbname)
exten =>
exten =>
exten => _X.,4,GotoIf($[$(AGIScript) = NULL]?5:7)
exten => _X.,5,AGI($(DefaultAGIScript),$(EXTEN))
exten => _X.,6,Goto(_X.,8)
exten => _X.,7,AGI($(AGIScript),$(EXTEN))
exten => _X.,8,MYSQL(Clear $(resultid))
exten => _X.,9,MYSQL(Disconnect $(connid))
exten => _X.,10,Hangup


У наведеному вище прикладі, якщо користувач від'єднається, коли його виклик обробляється, десь у проміжку між 5 і 7 пріоритетом, тоді функції MYSQL(Clear...) і MYSQL(Disconnect....) не будуть виконані. У цьому випадку з'єднання залишиться не закритим, і з кожним новим викликом кількість незакритих з'єднань збільшуватиметься. Зрештою, в MySQL сервері закінчиться ліміт на кількість одночасно відкритих з'єднань з базою. (Залежно від встановленого ліміту конфігураційного файлу mysql). Тому для цього випадку потрібно трохи змінити послідовність дій так, як показано нижче:

exten => _X.,1,MYSQL(Connect connid localhost asterisk dbpass asterisk)
exten => _X.,2,MYSQL(Query resultid $(connid) SELECT\ scriptname\ from\ mac2pin\ where\ userid=$(CALLERIDNAME))
exten => _X.,3,MYSQL(Fetch fetchid $(resultid) AGIScript)
exten => _X.,4,MYSQL(Clear $(resultid))
exten => _X.,5,MYSQL(Disconnect $(connid))
exten => _X.,6,GotoIf($(fetchid)?7:9)
exten => _X.,7,AGI($(DefaultAGIScript),$(EXTEN))
exten => _X.,8,Hangup
exten => _X.,9,AGI($(AGIScript),$(EXTEN))
exten => _X.,10,Hangup


Примітка для цього випадку. Тут ми очищаємо пам'ять і від'єднуємося від бази даних відразу після Fetch. Це гарантує те, що перед тим як ми запустимо виконання AGI скрипт, ми будемо впевнені, що Очищення пам'яті і від'єднання від бази даних вже було виконано. Цей метод можна застосовувати, якщо Вам дійсно необхідно отримати з бази щось або унікальне, або таке, що часто змінюється. Якщо Ви використовуєте лапки, вони будуть відправлені в додаток, як частина запиту. Інші символи, для яких необхідне екранування - це лапки (\" і \"), кома (\,) і зворотний сліш (\\). (Використовуйте Mysqlscape- дивись наведений нижче приклад) Повертаються запитом поля, будуть призначені змінним в тому ж порядку, в якому вони були повернуті MySQL. Не рекомендується використовувати запит типу "SELECT *", тому що немає гарантії того, що поля, що повертаються будуть в тому порядку, в якому Ви їх очікуєте. Вам немає необхідності використовувати псевдоніми для полів типу, що вибираються з бази: "SELECT (довгий вираз) as коротке_ім'я", тому що ім'я поля не впливає на порядок полів, отриманих за цим запитом. В описі asterisk для цієї команди означає, що $(fetchid) встановлюється в TRUE, якщо є доступні записи. Це не правильно. Воно встановлюється в 1, якщо є дані після виконання останньої операції fetch і встановлюється в 0, якщо ні.

exten => 888,1,MYSQL(Connect connid localhost ipcontact passwd ipcontact)
exten => 888,2,MYSQL(Query resultid $(connid) SELECT\ `number`\ FROM\ `phones`\ WHERE\ `channel`=\"$(chan)\")
exten => 888,3,MYSQL(Fetch foundRow $(resultid) number) ; fetch row
exten => 888,4, GotoIf($["$(foundRow)" = "1"]?7:5) ; leave loop if no row found
exten => 888,5,NoOp($(number))
exten => 888,6, Goto (3); continue loop if row found
exten => 888,7,MYSQL(Clear $(resultid))
exten => 888,8,MYSQL(Disconnect $(connid))

Примітки __Зверніть увагу на виправлення з MYSQL(Fetch). $(fetchid) - не обов'язково встановлюється в 1, якщо є доступні дані, ця функція встановлює це поле в 1, якщо є дані тільки для цього конкретного виклику MYSQL(Fetch). Це було спочатку неправильно пояснено ще з створення опису цієї функції.
Якщо Ви не очистите пам'ять і не від'єднаєтеся від MySQL, з'єднання залишаться відкритими і зрештою їх кількість досягне ліміту, встановленого для сервера MySQL. Тоді, єдиний шлях виправити цю ситуацію - це перезавантаження Asterisk, або ще можна переглянути список процесів і прибити ці висять процеси командою kill.
На додаток до вищесказаного, Flobi придумав деяке збочення для очищення ресурсів. Так як я не вловив логіку його дій і знайшов її повним маренням, то перекладати я це не став.

Файл cdr.conf призначений для запису параметрів дзвінків у файл або базу даних. Зберігання записів дзвінків буває необхідно для обліку дзвінків та часу розмови абонента, запобігання шахрайству тощо. . Параметри файлу cdr.conf вказують, як asterіsk повинен обробляти цю інформацію.
Список деяких параметрів розділу cdr.conf:

enable = yes\no - Пишеться чи ні CDR. За промовчанням – yes.

batch = yes\no - дозволяє записувати дані в буфер, а не в базу даних, щоб скоротити навантаження на систему.
Якщо встановлено значення yes, у разі несподіваного збою системи дані можуть бути втрачені!

size = 100 Максимальна кількість записів CDR, що накопичуються у буфері перед передачею на серверну частину систем зберігання CDR. Потрібно використовувати, якщо batch = yes. За замовчуванням – 100 записів.

time = 300 Через який час у секундах очищається буфер і вносяться дані до бази даних, незалежно кількості записів у буфері (визначається параметром size). Значення за промовчанням – 300 с.

scheduleronly = yes/no. При передачі у віддалену базу даних великого обсягу CDR-записів, потрібно задати для scheduleronly значення yes. Ця установка буде вказувати Asterisk обробляти запис CDR в новому потоці, по суті, призначаючи спеціальний планувальник для цієї функції.

safeshutdown = yes/no. Значення yes не дасть Asterisk повністю вимкнутись, поки буфер не буде повністю очищений і вся інформація не буде записана до бази даних. Якщо для цього параметра встановлено значення no і відбувається вимкнення Asterisk за наявності інформації в буфері, ця інформація, швидше за все, буде втрачена.

endbeforehexten = yes\no. Значення за промовчанням – no. Якщо вказати yes, CDR буде завершуватися перед виконанням додаткового номера h, тому такі значення CDR, як end і billsec, можуть бути вилучені в цьому додатковому номері.

Докладнішу інформацію можна отримати у шаблоні cdr.conf.

Приклад файлу cdr.conf:
;
; Asterisk Call Detail Record engine configuration
;
; CDR є Call Detail Record, який забезпечує сервісне обслуговування за допомогою різних
; pluggable backend modules. Detailed call information can be recorded to
; databases, files, etc. Useful for billing, fraud prevention, compliance with
; Sarbanes-Oxley як The Enron Act, QOS evaluations, і більше.
;

; Define whether or not to use CDR logging. Setting this to "no" will override
; any loading of backend CDR modules. Default is "yes".
;enable=yes

; Define whether or not to log unanswered calls. Setting this to "yes" will
; report every attempt to ring a phone in dialing attempts, when it was not
; answered. Для прикладу, якщо ви намагаєтеся дати 3 extensions, і ця option is "yes",
; ви повинні отримати 3 CDR", один для кожного телефону, який був rung. Default is "no".
; find this information horribly useless. Інші find it дуже valuable. Note, in "yes"
; Може, ви будете один CDR, з одним call targets на одній стороні, і originating
; канал на іншому, і один CDR для кожного каналувідбувається. This may seem
; redundant, але cannot be helped.
;
; У брифе, ці опції керують повідомленнями про unanswered calls, які тільки мають an A
; party. Calls which get offered to outgoing line, але є unanswered, є still
; logged, and that is the intended behaviour. (It also results in some B side CDRs being
; output, як вони мають B side channel as their source channel, and no destination
; channel.)
;unanswered = no

; Define whether or not log congested calls. Setting this to "yes" will
; report each call that fails to complete due to congestion conditions. Default
; is "no".
;congestion = no

; Normally, CDR's не closed out until after all extensions are finished
; executing. By enabling this option, the CDR will be ended before executing
; the "h" extension and hangup handlers so that CDR values ​​such as "end" and
; "billsec" може бути віднесено до цієї extension.
; The default value is "no".
;endbeforehexten=no

; Normally, "billsec" field logged to the backends (text files or databases)
; is simply the end time (hangup time) мінус the answer time in seconds. Internally,
; Asterisk stores the time in terms of microseconds and seconds. By setting
; почати секунди до "Yes", ви можете for asterisk to report any seconds
; що були initiated (а sort of round up method). Technically, this is
; коли microsecond part of the end time is greater than the microsecond
; Частина answer time, then billsec time is incremented one second.
; The default value is "no".
;initiatedseconds=no

; Define the CDR batch mode, де instead of posting the CDR at the end of
; every call, the data will be stored in buffer to help alleviate load on the
; Asterisk Server. Default is "no".
;
; WARNING WARNING WARNING
; Використовуйте batch mode result в data loss after unsafe asterisk termination
; ie. software crash, power failure, kill-9, etc.
; WARNING WARNING WARNING
;
;batch=no

; Define the maximum number of CDRs accumulate in the buffer before posting
; them to the backend engines. "batch" must be set to "yes". Default is 100.
;size=100

; Define the maximum time to accumulate CDRs in the buffer before posting them
; до backend engines. If this time limit is reached, then it will post the
; записи, незрівнянно з значенням, визначеним для "サイズ". "batch" must be set to
; "Yes". Note that time is in seconds. Default is 300 (5 minutes).
;time=300

; CDR Engine використовує внутрішній Asterisk Scheduler для визначення, коли для post
; records. Posting can either occur inside scheduler thread, or a new
; thread can be spawned for the submission of every batch. Для невеликих batches,
; it might be aceptable to just use the scheduler thread, so set this to "yes".
; Для великих batches, say anything over size=10, а новий thread is recommended, so
; set this to "no". Default is "no".
;scheduleronly=no

; Якщо стріляти вниз стереотип, ви можете блокувати until the CDRs є submitted. If
; ви не будете, якщо ви збираєтеся скоротитися.
; CDR batch buffer with CLI "cdr status" command. To enable blocking on
; Зміщення CDR data під час астеріського shutdown, набір цього до "Yes". Default
; is "yes".
;safeshutdown=yes

;
;
; CHOOSING A CDR "BACKEND" (what kind of output to generate)
;
; Для того, щоб вибрати backend, ви маєте зробити, щоб вони були правою категорією is
; defined in this file, or that the appropriate config file exists, and has the
; proper definitions in it. Якщо є будь-які проблеми, зазвичай, введення буде
; silently ignored, і ви не output.
;
; Also, please note that you can generate CDR records in as many formats as you
; wish. Якщо ви configure 5 різних CDR форматів, то їх буде will be logged
; in 5 different places! У розділі config files, all formats are commented
; out except for cdr-csv format.
;
; Тут є всі можливі back ends:
;
; csv, custom, manager, odbc, pgsql, radius, sqlite, tds
; (Але, MySQL є можливим за допомогою астеріських-документів, що licensing
; requirements)
; (please note, also, що інші backends може бути створена, створена
; a новий backend module in the source cdr/ directory!)
;
; Кілька modulів потрібні для здійснення цих backends не буде збудовано або налаштовано
; unless some dependency requirements are met. Examples of this are pgsql, odbc,
; etc. If you not getting output as you would expect, перша thing to do
; is to run the command "make menuselect", and check what modules are available,
; by looking в "2. Call Detail Recording" option в main menu. If your
; backend is marked with XXX, ви знаєте, що "configure" command could not find
; потрібні libraries for that option.
;
; Використовуйте CDRs, щоб бути заблокованим на плагін-jane /var/log/asterisk/cdr-csv/Master.csv
; file, define the category in this file. Не потрібнобагато. The example
; config files є set up to provide this kind of output by default.
;
; Щоб отримати custom csv CDR записи, можна отримати cdr_custom.conf file
; is present, and contains the proper section. The advantage to
; using this backend, is that you can define which fields to output, and in
; what order. Залежно від тега, налаштування параметрів, які ви збираєтеся встановити в mimic cdr-csv
; output. If you don"t make any changes to the mappings, ви є basically generating
; той самий, як cdr-csv, але expending more CPU cycles to do so!
;
; Щоб отримати manager events generated, make sure the cdr_manager.conf file exists,
; and the section is defined, with the single variable "enabled = yes".
;
; Для odbc, мабуть, всі загальні libs є налагодженим, що "маке menuselect"
; Указують, що modules є available, and the cdr_odbc.conf file exists, and

;
; Для pgsql, мабуть, всі загальні libs є налагодженим, що "make menuselect"
; Досліджують, що moduly є наявними, і cdr_pgsql.conf file exists, and
; has a section with the property variables defined.
;
; Для того, щоб залучити до радіусу databases, маю на увазі всі подібні libs є installed, що
; "make menuselect" shows that the modules є available, and the
; category is defined в цьому файлі, і в цьому розділі, робиться "radiuscfg"
; variable is property pointing to an existing radiusclient.conf file.
;
; Для loging до sqlite databases, make sure the "cdr.db" file exists in the log directory,
; which is usually /var/log/asterisk. Of course, the properties libraries should be available
; під час "configure" operation.
;
; Для tds logging, make sure the property libraries are available during the "configure"
; phase, and that cdr_tds.conf exists and is property set up with a category.
;
; Also, remember, що якщо ви збираєтеся до log CDR info для 데이터베이스, ви будете визначати
; a specific table in that databse to make things work! See the doc directory for more details
; on how to create this table in each database.

Запис статистики, Asterisk, веде автоматично, якщо завантажено модуль cdr_csv.so, статистика ведеться за замовчуванням /var/log/asterisk/cdr-csv/Master.csv. Цієї статистики в принципі достатньо, але працювати не зручно. Найзручніше обробляти статистику, що зберігається в базі. Для того, щоб статистика писалася в MySQL потрібно встановити з портів:

попередньо додавши в Makefile рядок:

CFLAGS+=-DMYSQL_LOGUNIQUEID

cd / usr / ports / net / asterisk-addons /
make install clean

На початку з'явиться конфігураційний діалог з одним пунктом:

┌───────────────────────────────────────────────── ───────────────────┐ │ Options for asterisk-addons 1.4.6_4 │ │ ┌────────────────── ──────────────────────────────────────────────┐ │ │ │ [ X ] Install sample configuration files │ │ │ │ │ │ │ │ │ │ ├─└──────────────────────────── ───────────────────────────────────┘─┤ │ [ OK ] Cancel │ └───── ────────────────────────────────────────────────── ─────────────┘

Вибираємо цей пункт, дозволяє розмістити приклади конфігураційних файлів. А приклади нам знадобляться і чекаємо коли збереться модуль.
Звичайно, у вас вже має бути сервер MySQL, клієнта при складанні порт витягне за депендами.
Після того, як все обереться, приступаємо до налаштування.
Насамперед створимо базу asterisk в MySQL і користувача asterisk з паролем asterisk-123. Для цього підключаємося до MySQL та виконуємо такі команди:

mysql -uroot
create database asterisk;
grant all on asterisk.

і тепер створимо таблицю в якій зберігатимемо інформацію:


USE asterisk;

CREATE TABLE `cdr` (
`calldate` datetime NOT NULL default "0000-00-00 00:00:00" ,
` clid ` varchar(80 ) NOT NULL default "" ,
` src ` varchar(80 ) NOT NULL default "" ,
` dst` varchar(80 ) NOT NULL default "" ,
` dcontext` varchar(80 ) NOT NULL default "" ,
` channel ` varchar(80 ) NOT NULL default "" ,
` dstchannel` varchar(80 ) NOT NULL default "" ,
` lastapp` varchar(80 ) NOT NULL default "" ,
` lastdata` varchar(80 ) NOT NULL default "" ,
` duration` int(11 ) NOT NULL default "0" ,
` billsec` int(11 ) NOT NULL default "0" ,
`disposition` varchar(45 ) NOT NULL default "" ,
` amaflags` int(11 ) NOT NULL default "0" ,
`accountcode` varchar(20 ) NOT NULL default "" ,
`userfield` varchar(255 ) NOT NULL default "",

` uniqueid ` varchar(32 ) NOT NULL DEFAULT ""

) ;

Як ви можете помітити наведена таблиця без індексів. Чому? Та все дуже просто, індекси при кожній вставці нового запису перераховуються, це сповільнює роботу з базою. При великій інтенсивності дзвінків це може негативно позначиться на роботі. Якщо вам швидкість побудови звіту важливіша (робота select, вибірка статистики), можна додати індекси.

create index cld_idx on cdr(calldate);
create index src_idx on cdr(src);
create index dst_idx на cdr(dst) ;
create index acc_idx на cdr(accountcode) ;

Тепер налаштуємо підключення до MySQL, для цього внесемо у файл /usr/local/etc/asterisk/cdr_mysql.conf налаштування на наш обліковий запис MySQL:


[global]
hostname = localhost
dbname = Asterisk
table = cdr
password = asterisk-777
user = Asterisk
sock =/tmp/ mysql.sock
userfield =1

І завантажити модуль в астериск. Для цього підключимося до працюючого астериску і завантажимо модуль:
exten => _8.,1 ,MYSQL(Connect connid localhost asterisk asterisk-777 asterisk)
exten => _8.,2 ,Dial(SIP/ prov1/ $(EXTEN) )
exten => h,1 ,MYSQL(Disconnect $(connid) )

Останній рядок MYSQL(Disconnect $(connid)) - обов'язковий, задається він в extention h. h - це обробник викликаний при hangup, тобто коли розривається канал зв'язку, а коли одна зі сторін кладе трубку.

Найчастіше викликається інтерфейс SIP. Виклик здійснюється командою Dial().


exten => 100,1,Dial(DAHDI/1,20,tTr)
exten => 100,2, Voicemail ( u100@default)
exten => 100,102,Voicemail( b100@default)
;
exten => 105,1,Dial(SIP/105,20,tTr)
exten => 105,n,Voicemail( u100@default)
exten => 105,n,Voicemail( b100@default)

Цей приклад ілюструє різні варіантидій, якщо на виклик не відповіли. Спочатку викликається канал DAHDI/1, якщо через 20 секунд ніхто не відповів виклик перенаправляється на VoiceMail() з оголошенням «абонент не відповідає»(u100), якщо абонент зайнятий, виклик перейде на пріоритет N+101, в нашому випадку це пріоритет 102 .

2.2.2 Маршрутизація по CallerID до Asterisk

Приклад маршрутизації за номером абонента:


exten => 100/1234567,1,Congestion
exten => 100,1,Dial(DAHDI/1,20)
exten => 100,2,Voicemail(u100)
exten => 100,102,Voicemail(b100)

Якщо викликається екстеншен 100, то виклик спрямовується на інтерфейс DAHDI/1, крім випадку, якщо виклик здійснює абонент з номера 1234567. У цьому випадку виклик відхиляється. На прикладі видно, що ідентифікатор абонента, що викликає, задається формою "/1234567".

Ще один приклад маршрутизації, тепер за відсутністю CallerID:


exten => 100/,1,Zapateller
exten => 100,1,Wait(1)
exten => 100,2,Dial(DAHDI/1)

У цьому прикладі, якщо надходить дзвінок без CallerID, то виклик блокується за допомогою програми Zapateller().

2.2.3 Виклик групи телефонів до Asterisk

Часто потрібно, щоб виклик через невідповідь перейшов на інший телефон. Розглянемо як це зробити з прикладу «оператор».


exten => _X.,1,Dial(DAHDI/1,15)
exten => _X.,2,Dial(DAHDI/1&DAHDI/2&DAHDI/3,15)
exten => _X.,3,Playback(companymailbox)
exten => _X.,4,Voicemail(100)
exten => _X.,5,Hangup

Виклик надходить на DAHDI/1, якщо телефон зайнятий або не відповідає протягом 15 секунд, дзвінок переходить на групу телефонів, включаючи DAHDI/1. Якщо й цього разу ніхто не піднімає слухавку, дзвінок переходить на голосову пошту.

2.2.4 Вкладені контексти

Один контекст може включати інші контексти, оброблювані в порядку перерахування.

include => [||||]

Де - контекст, що включається
опціонально може використовуватися:

  • - годинник в який дійсний контекст (наприклад робочий час 9:00-17:00)
  • -Дні тижня (mon-fri)
  • - дні
  • - Місяці


exten => _.,1,Dial(SIP/trunk1/$(EXTEN))

exten => _8.,1,Dial(SIP/trunk2/$(EXTEN))

include => local
include => long

include => local

У цьому прикладі контекст "local_long" включає два інших контексти для міської та міжміського зв'язкуа контекст "local_only" тільки для міської.

2.2.5 Вихідні дзвінки в діалплані Asterisk

Напрямок вихідного зв'язку можна реалізувати визначенням короткого коду доступу (наприклад "9"), або визначити повністю шаблон номерів, що набираються.


ignorepat => 9
exten => _9810.,1,Dial(DAHDI/g2/$(EXTEN:1))
exten => _9810.,2,Congestion
include => longdistance

ignorepat => 9
exten => _98XXXXXXXXX,1,Dial(DAHDI/g2/$(EXTEN:1))
exten => _98XXXXXXXXX,2,Congestion
include => local

ignorepat => 9
exten => _9XXXXXX,1,Dial(DAHDI/g2/$(EXTEN:1))
exten => _9XXXXXX,2,Congestion
include => default

У цьому прикладі розглядаються 3 контексти з різними правами доступу до Телефонної мережі Загального Користування.

Конструкція "ignorepat => 9" говорить Астеріску не відключати тон готовності після набору заданої цифри.

Контекст дозволяє набрати міжнародний номер із будь-якою кількістю цифр.
Контекст - міжміський номер до 11 цифр.
Контекст - міський номер довжиною до 7 цифр.

Змінна $(EXTEN:1) видаляє префікс:

  • $(123456789:1) - повертає рядок 23456789
  • $(123456789:-4) - повертає рядок 6789
  • $(123456789:0:3) - повертає рядок 123
  • $(123456789:2:3) - повертає рядок 345
  • $(123456789:-4:3) - повертає рядок 678

2.2.6 Автовідповідач-ехотест

Автовідповідач-ехотест необхідний, щоб абонент міг зателефонувати до нього, протестувати якість зв'язку та працездатність свого клієнтського обладнання. При дзвінку на будь-який внутрішній номер (наприклад 7000) відбуватиметься таке:

  • Відповідаємо на дзвінок.
  • Програється заздалегідь підготовлений аудіофайл-привід.
  • Голос записаного протягом декількох секунд, потім відтворюється зателефонував.
  • Програється заздалегідь підготовлений аудіофайл-прощання.
  • Завершення дзвінка.

Для реалізації цього сценарію додаємо у файл extension.conf:

Exten => 7000,1,Answer() ;Піднімаємо трубку
exten => 7000,n,Wait(2) ;Чекання 2 секунди
exten => 7000,n,Playback(/etc/asterisk/sounds/demo-echotest) ;Програємо привітання
exten => 7000,n,Wait(1) ;Чекання 1 секунду
exten => 7000,n,Set(fname=/etc/asterisk/sounds/records/$(STRFTIME($(EPOCH),%Y-%m-%d__%H-%M-%S))__$( CALLERID(number))) ;Задаємо ім'я та розташування файлу-аудіозапису
exten => 7000,n,Record($(fname).gsm,0,10,x) ;Записуємо голос телефонуючого протягом 10 секунд
exten => 7000,n,Playback(/etc/asterisk/sounds/beep) ;Повідомляємо про закінчення запису голосу сигналом
exten => 7000,n,Wait(1) ;Чекання
exten => 7000,n,Playback($(fname)) ;Відтворення запису голосу
exten => 7000,n,Playback(/etc/asterisk/sounds/demo-echodone) ;Програємо прощання
exten => 7000,n,Wait(2) ;Чекання
exten => 7000,n,Hangup() ;Завершуємо виклик

2.2.7 Озвучити поточний час сервера

Exten = 060,1, PlayBack (welcome)
exten = 060,n,PlayBack(digits/today)
exten = 060,n,SayUnixTime(,a)
exten = 060,n,SayUnixTime(,k)
exten = 060,n,PlayBack(hours)
exten = 060,n,SayUnixTime(,M)
exten = 060,n,PlayBack(minutes)
exten = 060,n,PlayBack(goodbye)
exten = 060,n,Hangup()

2.2.8 Функція диктофон

Exten = 98,1, Answer ()
exten = 98,n,Record(/tmp/myrecord%d:wav)
exten = 98,n,Wait(1)
exten = 98,n,Playback($(RECORDED_FILE))
exten = 98,n,Wait(1)
exten = 98,n,Hangup()

2.2.9 Порядок вибору потрібного вихідного маршруту під час використання шаблонів

Кожен контекст, визначений у плані набору, вказує Asterisk, як обробляти телефонні номери, виклики на які потрапляють у цей контекст. Оскільки у Вас є можливість використання шаблонів при визначенні екстеншенів, то цілком ймовірна ситуація, при якій телефонному номеру, що викликається, може бути зіставлений не один, а кілька екстеншенів у контексті. Asterisk не шукатиме відповідних збігів із шаблонними екстеншенами в тому порядку, що Ви описали в плані набору, т.к. Спочатку шаблонні екстеншени проходять сортування. Отже Asterisk може обробити виклик телефонного номера зовсім не так, як Вам хотілося б.

В даному прикладі описується, як Asterisk сортує шаблонні екстеншени і як керувати цим порядком сортування, щоб бути впевненим, що Asterisk вибере саме той екстеншен, який Вам потрібен, коли з номером, що викликається, можуть збігатися два або більше шаблонних екстеншенів. Розглянемо контекст «example», наприклад, Вам потрібно, щоб дзвінки на всі номери, що починаються з 918, проходили через аналогову телефонну лінію, з'єднану з інтерфейсом DAHDI/1, а решта всіх викликів проходили через інтерфейс SIP/200. Напишемо приклад:


exten => _918.,1,Dial(DAHDI/1/$(EXTEN),tTr)
exten => _.,1,Dial(SIP/200/$(EXTEN))
exten => h,1,Hangup

Але така конструкція не працює як нам треба! Ви виявите, що незалежно від набраного номера всі виклики йдуть через інтерфейс SIP/200. Справа в тому, що спочатку Asterisk сортує екстеншени, а вже потім шукає перший збіг. Для того, щоб побачити в якому порядку Asterisk здійснює пошук співпадаючого екстеншена, наберіть у консолі Asterisk команду: "show dialplan example". Ви побачите, що екстеншен відсортовано в наступному порядку:

1. _.
2. _918.
3. h

Зауважте, що цей порядок зовсім не той, що ви визначили у файлі extensions.conf. У цьому списку запис _. є першою, а вона має на увазі збіг з будь-яким набраним номером, включаючи і номери, які починаються з 918. Варто зазначити, що екстеншен h (hangup), також ніколи не буде обраний, тому що він теж збігатиметься з шаблоном _.
Отже, як змусити Asterisk перевіряти шаблонні екстеншени на збіги в потрібному порядку? Є вихід - це використовувати директиву include, включаючи до поточного контексту інший контекст, що містить шаблонні екстеншени. Наприклад:


include => example-sub
exten => h,1,Hangup
exten => _918.,1,Dial(Zap/1/$(EXTEN))

exten => _.,1,Dial(Zap/2/$(EXTEN))

Тепер Asterisk (для контексту «example») перевірятиме номер на збіг у такому порядку:

1. _918.
2. h
3. _.

Що в цьому випадку робить Asterisk:

  • Записи exten усередині контексту "example" будуть збережені першими і, відповідно, перевірятися також будуть першими.
  • Включені контексти кожною директивою include будуть зберігатися у порядку їх опису.

Включені контексти перевірятимуться на збіг у порядку їх опису у файлі extensions.conf

2.2.10 Dynamic Clip Routing

Вхідні дзвінки на внутрішнього абонента, що дзвонив

Внутрішній абонент Asterisk виконує вихідний викликна міський чи мобільний номер. Коли зовнішній абонент передзвонює на міську лінію Asterisk, його виклик спрямовується безпосередньо на внутрішнього абонента Asterisk, що дзвонив. Для визначення внутрішнього номера абонента використовується стандартна база даних MySQL asteriskcdrdb, яка створюється веб-інтерфейсом FreePBX.


exten => _X.,1,Set(CHANNEL(language)=ru)
exten => _X.,n,Set(CALLID=$(CALLERID(num):-11))
exten => _X.,n,MYSQL(Connect connidcdr localhost userdb passworddb asteriskcdrdb utf8);; All CALL
exten => _X.,n,MYSQL(Query resultidcdr $(connidcdr) SELECT * FROM cdr WHERE dst LIKE "%$(CALLID)%" ORDER BY calldate DESC)
;;; NOANSWER CALL ONLY
;;exten => _X.,n,MYSQL(Query resultidcdr $(connidcdr) SELECT * FROM cdr WHERE dst LIKE "%$(CALLID)%" AND disposition LIKE "NO ANSWER" ORDER BY calldate DESC)
;;
exten => _X.,n,MYSQL(Fetch fetchid $(resultidcdr) accid calldate clid src dst)
exten => _X.,n,Set(number=$(src))
exten => _X.,n,NoOp(caller --> $(clid) callee --> $(dst))
exten => _X.,n,GOTOIF($["$(dst)" = ""]?nodst:dst)
exten => _X.,n(dst),MYSQL(Clear $(resultidcdr))
exten =>
exten => _X.,n,Dial(SIP/$(number),20,tT)
exten => _X.,n,GotoIf($["$(DIALSTATUS)" = "BUSY"]?nodst)
exten => _X.,n,GotoIf($["$(DIALSTATUS)" = "NOANSWER"]?nodst)
exten => _X.,n,GotoIf($["$(DIALSTATUS)" = "FAILED"]?nodst)
exten => _X.,n(nodst),MYSQL(Clear $(resultidcdr))
exten => _X.,n,MYSQL(Disconnect $(connidcdr))
exten => _X.,n,Goto(from-trunk,$(DID),1)
exten => h,1,hangup()

Вибір даних за останні 120 хвилин

SELECT * FROM cdr WHERE dst LIKE "%$(CALLID)%" AND calldate >= DATE_SUB(NOW(), INTERVAL 120 MINUTE) ORDER BY calldate DESC;

або за три години:

SELECT * FROM cdr WHERE dst LIKE "%$(CALLID)%" AND calldate >= DATE_SUB(NOW(), INTERVAL 03 HOUR) ORDER BY calldate DESC;

Виведення консолі Asterisk при маршрутизації по cdr БД:

Executing [ 3216111@from-samsung:1] Goto("SIP/samsung-00001694", "dynamic_did,3216111,1") in new stack
- Goto (dynamic_did,1111,1)
-- Executing [ 3216111v@dynamic_did:1] Set("SIP/samsung-00001694", "CHANNEL(language)=ru") in new stack
-- Executing [ 3216111@dynamic_did:2] Set("SIP/samsung-00001694", "CALLID=8129981138 ") в новому станку
-- Executing [ 3216111@dynamic_did:3] MYSQL("SIP/samsung-00001694", "Connect connidcdr localhost userdb passworddb asteriskcdrdb utf8") in new stack
-- Executing [ 3216111@dynamic_did:4] MYSQL("SIP/samsung-00001694", "Query resultidcdr 11 SELECT * FROM cdr WHERE dst LIKE "%8129981138%" AND calldate >= DATE_SUB(NOW(), INTERVAL 03 HOUR)") in new
-- Executing [ 3216111@dynamic_did:5] MYSQL("SIP/samsung-00001694", "Fetch fetchid 12 accid calldate clid src dst") in new stack
WARNING: app_mysql.c:498 aMYSQL_fetch: ast_MYSQL_fetch: More fields (24) than variables (5)
-- Executing [ 3216111@dynamic_did:6] Set("SIP/samsung-00001694", "number=1000") in new stack
-- Executing [ 3216111@dynamic_did:7] NoOp("SIP/samsung-00001694", "хто дзвонив --> 1000 кому дзвонив --> 8129981138") in new stack
-- Executing [ 3216111@dynamic_did:8] GotoIf("SIP/samsung-00001694", "0?nodst:dst") in new stack
- Goto (dynamic_did,1111,9)
-- Executing [ 3216111@dynamic_did:9] MYSQL("SIP/samsung-00001694", "Clear 12") in new stack
-- Executing [ 3216111@dynamic_did:10] MYSQL("SIP/samsung-00001694", "Disconnect 11") in new stack
-- Executing [ 3216111@dynamic_did:11] Dial("SIP/samsung-00001694", "SIP/1000,20,tT") in new stack

2.2.11 Введення DTMF сигналів з клавіатури телефону та запис даних у текстовий файл

Викликаючий абонент вводить dtmf сигнали, цифри, що набираються, записуються в текстовий файл.

Exten => s,1,Answer()
exten => s,2,Playback(access-code)
exten => s,3,Read(myvar,beep,6,15)
exten => s,n,SayDigits($(myvar))
exten => s,n,Set(CDR(userfield)=$(myvar))
exten => s,n,Verbose($(myvar))
exten => s,n,System(echo "$(CALLERID(num))" - "$(myvar)" >> /var/log/asterisk/test)

Опис кроків контексту:

  • Answer - відповісти на дзвінок (установити з'єднання)
  • Playback – програти стандартне повідомлення (введіть код).
  • Read - вважати дані, що вводяться користувачем, і зберегти їх у змінну $myvar
  • SayDigits - проговорити дані, збережені в змінній.
  • Set / function "CDR" - зберегти дані зі змінної в полі userfield CDR.
  • Verbose - вивести дані змінної в консоль та балку.
  • System - записати дані змінно до текстового файлу з нового рядка.

2.2.12 Введення DTMF сигналів з клавіатури телефону та збереження до бази даних MySQL

Exten => s,n,Authenticate(/tmp/pass,a)
exten => s,n,Playback(/var/lib/asterisk/sounds/custom/data)
exten => s,n,Read(data,beep,3,15)
exten => s,n,SayDigits($(data))
exten => s,n,MYSQL(Connect connid localhost test test test)
exten => s,n,MYSQL(Query resultid $(connid) INSERT INTO _$(myvar) SET callerid=$(CALLERID(name)), data=$(data), date=$(STRFTIME($(EPOCH)) ,%C%y%m%d%H%M)))
exten => s,n,MYSQL(Clear $(connid))

Схоже на попередній приклад, лише дані зберігаються в MySQL.

MYSQL (Connect connid dhhost [: dbport] dbuser dbpass dbname) - з'єднатися з БД
MYSQL(Query resultid $(connid) query-string) - записати дані в БД
MYSQL(Clear $(resultid)) - очистити пам'ять

2.2.13 Обмеження кількості одночасних дзвінків за набраним номером

  • Набирається номер 810ХХХХХХХ, у консоль виводиться повідомлення: Asterisk dialing 810ХХХХХХХ
  • функція GROUP() призначає дзвінки до групи long
  • У консоль виводиться повідомлення: Number of concurrent calls are $(GROUP_COUNT(long)) де $(GROUP_COUNT(long) = порядковий номер виклику.
  • Перевіряється умова, якщо кількість одночасних дзвінків більше 1, дзвінок направляється в екстеншен 666 і роз'єднується з виведенням в консоль: Number of concurrent calls are 2 over limit.
  • Якщо перший виклик, номер набирається через SIP транк provider.

    Exten => _810.,1,Verbose(1,***** Asterisk dialing $(EXTEN) *******)
    same => n,Set(GROUP()=long)
    same => n,Verbose(1,**** Number of concurrent calls are $(GROUP_COUNT(long)))
    same => n,GotoIf($[$(GROUP_COUNT(long)) > 1]?666)
    same => n,Set(CDR(userfield)=unblocked$(EXTEN))
    same => n,Dial(SIP/provider/$(EXTEN),60)
    same => 666,Verbose(1,***Number of concurrent calls are $(GROUP_COUNT(long)) over limit)
    same => n,Set(DIALSTATUS=CHANUNAVAIL)

    2.2.14 Резервні транки та LCR (вибір напрямку для вихідних дзвінків з найменшою вартістю)

    Дуже корисно налаштувати LCR (Least Coast Routing) та перенаправлення у разі відмови зовнішньої лінії.


    exten => _98XXXXXXXXXX,1,Dial(DAHDI/g2/$(EXTEN:1))
    exten => _98XXXXXXXXXX,2,Congestion()

    exten => _98495XXXXXXX,1,Dial(IAX/trunk/$(EXTEN:1),tTr)
    exten => _98495XXXXXXX,n,Dial(DAHDI/g2/$(EXTEN:1))
    exten => _98495XXXXXXX,n,Congestion()

    include => low_rate_moscow
    include => tolllongdistance

    У цьому прикладі міжміські виклики направляються на DAHDI інтерфейс, але дзвінки до Москви направляються через вигідніший провайдер на IAX транк. У разі недоступності IAX транку, дзвінки перенаправляються через DAHDI.

    Однією з найпопулярніших (або, можливо, непопулярних) функцій будь-якої сучасної телефонної системи є голосова пошта. Природно, Asterisk має досить гнучку систему голосової пошти. Серед її можливостей можна згадати:

    • Необмежені за розміром захищені паролем скриньки голосової пошти, у кожному з яких містяться поштові папкидля
    • організації повідомлень голосової пошти.
    • Різні вітання для станів «зайнято» та «недоступний».
    • Стандартні та спеціальні привітання.
    • Можливість зв'язувати телефони з кількома поштовими скриньками, а поштові скриньки – з кількома телефонами.
    • Повідомлення про надходження повідомлення голосової пошти електронною поштою з можливістю прикріплення повідомлення голосової пошти
    • пошти як звукового файла.
    • Пересилання та широкомовні розсилки голосової пошти.
    • Індикатор повідомлень, що очікують (блимає світловий індикатор
    • або переривчастий сигнал) у багатьох типах телефонів.
    • Каталог скриньок голосової пошти службовців компанії.

    Конфігурація голосової пошти описується у конфігураційному файлі voicemail.conf. Цей файл містить набір налаштувань, які можуть використовуватися для приведення системи голосової пошти у відповідність до конкретних вимог.

    Створення поштових скриньок - Всередині кожного контексту голосової пошти визначаються різні поштові скриньки. Для опису поштової скриньки використовується наступний синтаксис:
    поштова скринька => пароль,ім'я[,email[,email_пейджера[,опції]]]
    Пояснимо призначення кожної частини опису поштової скриньки:

    • Поштова скринька – це номер поштової скриньки. Зазвичай він відповідає додатковому номеру асоційованого з ним телефону.
    • пароль - Числовий пароль, який буде використовуватись власником поштової скриньки для доступу до своєї голосової пошти. Якщо користувач змінить пароль, система оновить це поле у ​​файлі voicemail.conf.
    • Ім'я – це ім'я власника поштової скриньки. Текст цього поля використовується у телефонному довіднику компанії для забезпечення можливості абонентам при викликі застосовувати імена користувачів.
    • email - Це адреса електронної пошти власника скриньки голосової пошти. Asterisk може надсилати повідомлення про отримання голосової пошти (включаючи повідомлення голосової пошти) на задану скриньку електронної пошти.
    • email_пейджера – це електронна адреса пейджера або мобільного телефону власника скриньки голосової пошти. Asterisk може надсилати коротке повідомлення, що повідомляє про отримання голосової пошти, задану адресуелектронної пошти.
    • Опції - це список опцій, що визначають часовий пояс, в якому знаходиться власник поштової скриньки, та перевизначають глобальні налаштуванняголосової пошти. Існує дев'ять допустимих опцій: attach, serveremail, tz, saycid, review, operator, callback, dialoutі exitcontext. Ці опції визначаються парами опция=значение, поділюваними символами вертикальної межі (|). Опція tzзадає часовий пояс користувача відповідно до часового поясу, визначеного раніше в розділі файлу voicemail.conf. Інші вісім опцій перевизначають відповідні їхнім іменам глобальні налаштування голосової пошти.

    Ось типовий опис поштової скриньки:

    101 => 1234, Joe Public, [email protected] ,[email protected],tz=central|attach=yes

    Продовжуючи створення нашого діалплану з останнього розділу, поставимо скриньки голосової пошти для Джона та Джейн. Для Джона визначимо пароль 1234, а для Джейн – 4444 (пам'ятайте, це робиться у файлі voicemail.conf, а не extensions.conf):


    101 => 1234, John Doe, [email protected] ,[email protected]
    102 => 4444, Jane Doe, [email protected] ,[email protected]

    Додавання голосової пошти в діалплан - Тепер, коли створено поштові скриньки для Джейн та Джона, давайте забезпечимо можливість абонентам залишати повідомлення для них у разі, якщо вони не відповідають на дзвінок. Для цього скористаємось програмою VoiceMail(). Програма VoiceMail() направляє абонента, що викликає, на задану поштову скриньку, щоб він міг залишити повідомлення. Поштова скринька має бути описана так: поштова скринька@контекст, де контекст – ім'я контексту голосової пошти. Сюди можуть бути додані літери b або u для запиту типу привітання. Якщо використовується буква b, абонент почує повідомлення про зайнятість власника поштової скриньки. Якщо використовується буква u, абонент почує повідомлення про недоступність власника поштової скриньки (якщо таке існує). Застосуємо це у нашому діалплані. Раніше в контексті розташовувався наступний рядок, який забезпечує можливість дзвонити Джону:

    Exten => 101,1,Dial($(JOHN))

    Тепер давайте додамо повідомлення про недоступність, яке почує абонент, якщо Джон не відповість на дзвінок протягом 10 секунд.
    Пам'ятайте, другий аргумент у Dial() – час очікування. Якщо до закінчення часу очікування відповіді на дзвінок не було, дзвінок перенаправляється в наступний пріоритет. Задамо час очікування 10 секунд і додамо пріоритет для переведення абонента на голосову пошту, якщо Джон не відповідає на дзвінок вчасно:

    Exten => 101,1,Dial($(JOHN),10)
    exten => 101,n,VoiceMail( 101@default,u)

    Тепер скоригуємо це так, щоб якщо Джон зайнятий (в іншому дзвінку), абонент перенаправлявся на голосову пошту, де чув би повідомлення про зайнятість. Для цього скористаємося змінною $(DIALSTATUS), в якій міститься одне зі значень статусу (список всіх можливих значень можна отримати в консолі Asterisk за допомогою команди "core show application dial"):

    Exten => 101,1,Dial($(JOHN),10)
    exten => 101,n,GotoIf($["$(DIALSTATUS)" = "BUSY"]?busy:unavail)
    exten => 101,n(unavail),Voicemail( 101@default,u)
    exten => 101,n,Hangup()
    exten => 101,n(busy),VoiceMail( 101@default,b)
    exten => 101,n,Hangup()

    Тепер абоненти отримуватимуть повідомлення голосової пошти Джона (з відповідним вітанням), якщо Джон зайнятий чи недоступний. Однак залишилася невелика проблема – Джон не має змоги отримувати свої повідомлення. Виправимо це.

    Організація доступу до голосової пошти - Користувачі можуть отримувати повідомлення голосової пошти, змінювати опції та записувати привітання голосової пошти за допомогою програми VoiceMailMain(). У своїй типовій формі програма VoiceMailMain() викликається без аргументів. Додамо до контексту діалплану додатковий номер 700, щоб внутрішні користувачі могли здійснювати дзвінки для доступу до своїх повідомлень голосової пошти:

    Exten => 700,1,VoiceMailMain()

    Створення телефонного довідника для набору номера на ім'я - Залишилася остання функція системи голосової, що заслуговує на увагу. пошти Asterisk– телефонний довідник для набору номера на ім'я. Він створюється за допомогою програми Directory(). Ця програма, використовуючи імена, задані в описах поштових скриньок у voicemail.conf, надає абоненту телефонний довідник абонентів АТС для набору номерів на ім'я.

    Directory() приймає три аргументи: контекст голосової пошти, з якого зчитуються імена, контекст діалплану, в якому викликається
    користувач (необов'язковий) та рядок опцій (також необов'язковий). За промовчанням Directory() веде пошук користувача на прізвище.
    Якщо передається опція f, пошук здійснюється на ім'я. Додамо два довідники для набору номера на ім'я в контекст нашого
    зразка діалплану, щоб абоненти могли виконувати пошук або на ім'я або на прізвище:

    Exten => 8,1,Directory(default,incoming,f)
    exten => 9,1,Directory(default,incoming)

    Якщо абоненти натиснуть кнопку 8, отримають довідник, складений за іменами. Якщо вони наберуть 9, то отримають довідник, складений на прізвища.

    2.2.16 Zapateller()

    Zapateller() – це проста програма Asterisk, яка відтворює спеціальний інформаційний тон на початку дзвінка. Пристрої автоматичного набору (які зазвичай використовуються в системах продажу телефоном) приймають цей тон за сигнал роз'єднання лінії. Причому вони
    не тільки припинять виклик, але також помітять цей номер як не обслуговується, що допоможе уникнути всіх видів телемаркетингових дзвінків. Щоб використовувати цю функціональність у своєму діалплані, вам потрібно просто викликати програму Zapateller().

    Також застосуємо необов'язкову опцію nocallerid, щоб тон відтворювався лише у випадку, якщо вхідний дзвінок не надає інформації про Caller ID (ID). Ось приклад використання програми Zapateller() у додатковому номері контексту:


    exten => s,1,Zapateller(nocallerid)
    exten => s,n,Playback(enter-ext-of-person)

    2.2.17 Паркування виклику

    Ще одна зручна функція – паркування виклику. Вона забезпечує можливість перевести виклик у стан очікування, поставити його на паркування, щоб він міг бути прийнятий на іншому додатковому номері. Усі параметри паркування дзвінків (такі, як додаткові номери, кількість місць і т. д.) задаються в конфігураційному файлі features.conf . Розділ файлу features.conf містить чотири налаштування щодо паркування дзвінків:

    • Parkext – це додатковий номер для паркування. Передайте виклик на цей додатковий номер – і система повідомить, в якому паркувальному слоті він поміщений. Додатковий номер за замовчуванням – 700.
    • Parkpos - Ця опція визначає кількість паркувальних слотів. Наприклад, задавши номери 701-720, ви створите 20 паркувальних слотів з нумерацією від 701 до 720.
    • context – це ім'я контексту паркування. Щоб мати змогу паркувати дзвінки, необхідно увімкнути цей контекст.
    • parkingtime - Якщо ця опція задана, вона визначає, як довго (у секундах) виклик може залишатися на парковці. Якщо дзвінок не прийнято протягом заданого часу, виконується дзвінок на додатковий номер, з якого дзвінок надійшов на паркування.

    Після редагування файлу features.conf необхідно перезавантажити Asterisk, тому що читання файлу виконується тільки при запуску системи. Виконання команди reload не забезпечить читання файлу features.conf.

    Також зверніть увагу, що оскільки користувачеві необхідно мати можливість передавати виклики на додатковий номер паркування, у додатку Dial() повинні використовуватися опції t та/або T .

    Отже, давайте створимо простий діалплан для демонстрації паркування викликів:


    include => parkedcalls
    exten => 103,1,Dial(SIP/Bob,tT)
    exten => 104,1,Dial(SIP/Charlie,tT)

    Проілюструємо принцип роботи паркування дзвінків. Скажімо, Еліс дзвонить у систему та набирає додатковий номер 103, щоб поговорити з Бобом. Через деякий час Боб переводить виклик на додатковий номер 700, який повідомляє йому, що дзвінок від Еліс був припаркований у слот 701. Після цього Боб дзвонить Чарлі на додатковий номер 104 і каже йому, що Еліс чекає на номер 701. Чарлі набирає додатковий номер 701 і розмовляє з Еліс. Це простий і ефективний спосіб забезпечити можливість перемикання абонентів, що викликають, між користувачами системи.
    Аргументи t і T програми Dial()потрібні задля всіх типів каналів. Наприклад, багато SIP-телефонів реалізують це за допомогою функціональної або звичайної кнопки та обміну сигналами за протоколом SIP.

    2.2.18 Організація конференц-зв'язку за допомогою MeetMe()

    Не менш корисною функцією є встановлення аудіо-конференц-зв'язку за допомогою програми MeetMe(). Ця програма забезпечує можливість одночасного спілкування безлічі абонентів так, ніби вони всі фізично знаходилися в одному місці. До основних функцій відносяться:

    • Можливість створення захищених паролем конференцій.
    • Адміністрація конференції (вимкнення звуку конференції, блокування конференції, виключення учасників).
    • Опція відключення звуку всіх учасників, крім одного (корисна для оголошень по компанії, широкомовних розсилок тощо).
    • Створення статичних чи динамічних конференцій.

    Давайте поетапно розглянемо процес налаштування базового конференц-залу. Конфігураційні опції системи конференц-зв'язку MeetMe розміщуються у файлі meetme.conf. У цьому конфігураційному файлі задаються конференц-зали та необов'язкові числові паролі. (Якщо
    пароль заданий, він буде необхідний для входу на всі конференції, що проводяться з використанням цього конференц-залу.) Для нашого прикладу налаштуємо конференц-зал за додатковим номером 600. Спочатку задамо всі налаштування у файлі meetme.conf. Назвемо цю конференц-залу
    600 і цього разу не задаватимемо пароль:


    conf => 600

    Закінчивши роботу з файлом конфігурації, необхідно перезавантажити Asterisk, щоб вона могла повторно прочитати файл meetme.conf. Далі додамо підтримку конференц-залу в діалплан, використовуючи програму MeetMe(). MeetMe() приймає три аргументи: ім'я конференц-залу (задане в meetme.conf), набір опцій та пароль, який користувач повинен ввести, щоб приєднатися до конференції. Налаштуємо просту конференцію, використовуючи конференц-зал 600, опцію i (яка забезпечує оповіщення про те, що хтось приєднався або залишив конференцію) та пароль 54321:

    Exten => 600,1, MeetMe (600, i, 54321)

    Коли абоненти потраплять на додатковий номер 600, їм запропонують ввести пароль. Якщо вони правильно введуть 54 321, то потраплять на конференцію.
    інше корисна програма– MeetMeCount(). Як випливає з його імені, ця програма підраховує, скільки користувачів знаходиться
    у тому чи іншому конференц-залі. Воно приймає два аргументи: конференц-зал, де необхідно підрахувати кількість учасників, та необов'язкове ім'я змінної, в якій потрібно зберегти це число. Якщо другий аргумент, тобто ім'я змінної, не заданий, отримане число відтворюється абоненту, що викликає:

    Exten => 601,1,Playback(conf-thereare)
    exten => 601,n,MeetMeCount(600)
    exten => 601,n,Playback(conf-peopleinconf)
    Якщо другим аргументом MeetMeCount() передається змінна, підсумкова кількість учасників присвоюється цій змінній, а саме число
    не відтворюється. Так можна обмежувати кількість учасників:
    ; обмежити конференц-зал 10 учасників
    exten => 600,1,MeetMeCount(600,CONFCOUNT)
    exten => 600,n,GotoIf($[$(CONFCOUNT) 600,n(meetme),MeetMe(600,i,54321))
    exten => conf_full,1,Playback(conf-full)

    2.2.19 3-х (і більше) сторонній виклик Asterisk з використанням ConfBridge()

    Це налаштування дозволяє здійснювати n-сторонній виклик в Asterisk за допомогою програми ConfBridge.
    Рішення є адаптацією рішення для роботи з ConfBridge (новіший, ніж MeetMe, додаток Asterisk для конференц-зв'язку, до того ж, не залежить від модуля DAHDI).
    Для роботи даної схеми Asterisk повинні бути зібрані модулі app_confbridge.so іchan_bridge.so .

    Опис функціоналу

    До сервісних кодів Asterisk додається код *0 (його потрібно описати у файлі features.conf і додати змінну DYNAMIC_FEATURES). Сервісний код *0 викликає виконання макросу nway-start, який створює конференцію з ім'ям як UNIQUEID у поточного виклику та перенаправляє у створену конференцію абонента, який не є ініціатором конференції. Після цього абонент, який розпочав конференцію, отримує можливість додати до конференції 3-го учасника.

    Абоненту, який додає до конференції нового учасника, доступні такі сервісні коди:

    • ** - припинити виклик, не додавати абонента до конференції
    • # - додати абонента до конференції

    Після виконання будь-якого з цих сервісних кодів абонент, який додав нового учасника, сам повертається в конференцію. Всім абонентам, які перебувають у конференції, доступний сервісний код *0. Після виконання цього коду абонент залишає конференцію, отримує можливість додати учасника до конференції, після чого повертається назад у конференцію. Кількість одночасних n-сторонніх дзвінків та їх учасників обмежена лише продуктивністю сервера.

    1) Налаштування ConfBridge: confbridge.conf


    type = user
    type = user
    type = menu
    *0 = leave_conference

    2) Діалплан: extensions.conf


    exten => s,1,ChannelRedirect($(BRIDGEPEER),nway-conf,$(CONFNO),1)
    ;

    exten => s,1,Read(NEW_CALLEE,dial,20,i)

    same =>

    same =>
    same =>
    same =>
    same =>
    same => n,Dial( Local/$(NEW_CALLEE)@from-internal, gH)
    same =>
    same => n,ChannelRedirect($(CHANNEL(name)),nway-conf,$(CONFNO),1)
    ;

    exten => _X.,1,Answer
    same => n,Set(__CONFNO=$(EXTEN))
    same => n,Set(DYNAMIC_FEATURES=$(DYNAMIC_FEATURES_NWAY))
    same => n,Set(CONFBRIDGE(bridge,language)=$(CHANNEL(language)))
    same => n,Set(CONFBRIDGE(user,announce_user_count)=no)
    same => n,Set(CONFBRIDGE(user,announce_join_leave)=no)
    same => n,Set(CONFBRIDGE(user,announce_only_user)=no)
    same => n,Set(CONFBRIDGE(user,music_on_hold_when_empty)=yes)
    same => n,ConfBridge($(CONFNO),nway_menu)
    same => n, Goto (nway-invite, s, 1)
    ;

    exten => s,1,Set(__CONFNO=$(UNIQUEID))
    same => n,ChannelRedirect($(BRIDGEPEER),nway-conf,$(CONFNO),1)
    same => n,Read(NEW_CALLEE,dial,20,i)
    ; Add dynamic features for n-way invite
    same => n,Set(DYNAMIC_FEATURES=$(DYNAMIC_FEATURES_NWAYINV))
    ; Determine dialing context and dial
    same => n,ExecIf($[$(REGEX("H" $(DIAL_OPTIONS))) = 0]?Set(_DIAL_OPTIONS=$(DIAL_OPTIONS)H))
    same => n,Set(CALLER=$(CALLERID(num)))
    same => n,Set(DIALOUT_CONTEXT=$(SIPPEER($(CALLER),context)))
    same => n,ExecIf($["$(DIALOUT_CONTEXT)" = ""]?Set(DIALOUT_CONTEXT=from-internal))
    same => n,Dial( Local/$(NEW_CALLEE)@$(DIALOUT_CONTEXT), gH)
    same => n,Set(DYNAMIC_FEATURES=$(DYNAMIC_FEATURES_NWAY)) n,ChannelRedirect($(CHANNEL(name)),nway-conf,$(CONFNO),1)

    3) Сервісні коди Asterisk: features.conf


    disconnect=**
    nway-start => *0,self,Macro,nway-start
    nway-ok => #,self/caller,Macro,nway-ok>

    Додати до файлу extensions.conf


    DYNAMIC_FEATURES = feature1#feature2#nway-start
    DYNAMIC_FEATURES_NWAY = feature1
    DYNAMIC_FEATURES_NWAYINV = feature2#nway-ok

    Опис змінних:

    • disconnect - стандартний сервісний код Asterisk, що викликає завершення поточного виклику.
    • DYNAMIC_FEATURES_NWAY – сервісні коди, доступні під час n-стороннього виклику
    • DYNAMIC_FEATURES_NWAYINV - сервісні коди, доступні під час запрошення до n-стороннього виклику

    2.2.20 Запис телефонних розмов у форматі (.wav)

    Запис розмов – досить зручний функціонал. Можна завжди прослухати, хто кому говорив. Налаштування не складне, достатньо включити в dialplan на обробку цього напрямку функції Monitor або MixMonitor. Відмінність цих функцій полягає в тому, що Monitor пише окремо голос того, хто дзвонив і голос дзвонить, в різні файли. А MixMonitor створює один файл, який містить обидва напрямки розмови.
    У діалплані це виглядає для Monitor так:


    exten => _8X.,1,Set(fname=$(STRFTIME($(EPOCH),%Y%m%d%H%M))-$(CALLERID(number))-$(EXTEN))
    exten => _8X.,2,Monitor(wav,/home/share/monitor/$(fname),mb)
    exten => _8X.,3,Dial(SIP/trunk1/$(EXTEN),tTr)

    У цьому прикладі першим рядком, Set(fname і т.д. ми описуємо ім'я файлу в якому буде зберігатися запис розмови. У нашому випадку ім'я файлу складатиметься з дати і часу коли відбувався дзвінок, номери абонента і куди він дзвонив. Запис як вже говорилося складатися з двох файлів в кінці будуть відповідно додані цифри 1 і 2 відповідно до номерів каналів.
    І другий приклад - використання MixMonitor, тут так само просто:


    exten => _8.,1,Set(fname=$(STRFTIME($(EPOCH),%Y%m%d%H%M))-$(CALLERID(number))-$(EXTEN))
    exten => _8.,2,MixMonitor(/home/share/monitor/$(fname).wav)
    exten => _8.,3,Dial(SIP/trunk2/$(EXTEN),tTr)

    Тут все те саме, тільки менше прапорів у команді MixMonitor, тут вписується лише ім'я файлу з розширенням.

    2.2.21 Запис розмов на Asterisk із простим керуванням через CLI

    Цей документ описує, як створити систему вибіркового запису розмов на базі Asterisk.

    Короткий опис рішення

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

    • використовувати вбудовані функції DB для пошуку значень;
    • використовувати консоль Asterisk та команду database для модифікації правил.

    В основі існують дві гілки:

    • rec_a - у цій галузі містяться номери абонента А (callerid), котрим необхідно включати запис;
    • rec_b - відповідно, у цій галузі правила номера абонента Б (dnid).

    *CLI> database put rec_a 701 1
    Updated database успішно
    *CLI> database put rec_b 2323956 1
    Updated database успішно
    *CLI> database show
    /rec_a/701: 1
    /rec_b/2323956: 1
    *CLI>

    У наведеному вище прикладі було створено два правила. Одне писатиме всі дзвінки від внутрішнього користувача з номером 701, інше писатиме всі дзвінки на номер 2323956. Як можна помітити, використовується прапор активності правила - 0 або 1. Це дозволяє тимчасово відключати запис без видалення номера з бази.

    Формат запису
    Записані файли пишуться в папку /var/spool/asterisk/monitor у такому форматі:

    data/yyyy/mm/dd/hh_MM_ss_a_b_callid, де:

    • yyyy – рік запису;
    • mm – місяць запису;
    • dd – день запису;
    • hh – година початку розмови;
    • MM – хвилина початку розмови;
    • ss - секунда початку розмови;
    • a - номер абонента a або unknown, якщо carrerrid прихований;
    • b – номер абонента b;
    • callid – ID дзвінка.

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

    Діалплан Asterisk

    Нижче наведено фрагмент діалплану Asterisk, що реалізує описану вище логіку.

    extensions.conf:



    exten =>
    exten => _X.,n,Dial(DAHDI/g1/$(EXTEN),t)

    exten => _X.,1,Gosub(sub-recording,$(EXTEN),1)
    exten => _X.,n,Dial(SIP/$(EXTEN),T)

    exten => s,1,StopMixMonitor()
    exten => _X.,1,Set(CALLER=unknown)
    exten => _X.,n,GoToIf($?db)
    exten => _X.,n,Set(CALLER=$(CALLERID(num)))
    exten => _X.,n(db),GotoIf($?record:stop)
    exten => _X.,n,GotoIf($?record:stop)
    exten => _X.,n(record),MixMonitor(data/$(STRFTIME(,%G/%m/%H_%M_%S))_$(CALLER)_$(CALLED).gsm)
    exten => _X.,n(stop),Return

    Недоліки: Час у назві файлу – час надходження виклику, але не початку розмови. Для вказівки часу початку розмови потрібно створення сімлінку або перейменування після закінчення розмови

    2.2.22 Будильник на Asterisk

    Реалізувати будильник в linux можна далеко не одним способом (напевно, найпростіший: "sleep 20m & mpg123~/bell.mp3"), але хочеться чогось красивого та нестандартного. Пошук в інтернеті за запитом «asterisk wakeup» видасть кілька рішень, написаних з використанням різних мов програмування, які трохи відрізняються як процесом установки, так і можливостями. Найпопулярнішим з них є PHP скрипт wakeup.php, автором якого є Анді Висоцький. Завантажуємо tar архів, розпаковуємо php-файл в каталог з AGI скриптами (Asterisk Gateway Interface- шлюзовий інтерфейс, за допомогою якого зовнішні програмиможуть керувати діалпланом Asterisk) і робимо його виконуваним: "chmod a+x /var/lib/asterisk/agi-bin/wakeup.php" ( потрібний каталогможна дізнатися, переглянувши значення змінної astagidir у конфізі asterisk.conf).
    Скрипт wakeup.php містить низку змінних, які необхідно підправити з урахуванням налаштувань системи:

    ; Розташування інтерпретатора PHPу різних linux-системах може відрізнятися
    #!/usr/bin/php -q
    ; Журнал із /tmp краще прибрати
    $parm_error_log = "/var/log/asterisk/wakeup.log";
    ; За замовчуванням скрипт створює тимчасові файли /tmp,
    ; але якщо цей каталог знаходиться на окремому розділі, wakeup.php відмовиться працювати, тому:
    $parm_temp_dir = "/var/spool/asterisk/tmp";

    Принцип запуску скрипта аналогічний прикладу Motion - просто заносимо в extensions.conf інформацію про новий номер:

    Exten => *97,1,Answer()
    exten => *97,n,AGI(wakeup.php)
    exten => *97,n,Hangup()

    Тепер достатньо зателефонувати на номер *97 і за запитом ввести час, коли система повинна здійснити зворотній дзвінок. Наприклад, щоб завести будильник на 17:55 (сьогодні фінал кубка англійської ліги), набираємо "0555", а потім "2" (1 – до полудня, 2 – після полудня).
    Якщо при запуску скрипту виникли проблеми, доустановіть пакети php5-cli та asterisk-sound-extra і використовуйте утиліту fromdos, щоб привести wakeup.php до Unix стандартів.

    2.2.23 Текстові повідомлення SIP/SIMPLE в Asterisk

    Для надсилання повідомлень використовується метод SIP MESSAGE (RFC 3428), відомий також як протокол SIMPLE. В Asterisk його підтримка з'явилася у 10 версії. Конфігурація функціоналу (використовується Asterisk версії 11).
    Варіант №1
    У розділ файлу sip.confдодаються рядки:


    outofcall_message_context = messages
    auth_message_requests = no

    А в dialplan extensions.confдодається контекст:


    exten => _XXX,1,MessageSend(sip:$(EXTEN),"$(CALLERID(name))"$(MESSAGE(from)))

    Кількість X проставте відповідно до кількості цифр у внутрішніх номерах.

    Варіант №2
    У розділ файлу sip.confдодаються рядки:

    Accept_outofcall_message = yes
    outofcall_message_context = astsms
    textsupport = yes
    auth_message_requests = yes

    А в dialplan extensions.confдодається контекст:


    exten => _.,1,NoOp(SMS отримувати dialplan invoked)
    exten => _.,n,NoOp(To $(MESSAGE(to)))
    exten => _.,n,NoOp(From $(MESSAGE(from)))
    exten => _.,n,NoOp(Body $(MESSAGE(body)))
    exten => _.,n,Set(ACTUALTO=$(CUT(MESSAGE(to),@,1))))
    exten => _.,n,MessageSend($(ACTUALTO),$(MESSAGE(from)))
    exten => _.,n,NoOp(Send status is $(MESSAGE_SEND_STATUS))
    exten => _.,n,GotoIf($["$(MESSAGE_SEND_STATUS)" != "SUCCESS"]?sendfailedmsg)
    exten => _.,n,Hangup()
    exten => h,1,Hangup()
    ;
    exten => _.,n(sendfailedmsg),Set(MESSAGE(body)="[$(STRFTIME($(EPOCH), %d%m%Y-%H:%M:%S))]] Your message to $(EXTEN) has failed. Retry later.")
    exten => _.,n,Set(ME_1=$(CUT(MESSAGE(from), exten => _.,n,Set(ACTUALFROM=$(CUT(ME_1,@,1))))
    exten => _.,n,MessageSend($(ACTUALFROM),ServiceCenter)
    exten => _.,n,Hangup()
    exten => h,1,Hangup()

    2.2.24 Функціонал для служби безпеки та керівництва компанії - Прослуховування розмов у режимі онлайн

    Варіант №1


    exten => 5555,1,Macro(user-callerid)
    exten => 5555,2,Authenticate(1234)
    exten => 5555,3,Read(SPYNUM,agent-newlocation)
    exten => 5555,4,ChanSpy(SIP/$(SPYNUM))

    Варіант №2


    exten => _555XX.,1,chanspy(sip/$(EXTEN:3))
    exten => 556,1,ChanSpy(канал,B) - чують обидва канали, типу тристоронньої конференції
    exten => 557,1,ChanSpy(канал,q) - канали не чують, ти все чуєш
    exten => 558,1,ChanSpy(канал,w) - тебе чує тільки канал, до якого підключаєшся, ти чуєш обидва канали

    Команда core show application ChanSpy показує всі опції функціоналу

    Ось як це працює на кілька телефонів

    Exten => *9720,1,ChanSpy(SIP/720,wqv(-1))
    exten => *9701,1,ChanSpy(SIP/701,wqv(-1))
    exten => *9700,1,ChanSpy(SIP/700,wqv(-1))

    Варіант №3

    ;listen - Прослуховування розмов (Вас не чують)
    exten => _*222x.#,1,Macro(user-callerid,)
    exten => _*222x.#,n,Answer
    exten => _*222x.#,n,NoCDR
    exten => _*222x.#,n,Wait(1)
    exten => _*222x.#,n,ChanSpy(sip/$(EXTEN:4),q)
    exten => _*222x.#,n,Hangup ;whisper - Вторгнення у розмову
    exten => _*223x.#,1,Macro(user-callerid,)
    exten => _*223x.#,n,Answer
    exten => _*223x.#,n,NoCDR
    exten => _*223x.#,n,Wait(1)
    exten => _*223x.#,n,ChanSpy(sip/$(EXTEN:4),qw)
    exten => _*223x.#,n,Hangup ;barge - Чують усі 3 учасники
    exten => _*224x.#,1,Macro(user-callerid,)
    exten => _*224x.#,n,Answer
    exten => _*224x.#,n,NoCDR
    exten => _*224x.#,n,Wait(1)
    exten => _*224x.#,n,ChanSpy(SIP/$(EXTEN:4),qB)
    exten => _*224x.#,n,Hangup