1. Подключение SIP телефона
- Настроить IP телефон для работы с Asterisk.
- Ознакомиться с базовым синтаксисом и поведением диалплана.
- Использовать несколько стандартных команд CLI.
- Понять важность директивы “context” в pjsip.conf
Телефонная станция без телефонов не особо полезна. Поэтому первую лабораторную вы начнете с настройки IP-телефона для работы с Астериском, и набора нескольких простых экстеншенов. Для того, чтобы телефон смог звонить вы должны указать одинаковые настройки логина и пароля в Астериске и в телефоне.
Шаг 1: Настройка телефона Digium D60
Вы будете настраивать IP-телефон через веб-интерфейс и для того, чтобы это сделать, нужно узнать IP-адрес своего телефона. Прочитайте инструкцию к IP-телефону или спросите у преподавателя как это сделать. Можно также воспользоваться методом «научного тыка».
Откройте браузер и введите IP-адрес телефона. Логин / пароль по умолчанию admin / 789. В соответствующие поля веб-интерфейса внесите следующие настройки:
- User ID/Extension: 7001
- Authorization Name: XX_sip_phone. Вместо “XX” используйте номер вашей станции (см. маркировку компьютера).
- Password: digium. В продакшине используйте только сильные пароли! (утилиты вроде apg вам в помощь).
- Register: Yes
- Primary Host: IP-адрес вашей рабочей станции.
Чтобы узнать IP-адрес вашего лабораторного сервера, наберите в консоли Linux:
$ ip address
Вы получите что-то вроде:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:30:53:f0 brd ff:ff:ff:ff:ff:ff
inet 192.168.101.107/24 brd 192.168.101.255 scope global eth0
inet6 fe80::20c:29ff:fe30:53f0/64 scope link
valid_lft forever preferred_lft forever
Вам нужен адрес, следующий за «inet» — это IP-адрес вашего компьютера.
После того, как все настройки сохранены, не забудьте применить их (Apply / Submit).
Шаг 2: Создание SIP аккаунта
Теперь IP-телефон настроен на общение с Астериском, но Астериск еще не настроен на работу с этим телефоном. В терминале наберите:
student@01:~$ sudo -i
Пароль:
root@01:~#
Теперь вы суперпользователь (root). Asterisk на ваших станциях уже запущен и ждетm, чтобы вы к нему подключились: asterisk -rvvv
Вы увидите в CLI сообщения о том, что телефон, который вы настроили, пытается зарегистрироваться. Но сообщения “No matching endpoint found»” означают, что эти попытки безуспешны.
В целях безопасности Asterisk по умолчанию отвергает сообщения от неизвестных устройств.
В CLI Астериск наберите:
*CLI> pjsip show endpoints
No objects found.
Видите, на текущий момент не определено ни одного устройства в качестве endpoint’а.
Далее, вы настроите учетную запись для Digium телефона в файле /etc/asterisk/pjsip.conf. Вы можете использовать любой знакомый вам текстовый редактор, для вас установлены: mc, vim, nano, а также графический редактор gedit. Рекомендуем vim, на сервере есть шпаргалка по его использованию: http://trainingserver/pub/extras/Vim_guide.pdf.
Редактировать файлы конфигурации рекомендуется в отдельном терминале (или в отдельном окне текстового редактора) для ускорения рабочего процесса. Вам придется много раз переключаться между редактированием конфигурационных файлов и CLI Asterisk. И каждый раз тратить время на подключение/отключение к консоли Asterisk и открытие/закрытие конфигурационных файлов совсем не эффективно.
Файл pjsip.conf не совсем пустой, но там пока совсем немного. Для ясности из него было удалено все лишнее. После лабораторной вы можете взглянуть на дефолтный pjsip.conf.sample, который поставляется вместе с исходниками Asterisk в субдиректории configs/samples — там много опций и комментариев к ним. Все исходники на вашей рабочей станции расположены в каталоге /usr/src/.
Также, для вашего удобства создана символическая ссылка: /etc/asterisk/samples -> /usr/src/asterisk-x.x.x/configs/samples/
Пока можете проигнорировать секции [global]
и [dpma_endpoint]
, но не удаляйте их. Заметьте, что секция с типом transport уже добавлена:
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0
Данный транспорт привязывается ко всем IP-адресам станции (0.0.0.0 означает все адреса), порт по умолчанию 5060, и использует протокол UDP для SIP сигнализации.
Далее вы создадите другие секции, необходимые для SIP устройства, и свяжите их вместе в секции с типом endpoint. Каждая секция типа endpoint должна ссылаться на секцию типа transport, aor и auth (если нужна аутентификация).
ЗАМЕТКА: секции различных типов могут иметь одинаковые имена. В рамках данного курса мы будем использовать именно такой подход.
Добавьте в pjsip.conf следующие строчки:
[7001]
type=aor
max_contacts=1
[7001]
type=auth
auth_type=userpass
password=digium
username=XX_sip_phone
[7001]
type=endpoint
transport=transport-udp
aors=7001
auth=7001
disallow=all
allow=ulaw,gsm
context=features
Тип секции aor означает “address of record” и определяет адрес местонахождения SIP устройства. max_contacts=1 означает, что не более чем одно устройство может зарегистрироваться под этой учетной записью в один момент времени. Asterisk будет сохранять в своей базе данных этот адрес, для отслеживания местонахождения устройства.
Секция типа auth используется для аутентификации запросов на регистрацию и при совершении клиентом звонков. auth_type=userpass означает аутентификацию по логину и паролю.
Секция типа endpoint описывает характеристики оконечного оборудования и собирает в себе всю необходимую информацию для взаимодействия Asterisk с SIP устройством. Строчки aors= и auth= ссылаются на секции соответствующего типа. Опции disallow и allow управляют разрешенными кодеками. Опция context= задает входящий контекст. Когда с телефона приходит входящий вызов, набранный номер должен будет совпасть с экстеншеном в контексте features.
Сохраните изменения и возвращайтесь в консоль Asterisk. Теперь нужно применить изменения командой pjsip reload
Если конфигурация с обеих сторон корректна, то при следующей попытке телефон успешно зарегистрируется. Возможно вы увидите сообщение WARNING в консоли про то, что у телефона не настроен mailbox. Но после того, как телефон зарегистрирован, все готовo для совершения звонка. Регистрацию SIP-телефона можно проверить, выполнив команду pjsip show endpoints
Вы должны увидеть один настроенный endpoint. Если телефон уже зарегистрирован, в выводе команды вы заметите адрес телефона, включая IP-адрес, в формате SIP URI, например:
Contact: 7001/sip:7001@192.168.102.1:5060
Если телефон не зарегистрировался, строка Contact будет отсутствовать. По-другому SIP регистрацию можно проверить командой database show
. Астериск добавляет в AstDB отдельную запись для каждого зарегистрированного устройства. Если ваш телефон зарегистрирован, вы увидите что-то вроде:
/registrar/contact/7001;@d330dd21222257e800361e66a5189717: {..."uri":"sip:7001@192.168.101.61:5060;ob"...}
Шаг 3: Обзор плана нумерации
На предыдущих этапах мы настроили IP-телефон и SIP конфигурацию Астериска , чтобы они могли «говорить» друг с другом. Осталось настроить диалплан.
Открывайте в отдельном окне или вкладке редактора файл extensions.conf вашим любимым текстовым редактором. Отдельно, потому что к pjsip.conf вам придется в дальнейшем часто обращаться, так же как и к “extensions.conf”.
Вы видите секции [general]
и [globals]
и несколько контекстов. В секции [default]
нет ничего, кроме одной строчки с командой Hangup(). Это в целях безопасности. При некоторых обстоятельствах Астериск обращается к контексту [default]
в поисках подходящего экстеншена. Отвергая автоматически все звонки в нем, мы перестраховываемся от неожиданной обработки вызова.
В контексте [features]
определен один экстеншен.
[features]
exten => 8001,1,Playback(demo-congrats)
same => n,Hangup()
Адрес диалплана определяется как extension@context, в нашем случае это 8001@features. По этому адресу Астериск первой выполняет команду Playback() с аргументом demo-congrats. Следующей выполняется команда Hangup(), завершающая вызов. Вам нужно усвоить синтаксис диалплана на данном этапе, так как в дальнейшем он будет только усложняться. Если нужны пояснения — обращайтесь к инструктору.
Ваш телефон сможет набирать любой номер, которому соответствует хотя бы один экстеншен в его входящем контексте. В дальнейшем вам нужно будет добавлять экстеншены и контексты и входящий контекст всегда можно изменить.
Шаг 4: Первый звонок
В CLI Астериска выполните
*CLI> dialplan show 8001@features
[ Context 'features' created by 'pbx_config' ]
'8001' => 1. Playback(demo-congrats) [pbx_config]
2. Hangup() [pbx_config]
-= 1 extension (2 priorities) in 1 context. =-
Заметьте, как будет обработан вызов, когда он придет на данный экстеншен. Поглядывайте в CLI, когда звоните на номер 8001 с телефона.
*CLI>
-- Executing [8001@features:1] Playback("PJSIP/7001-00000000", "demo-congrats")
in new stack
-- <PJSIP/7001-00000000> Playing 'demo-congrats.gsm' (language 'en')
*CLI>
Вы должны услышать женский голос, произносящий “Congratulations…”. Пока вы его слушаете, наберите
*CLI> core show channels
Channel Location State Application(Data)
PJSIP/7001-00000000 8001@features:1 Up Playback(demo-congrats)
1 active channel
1 active call
1 call processed
*CLI>
Если вы не слышите голосового приветствия или сообщения существенно отличаются от приведенных выше, внимательно их прочитайте и постарайтесь понять, что они означают. Проверьте конфигурацию IP телефона и pjsip.conf и убедитесь, что нужные значения совпадают. Не забывайте сохранять изменения в конфигурационных файлах и применять их в Астериске соответствующими командами.
Команды, которые могут вам помочь обнаружить проблему:
*CLI> pjsip show aor 7001
*CLI> pjsip show auth 7001
*CLI> pjsip show transport transport-udp
*CLI> pjsip show endpoint 7001
*CLI> dialplan show features
Шаг 5: Команды CLI Asterisk
На данный момент у вас должен быть рабочий IP телефон с которого можно звонить в контекст [features]. В следующей лабораторной мы добавим еще одно SIP устройство, что бы можно было звонить между ними. Для завершения лабораторной, выполните следующие команды в CLI.
При наборе команд в CLI всегда пользуйтесь кнопкой Tab для автоматического дополнения набираемых команд. Это, во-первых, гарантирует вам отсутствие опечаток в команде, а во-вторых, вы легко найдете нужную вам команду, даже если не помните ее целиком.
*CLI> help
*CLI> core show channels
*CLI> core show uptime
*CLI> core show version
*CLI> core show license
*CLI> core show applications
*CLI> pjsip show channels (во время активного звонка)
*CLI> config show help res_pjsip
*CLI> config show help res_pjsip aor
*CLI> config show help res_pjsip aor max_contacts
Дополнительное задание
В этой и следующих лабораторных работах вам будут предложены дополнительные задания. Их следует выполнять только после завершения основной задачи и если вы справились раньше времени. Дополнительные задания описаны кратко — они рассчитаны на умение самостоятельно находить информацию.
Настройте SIP клиента на вашем смартфоне и подключите его к Asterisk. Для Android рекомендуем использовать встроенный SIP клиент (при наличии) или CsipSimple. Для iPhone и других платформ — на ваш выбор (подойдет, например, Zoiper).
2. Диалплан, Voicemail и включения контекстов
- Настроить больше SIP устройств для работы с Asterisk.
- Настроить диалплан для звонков между телефонами.
- Добавить возможность оставлять и получать голосовую почту.
- Научиться использовать включения контекстов (include ⇒).
Это еще одна небольшая лабораторная работа, которая охватывает много важных вопросов. Прежде всего, вы настроите SIP софтфон Zoiper так, чтобы вы могли звонить с одного телефона на другой. Затем вы на практике проверите, что контексты разделяют группы экстеншенов и в качестве примера добавите возможность проверять голосовую почту с телефонов. В завершении, мы рассмотрим на практике включение контекстов.
Шаг 1: Настройка SIP аккаунта в Asterisk
Создайте в pjsip.conf новую учетную запись для софтфона Zoiper точно так же, как вы делали для IP телефона Digium, за исключением:
- Вместо номера 7001 используйте 7002.
- В качестве входящего контекста укажите «phones».
- username=7002.
- password=zoiper.
Сохраните конфигурационный файл и примените настройки в Asterisk.
Шаг 2: Настройка софтфона
- Запустите Zoiper из системного меню Приложения → Интернет.
- Зайдите в Settings → Create new account → SIP → NEXT.
- user: 7002@ip_адрес_вашей_станции. Например 7002@192.168.101.101.
- Password: zoiper.
- NEXT → NEXT.
В консоли должно появиться сообщение об успешном добавлении контакта для endpoint 7002. Если нет — используйте команды из предыдущей лабораторной для выявления ошибки в конфигурации.
С софтфоном Zoiper есть одна досадная особенность — он по умолчанию использует STUN-сервер. Мы об этой технологии еще поговорим подробнее в дальнейшем, в двух словах - она позволяет увидеть свой внешний IP адрес и подставить его в SIP запросы. Поэтому вместо внутреннего адреса 192.168.101.1XX Asterisk получил внешний IP в поле Contact. А поскольку у вас сервер в локальной сети, вам нужно это отключить:
- Settings → Preferences → выберите вашу учетную запись и вкладку Advanced.
- Вместо “Use default STUN” выберите “Don’t use STUN”.
- Сохраните, нажав “OK”.
Чтобы изменения вступили в силу, достаточно перейти в режим Offline (левый нижний угол программы Zoiper), затем обратно в Online.
Шаг 3: Настройка диалплана Астериска
В extensions.conf создайте два экстеншена в контексте [phones]
- 7001 для звонков на IP-телефон Digium.
- 7002 для звонков на Zoiper.
[phones]
exten => 7001,1,Dial(PJSIP/7001)
exten => 7002,1,Dial(PJSIP/7002)
Сохраните extensions.conf и перезагрузите диалплан командой dialplan reload
Шаг 4: Тестирование конфигурации
- Поглядываем в CLI при совершении следующих звонков.
- C софтфона звоним на 7001.
- Ваш IP телефон должен зазвонить, снимите трубку.
- Пока оба телефона на связи, наберите в CLI:
core show channels
core show channels verbose
core show channels concise
- Заметьте, что 2 канала активны и существует связанный звонок между двумя телефонами.
Теперь позвоним с IP телефона на софтфон. Вызов не прошел, а в консоли что-то вроде:
*CLI> [Nov 4 20:07:24] NOTICE[10783]: res_pjsip_session.c:2095 new_invite:
Call from '7001' (UDP:192.168.101.56:38981) to extension '7002' rejected
because extension not found in context 'features'
Так? Такая ошибка встречается весьма часто у начинающих администраторов Asterisk. Смысл сообщения в том, что в контексте features отсутствует экстеншен 7002. И это действительно так.
Только не спешите копировать или переносить экстеншен 7002 в контекст features. Он у нас должен оставаться в контексте “phones”. Правильным будет в данном случае изменить входящий контекст для IP-телефона. И вы уже знаете как это делать. Если забыли — найдите, где в pjsip.conf указан контекст features и измените его.
Шаг 5: Добавление голосовой почты
- Откройте voicemail.conf и просмотрите его содержимое.
- Найдите секцию [default].
- Добавьте 2 голосовых ящика 7001 и 7002 по аналогии с закомментированными строчками.
- Перезагрузите настройки голосовой почты и проверьте их.
pc1*CLI> voicemail reload
Reloading voicemail configuration...
pc1*CLI> voicemail show users
Context Mbox User Zone NewMsg
default 7001 Digium Phone 0
default 7002 Zoiper Phone 0
2 voicemail users configured.
В extensions.conf добавьте команды для отправки в голосовую почты после Dial()
:
- Установите в командах
Dial()
тайм-аут 20 секунд на ожидание ответа (второй аргумент). - Добавьте к каждому экстеншену (7001 и 7002) приоритеты для вызова приложений VoiceMail() и Hangup().
- В качестве первого аргумента передайте командам VoiceMail номер голосовой почты пользователя.
- Активируйте уведомление о получении голосовой почты.
- Добавьте
mailboxes=7001@default
вendpoint
секцию для учетной записи 7001. - Выполните команду
pjsip reload
.
- Добавьте
- Оставьте голосовую почту.
- Позвоните с софтфона на IP телефон, подождите 20 секунд.
- Поглядывайте в CLI во время звонка.
- Оставьте голосовое сообщение.
После этого лампочка уведомлений о голосовой почте должна замигать на телефоне 7001. Теперь в extensions.conf добавьте пользователям возможность проверять голосовую почту:
- Добавьте экстеншен 8002@features для проверки голосовой почты командой
VoiceMailMain()
- Чтобы дать возможность пользователям звонить на экстеншены в контексте features, его нужно включить в контекст phones:
[phones]
include => features
- Перезагрузите диалплан.
- Проверьте голосовую почту.
- Наберите 8002. После приветствия наберите номер голосовой почты и пароль.
- Вы должны услышать сообщение, которое вы оставили и увидеть вывод в консоли CLI.
Пример вашей конфигурации
[general]
[globals]
[default]
exten => _.,1,Hangup()
[phones]
include => features
exten => 7001,1,Dial(PJSIP/7001,20)
same => n,VoiceMail(7001)
same => n,Hangup()
exten => 7002,1,Dial(PJSIP/7002)
same => n,VoiceMail(7002)
same => n,Hangup()
[features]
include => account_balance
exten => 8001,1,Playback(demo-congrats)
same => n,Hangup()
exten => 8002,1,VoiceMailMain()
same => n,Hangup()
...
[7002]
type=aor
max_contacts=1
;qualify_frequency=60
[7002]
type=auth
auth_type=userpass
password=zoiper
username=7002
[7002]
type=endpoint
transport=transport-udp
aors=7002
auth=7002
disallow=all
allow=alaw,g722
context=phones
device_state_busy_at=1
Дополнительное задание
- Русифицируйте голосовую почту.
- Сделайте так, чтобы каждый телефон при звонке на 8002 попадал в свой голосовой ящик без логина и пароля.
3. SIP Trunking
- Настроить PJSIP транк на лабораторный сервер.
- Проверить исходящие и входящие вызовы.
- Включить в диалплан глобальные переменные.
- Разобрать демонстрационный IVR.
- Научиться пользоваться встроенной документацией.
Шаг 1. Настроить подключение к SIP провайдеру (ITSP)
Создайте новую секцию с типом register и названием [sip-trunk-reg] в pjsip.conf. Для справки используйте команду config show help res_pjsip_outbound_registration
.
- type=registration.
- транспорт — тот же что и для телефонов.
- аутентификация ссылается на секцию sip-trunk-auth.
- она пока не существует, но скоро вы ее создадите.
- IP-адрес ITSP сервера 192.168.101.1
- client_uri равен trainingXX@192.168.101.1XX
- Как обычно, замените XX на номер вашей станции.
- Далее, создайте новую auth секцию в pjsip.conf со следующей конфигурацией. Используйте справочную команду
config show help res_pjsip
для настройки этой и следующих секций. - Username: trainingXX.
- Password: trainingXX.
Сохраните и перезагрузите SIP. В CLI проверьте статус регистрации:
*CLI> pjsip reload
*CLI> pjsip show registrations
...
sip-trunk-reg/sip:192.168.101.1 sip-trunk-auth Registered
Создайте новую aor секцию с названием [sip-trunk]:
- В качестве контакта определите sip:192.168.101.1:5060.
Создайте новую identify секцию с названием [sip-trunk] (config show help res_pjsip_endpoint_identifier_ip
).
- Все звонки с IP-адреса 192.168.101.1 должны соответствовать с endpoint-у “sip-trunk”.
- Ну и, наконец-то, можете создать endpoint секцию, которая “соберет” в себе все вышеперечисленные.
- Транспорт тот же.
- Обратите внимание, endpoint потенциально может использовать совсем другие секции auth и transport.
- Не забудьте указать aors и приемлемые кодеки.
- Не утруждайте провайдера аутентификацией на входящих звонках.
- Не разрешайте меда-потоку идти напрямую между вашими телефонами и провайдером.
- Все входящие звонки от провайдера должны попадать в контекст [inbound].
Как закончите с конфигурацией, перегружайте настройки SIP в Asterisk. Обращайте внимания на сообщения WARNING, NOTICE и ERROR и внимательно их читайте. Если конфигурация выполнена корректно, результат команды CLI pjsip show endpoints
покажет вам информацию по новому endpoint’у:
*CLI> pjsip show endpoints
...
Endpoint: sip-trunk Unavailable 0 of inf
OutAuth: sip-trunk-auth/training01
Aor: sip-trunk 0
Contact: sip-trunk/sip:192.168.101.1:5060 1f8623ff51 Created 0.000
Transport: transport-udp udp 0 0 0.0.0.0:5060 Identify: sip-trunk/sip-trunk
Match: 192.168.101.1/32
Шаг 2. Обновите диалплан для тестирования входящих и исходящих звонков
Теперь у Asterisk есть SIP провайдер, но чтобы конечные устройства могли его использовать, нужно немного пошаманить над extensions.conf. Вы создадите новый контекст outbound и направите в него ваши телефоны.
pjsip.conf:
- Замените входящий контекст для аккаунтов 7001 и 7002 на outbound.
- Примените изменения.
- После этого телефоны никуда не смогут звонить, т. к. такого контекста пока не существует.
extensions.conf:
-
Создайте контекст [outbound]:
Заметка: название контекста очень условно — обычно звонки направляются в контексты с различиями в классе доступа (local, long-distance, international). [outbound] в данном случае это упрощенное название. Поглядите extensions.conf-accessclasses в качестве примера разделения классов доступа для исходящих звонков.
-
В нем создайте экстеншен — паттерн.
- Любые 8 цифр, начинающиеся с “61”, должны удовлетворять этому паттерну.
- Например, номер 61990000 или 61017001.
- Этот экстеншен будет совершать исходящий вызов на AoR sip-trunk’а по набранному номеру:
- Dial(PJSIP/${EXTEN}@sip-trunk).
- Любые 8 цифр, начинающиеся с “61”, должны удовлетворять этому паттерну.
-
Включите контекст [phones] в контекст [outbound], чтобы телефоны не потеряли возможность звонить друг другу.
-
Так же создайте контекст [inbound] для входящих звонков от провайдера.
-
В контекст [inbound] включите контекст [phones], чтобы с сервера звонки могли поступать на номера телефонов 7001, 7002 и т.д.
Перезагрузите диалплан командой в CLI: dialplan reload
.
Шаг 3. Протестируйте входящие и исходящие вызовы
Исходящие звонки:
- С любого телефона наберите номер из 8-ми цифр: 61990000.
- В CLI наблюдайте за логами Asterisk.
- Вы должны услышать от сервера озвучку цифр набранного номера. Протестируйте входящие звонки.
Метод 1 — через web-скрипт callme:
- Откройте в браузере ссылку
- Введите номер вашей станции и номер телефона 7001 или 7002, а затем совешите вызов.
Метод 2 — петля через провайдера:
- Наберите номер 61ХХ7001 с телефона 7002 — должен зазвонить телефон 7001.
- Наберите номер 61ХХ7002 с телефона 7001 — должен зазвонить телефон 7002.
Как это работает
- В нашем классе используется 8-значная нумерация.
- Первые 2 цифры — выбор транка (в данном случае 61 — это SIP транк на лабораторный сервер).
- Следующие 2 цифры — номер станции.
- Последние 4 цифры — номер экстеншена на ваших станциях.
- Ваш звонок посылается на сервер, который вырезает префикс 61, выбирает номер станции на базе следующих двух цифр и отправляет вызов на нее. В качестве номера назначения передаются последние 4 цифры. Вы можете ознакомиться с диалпланом сервера по ссылке: http://192.168.101.1/pub/server_configs/asterisk/extensions.conf-aa.
Шаг 4. Включите глобальную переменную
- В секции [globals] файла extensions.conf создайте глобальную переменную “PJSIPTrunk” и присвойте ей значение “sip-trunk”:
PJSIPTrunk=sip-trunk
.
- Модифицируйте аргументы команды Dial на экстеншене _61ХХХХХХ так, чтобы вместо названия транка использовалась созданная глобальная переменная.
- Перезагрузите диалплан и убедитесь, что все работает.
Шаг 5. Разбор демонстрационного IVR
Откройте extensions.conf-ivr и изучите его. Внесите следующие изменения:
- Раскомментируйте строчку “#include extensions.conf-ivr” в extensions.conf.
- Добавьте в контекст [inbound] экстеншен 7200 с командой “Goto(ivr,s,1)”, что означает переход в контекст ivr, экстеншен s, приоритет 1.
- Наберите 61XX7200 и наблюдайте за сообщениями в CLI. Вызов должен уйти на sip-trunk и сразу вернуться к вам, как новый входящий звонок на номер 7200. Для вашего Asterisk сервера эти два канала никак не связанны между собой. Тем не менее, вы услышите в трубке приветствие Эллисон “Main menu” и сможете в течении 10 секунд передать DTMF для выбора следующего действия в IVR.
Пример вашей конфигурации
...
[globals]
PJSIPTrunk=sip-trunk
...
[outbound]
include => phones
exten => _61XXXXXX,1,Dial(PJSIP/${EXTEN}@${PJSIPTrunk})
[inbound]
include => phones
exten => 7200,1,Goto(ivr,s,1)
…
#include extensions.conf-ivr
[sip-trunk-reg]
type=registration
transport=transport-udp
outbound_auth=sip-trunk-auth
server_uri=sip:192.168.101.1
client_uri=sip:training01@192.168.101.101
[sip-trunk-auth]
type=auth
username=training01
password=training01
[sip-trunk]
type=aor
contact=sip:192.168.101.1:5060
[sip-trunk]
type=identify
match=192.168.101.1
endpoint=sip-trunk
[sip-trunk]
type=endpoint
transport=transport-udp
aors=sip-trunk
disallow=all
allow=alaw
outbound_auth=sip-trunk-auth
direct_media=no
context=inbound
Дополнительное задание
У GSM оператора Мегафон есть услуга Мультифон — прием входящих звонков на ваш мобильный номер по SIP, а также возможность по SIP совершать исходящие звонки. Инструктор выдаст вам параметры учетной записи. Вам нужно будет настроить реальный транк на реального оператора.
4. IAX Peering
- Объединить все Asterisk серверы в классе в единую сеть.
- Применить шаблоны.
Сценарий: предположим, что ваш Asterisk сервер обслуживает отдельный филиал географически распределенной компании, у которой есть еще 7 других филиалов. Ваш Asterisk — полностью независимая АТС, но все филиалы должны иметь возможность звонить друг-другу напрямую, без единого центрального узла связи. При этом конфигурация должна оставаться настолько простой, насколько это возможно. Не забывайте про принцип KISS.
Настройте первый IAX транк
Выберите себе напарника в группе для настройке тестового IAX транка. Уточните номер его станции и IP-адрес, а так же сообщите ему свои данные. Предположим его номер станции — 01, IP- адрес — 192.168.101.101, у вас — 09 и 192.168.101.109 соответственно. Тогда добавьте в iax.conf:
[station01]
type=friend
host=192.168.101.101
context=inbound
username=station09
secret=SuperSecret
- [server-trunk] — имя секции, оно же название пира, оно же используется на сервере в качестве username. Соответственно менять его без изменения на стороне сервера нельзя.
- type — обязательный параметр. Может принимать одно из трех значений:
user
означает “только входящие” → Asterisk не может звонить на user’ов.peer
означает “только исходящие” → Asterisk не может принимать звонки от peer’ов.friend
— совмещает в себе user & peer. Это как-бы две секции с одинаковым названием, но одна user, а другая peer.
- host — еще один обязательный параметр. Либо статически задается IP адрес / имя хоста, либо ключевое слово dynamic. Последнее означает, что он должен зарегистрироваться прежде, чем мы сможет на него звонить.
- context — входящие звонки с этого пира должны попадать в контекст inbound.
- username, secret — параметры для аутентификации на сервере при совершении исходящих звонков.
Проверяем:
*CLI> iax2 reload
*CLI> iax2 show registry
*CLI> iax2 show users
*CLI> iax2 show peers
Внимательно читайте консольные сообщения в ответ на команды.
Настройте диалплан
В контекст [outbound] добавьте строчку: exten => _6301XXXX,1,Dial(IAX2/station01/${EXTEN:4})
Смысл таков:
- 63 — префикс для связи с другими АТС.
- Следующие 2 цифры адресуют номер станции (01, 02, 03, …).
- Все остальные цифры передаются на станцию напарника в качестве номера назначения.
Перезагружаем диалплан:
*CLI> dialplan reload
и проверяем. Наберите 63017001 — вы должны дозвониться на номер 7001 вашего напарника.
-- Executing [63017001@outbound:1] Dial("PJSIP/7002-...", "IAX2/station01/7001")
-- Called IAX2/station01/7001
-- Call accepted by 192.168.101.101:4569 (format ulaw)
-- Format for call is (ulaw)
-- IAX2/station01-13000 is ringing
...
-- IAX2/station01-13000 answered PJSIP/7002-00000001
...
-- Hungup 'IAX2/station01-13000'
А также входящие звонки от напарника:
-- Executing [7002@inbound:1] Dial("IAX2/station01-2120", "PJSIP/7002")
-- Called PJSIP/7002
-- PJSIP/7002-00000000 is ringing
...
-- PJSIP/7002-00000000 answered IAX2/station01-2120
Подключитесь к остальным станциям
После успешной стыковки с одной станции можно настроить остальные по аналогии с первой. И чтобы не дублировать одинаковые настройки много-много раз, вам следует применить шаблоны (templates). К примеру, если добавить в iax.conf строчки:
[station02](station01)
host=192.168.101.102
Вы создадите новую секцию [station02]
, которая унаследует все настройки из секции [station01]
, но переопределит значение опции host. Это полностью аналогично, как если бы вы написали:
[station02]
type=friend
context=inbound
username=station09
secret=SuperSecret
host=192.168.101.102
Любая секция может унаследовать настройки любой другой секции, достаточно указать ее в круглых скобках, сразу после закрывающей квадратной скобки в имени секции. Аналогично, можно создать остальные транки:
[station03](station01)
host=192.168.101.103
[station04](station01)
host=192.168.101.104
…
Единственный минус в данном случае — это невозможность применить какую-либо специфичную опцию к транку station01 так, чтобы не «задеть» остальные транки. Поэтому сделать лучше так:
[station-template](!)
type=friend
context=inbound
username=station09
secret=SuperSecret
[station01](station-template)
host=192.168.101.101
[station02](station-template)
host=192.168.101.102
...
[station08](station-template)
host=192.168.101.108
Знак ”!” вместо имени наследуемой секции означает, что данная секция является только шаблоном. Т.е. команда iax2 show peer station-template
скажет, что такого пира нет. Теперь еще замените строчку:
exten => _6301XXXX,1,Dial(IAX2/station01/${EXTEN:4})
на
exten => _63XXXXXX,1,Dial(IAX2/station${EXTEN:2:2}/${EXTEN:4})
И проверяйте входящие/исходящие на другие станции.
Дополнительное задание
Сделайте так, чтобы после получения входящего вызова с других АТС вы могли перезвонить абоненту обратно из истории звонков.
5. Asterisk Call Queues
- Познакомиться с основными настройками очередей.
- Применить команды диалплана
Queue()
,AddQueueMember()
,RemoveQueueMember
,PauseQueueMember()
иUnpauseQueueMember()
. - Поработать с очередями из CLI.
В этой лабораторной работе Digium телефон будет звонящим в очередь (клиентом). Прочие SIP устройства — членами очереди (операторами).
Настройте диалплан
Откройте /etc/asterisk/extensions.conf-queues и внимательно его изучите.
- Вызов на 8100 отправляет звонящего в очередь с названием q1.
- Номера 8201 и 8202 добавляют в очередь звонящего в качестве оператора и удаляют из очереди соответственно.
- Номера 8203 и 8204 ставят оператора на паузу в очереди q1 и снимают с паузы соответственно.
- Имя оператора берется из переменной ${CHANNEL}, которая содержит имя текущего канала.
От вас не требуется каких-либо изменений в данный файл, вы будете использовать эти номера далее в лабораторной. Теперь внесите в extensions.conf следующие изменения:
- Внизу файла раскомментируйте строчку:
#include extensions.conf-queues
. - В контекст [features] добавьте:
include => queues
. - Перезагрузите диалплан.
Настройте очередь
- Откройте /etc/asterisk/queues.conf (он совершенно пустой сейчас).
- Минимальные настройки чтобы добавить очередь — просто объявить секцию с именем очереди
[q1]
. - Перезагрузите настройки очередей из CLI:
*CLI> queue reload all
[Nov 29 17:30:25] NOTICE[2240]: app_queue.c:8700 reload_queue_rules: queuerules.conf has not changed since it was last loaded. Not taking any action.
== Parsing '/etc/asterisk/queues.conf': Found
Сообщения касательно queuerules.conf можно проигнорировать.
*CLI> queue show q1
q1 has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
No Members
No Callers
Протестируйте очередь
- Наберите 8100 с телефона Digium, наблюдая в консоли Астериск за сообщениями:
*CLI>
-- Executing [8100@outbound:1] Answer("PJSIP/7001-00000020", "")
-- Executing [8100@outbound:2] Queue("PJSIP/7001-00000020", "q1")
-- Started music on hold, class 'default', on channel 'PJSIP/7001-00000020'
Заметьте, что экстеншен 8100 определен в контексте [queues], а SIP endpoint попадает в контекст [outbound]. Но благодаря транзитивности директивы “include ⇒” экстеншен 8001 доступен в контексте outbound. Убедиться в том, что канал находится в очереди можно командой:
*CLI> queue show q1
q1 has 1 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:1, SL:0.0% within 0s
No Members
Callers:
1. PJSIP/7001-00000020 (wait: 0:06, prio: 0)
Ответить “клиенту” в очереди q1 пока некому, в ней нет ни одного оператора.
Опция joinempty
Т.к. отправлять клиента в очередь, в которой нет операторов не очень разумно (хотя бывают исключения), примените опцию joinempty, которая позволяет контролировать, зайдет ли клиент в пустую очередь. Добавьте в секцию [q1]
опцию:
joinempty=invalid
.- Она указывает Астериску чтобы он не добавлял клиента в очередь, если в очереди нет операторов. Члены очереди со статусом invalid не в счёт.
- Примените настройки и позвоните снова в очередь.
-- Executing [8100@outbound:1] Answer("PJSIP/7001-00000005", "") in new stack
-- Executing [8100@outbound:2] Queue("PJSIP/7001-00000005", "q1") in new stack
WARNING[5746][C-00000006]: app_queue.c:8019 queue_exec: Unable to join queue 'q1'
-- Executing [8100@outbound:3] Hangup("PJSIP/7001-00000005", "") in new stack
== Spawn extension (outbound, 8100, 3) exited non-zero on 'PJSIP/7001-00000005'
С опцией joinempty клиент не может зайти в очередь, команда Queue() немедленно завершается, и выполняется следующая команда, в данном случае Hangup(). Вы можете добавить в диалплан анализ переменной QUEUESTATUS, которую устанавливает команда Queue, и на основе ее значения принимать решение о дальнейшей маршрутизации подобного звонка.
Добавление в очередь операторов
- Наберите 8201 с софтфона или смартфона:
-- Executing [8201@outbound:1] AddQueueMember("PJSIP/7002-0000000c", "q1") in new stack
NOTICE[6797][C-0000000c]: app_queue.c:7765 aqm_exec: Added interface 'PJSIP/7002' to queue 'q1'
-- Executing [8201@outbound:2] Hangup("PJSIP/7002-0000000c", "") in new stack
Выполните queue show
в CLI:
pc1*CLI> queue show
q1 has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
Members:
**PJSIP/7002** (ringinuse enabled) (dynamic) (Not in use) has taken no calls yet
No Callers
Теперь наберите 8100 с Digium телефона, чтобы зайти в очередь в качестве клиента.
-- Executing [8100@outbound:1] Answer("PJSIP/7001-0000002d", "") in new stack
-- Executing [8100@outbound:2] Queue("PJSIP/7001-0000002d", "q1") in new stack
-- Started music on hold, class 'default', on channel 'PJSIP/7001-0000002d'
-- Called PJSIP/7002
-- PJSIP/7002-0000002e connected line has changed. Saving it until answer for PJSIP/7001-0000002d
-- PJSIP/7002-0000002e is ringing
Звонок попадает в очередь, потому что теперь там есть оператор, телефон которого немедленно начинает звонить.
- Примите вызов
-- PJSIP/7002-0000002e answered PJSIP/7001-0000002d
-- Stopped music on hold on PJSIP/7001-0000002d
-- Channel PJSIP/7002-0000002e joined 'simple_bridge' basic-bridge <718ca9f4-4b8d-428b-8444-75604fab080f>
-- Channel PJSIP/7001-0000002d joined 'simple_bridge' basic-bridge <718ca9f4-4b8d-428b-8444-75604fab080f>
Вот оно, работает! Очередь соединила клиента с оператором.
Постановка операторов на паузу
Операторам иногда нужен перерыв в приеме входящих звонков. Чтобы не выходить из очереди и потом снова заходить, для этой цели лучше использовать постановку оператора на паузу.
- Обратите внимание на экстеншены 8203 и 8204 в extensions.conf-queues. Команды
PauseQueueMember()
иUnpauseQueueMember()
принимают аргументы:- Первый аргумент (необязательный) — имя очереди, в котором нужно поставить на паузу.
- Второй аргумент — имя члена очереди.
Как это работает: ${CUT(CHANNEL,-,1)}
используется здесь, чтобы получить имя члена очереди из переменной ${CHANNEL}
, которая имеет вид “PJSIP/7001-0000002”. Для этого используется функция CUT() что бы отсечь лишнюю часть строки и взять только “PJSIP/7001”. Второй аргумент функции указывает использовать в качестве разделителя знак ”-”, а третий аргумент, единица, — означает взять первую часть строки до разделителя.
- Наберите 8203 с телефона, который является уже членом очереди.
- Наберите в CLI
queue show
:
Members:
PJSIP/7002 (ringinuse enabled) (dynamic) (paused) (Not in use) has taken 3 calls (last was 2444 secs ago)
- Наберите 8100 с Digium телефона:
- Член очереди молчит, верно?
- Наберите 8204, чтобы снять телефон оператора с паузы:
- Вызов из очереди почти сразу будет направлен на оператора.
У очереди может быть много других опций. Пролистайте queues.conf.sample в субдиректории configs в исходниках Астериска. Обратите внимание на опции:
- strategy
- autofill
- persistentmembers
- wrapuptime
- shared_lastcall
- timeout
- retry
Подсказка: Если вы не желаете, чтобы на телефон, который является членом очереди, не приходил вызов из очереди, когда он уже находится в состоянии разговора с кем-то, добавьте опцию
ringinuse=no
.
Дополнительное задание
К сожалению, в Asterisk нет одной команды, чтобы поставить оператора на паузу, если он был не на паузе, и снять с паузы, если он уже был на паузе. Но это легко реализовать в диалплане, используя функцию QUEUE_MEMBER(). Добавьте в контекст features экстеншен 8205, который будет ставить на паузу, или снимать с паузы, в зависимости от текущего статуса.
6. Автоматизация звонков
- Узнать о дополнительных возможностях совершения звонков в Asterisk помимо традиционного:
- CLI-оригинация.
- Файлы вызовов.
- Manager originate (AMI).
- Усвоить материал на практическом примере.
CLI-оригинация
-
Напишите
help channel originate
в CLI Asterisk для получения справки.Заметьте, что имеется два варианта использования команды.
-
Напишите
channel originate PJSIP/7001 application Playback demo-congrats
CLI> channel originate PJSIP/7001 application Playback demo-congrats
-- Called 7001
-- PJSIP/7001-00000004 is ringing
-- PJSIP/7001-00000004 answered
-- <PJSIP/7001-00000004> Playing 'demo-congrats.gsm' (language 'ru')
Обратите внимание, что Caller ID показывает звонок от анонимуса, ибо оригинация идёт с сервера, а не с другого телефона. * Напишите
channel originate PJSIP/7001 extension 8001@features
CLI> channel originate PJSIP/7001 extension 8001@features
-- Called 7001
-- PJSIP/7001-00000005 is ringing
-- PJSIP/7001-00000005 answered
-- Executing [8001@features:1] Playback("PJSIP/7001-00000005", "demo-congrats") in new stack
-- <PJSIP/7001-00000005> Playing 'demo-congrats.gsm' (language 'ru')
- Тот же самый результат (телефон звонит, играет демо-поздравление о настройке), но посредством другого механизма:
- Первый подход вызывал непосредственно приложение и потом вешал трубку.
- Второй подход делал вызов через существующий экстеншен в вашем диаплане.
Использование файлов звонков
Файлы звонков (call files) размещаются по пути /var/spool/asterisk/outgoing/, где Астериск их видит и обрабатывает. Не рекомендуется использовать Linux-утилиту “cp” с этими файлами, потому что Asterisk может начать их обработку, когда они еще не до конца скопируются. Используйте Linux-утилиту “mv” - изменится только указатель, физически файл не затронется.
-
Откройте два терминала: в одном Астер, в другом - директория /root.
-
Откройте файл sample.call, находящийся в /root.
-
Измените XX_sip_phone на 7001, сохраните и закройте файл.
-
Затем выполните следующие команды:
cp sample.call $$.call
иmv $$.call /var/spool/asterisk/outgoing/
- Телефон Digium должен немедленно зазвонить и проиграть demo-congrats.
-
Пока идет звонок, наберите в консоли
core show channel <tab complete>
Заметьте, что тестовая переменная “TestVariable=31415” отображается — она была определена в call-файле.
-
- Телефон Digium должен немедленно зазвонить и проиграть demo-congrats.
-
Можно по-разному экспериментировать с различными конфигурациями и опциями в файлах вызовов.
AMI оригинация
- AMI может также использоваться для инициализации звонков.
- Лучшее решение для автоматизации звонков с удаленных систем.
- Не раскрывается детально в данной лабораторной.
Автоматизация звонков — практический пример
- Сценарий следующий — вы хотите автоматически генерировать звонки, когда веб-вервер перестает работать.
- Если у вас установлен Apache (httpd), в терминале Linux наберите
systemctl start httpd
для запуска сервера. - Убедитесь, что он запущен
# ps x | grep httpd
apache 6534 0.0 0.1 230344 3172 ? S 11:43 0:00 /usr/sbin/httpd -DFOREGROUND
root 6615 0.0 0.0 112672 984 pts/2 S+ 11:43 0:00 grep --color=auto httpd
- Вывод в вашем терминале может отличаться от описанного выше. Вторая, нужная нам колонка, является номером процесса (PID).
- Если Apache не запустился, то смотрите логи ошибок.
- Далее откройте
*/root/httpd_down_spool_callfile.sh
- Измените “
SIP/ХХ_digium_phone
” наPJSIP/7001
.-
Пояснение содержимого bash скрипта
-
Первые строчки устанавливают переменные для использования, когда произойдет вызов.
-
”
while true; do
” означает, что будет выполняться цикл при определенных усовиях. -
”
if
” проверяет, запущен ли Апач. -
”
|
” отделяет команды и их вывод друг от друга. -
”
ps x
” получает список процессов. -
”
grep -v callfile
” удаляет “callfile”. -
”
grep -v grep
” удаляет “grep” из списка. -
”
wc -l
” получает номер строки. 1 - сервер запущен, 0 - не запущен.- Логический вариант объяснения (алгоритм):
- Поиск всех запущенных процессов | которые имеют название “httpd” | далее удаление процесса с “callfile” в его имени | потом удаление процесса с именем “grep” | и вывод на экран строк с цифрами.
- Иначе, если сервер не запущен, создать файл вызова и совершить звонок.
- ”Sleep 60” — установить ожидание на 60 секунд в конце цикла.
- После изменения ХХ на номер вашей станции в скрипте, сохраните и закройте файл.
- Логический вариант объяснения (алгоритм):
-
- Запустите
httpd_down_spool_callfile.sh
скрипт из консоли Linux, находясь в директории /root:./httpd_down_spool_callfile.sh
-
Скрипт ничего не выводит на экран и создается впечатление, будто ничего не происходит, но это не так.
-
На данный момент ничего не произойдет, ибо Апач все ещё запущен. Откройте новую вкладку терминала комбинацией Ctrl+Shift+C и остановите процесс Apache:
systemctl stop httpd
Имейте ввиду, что можно выполнить команду из CLI Астера, добавив знак восклицания:
!systemctl stop httpd
-
Ваш Digium-телефон должен зазвонить через 60 секунд после остановки Apache. Звонок будет осуществляться каждую минуту, пока запущен скрипт и не запущен веб-сервер. * Остановите скрипт, нажав Ctrl+C в терминале Linux.
Заключение
- Все автоматизированные звонки в этой лабораторной были адресованы телефонам, но они могли также легко быть подключены к SIP-транкам или любым другим каналам Астериск.
- Дополнительный файл вызовов может быть весьма полезен:
- WaitTime — определяет длительность звонка в секундах.
- RetryTime — определяет время для повторного вызова.
- MaxRetries — максимальное количество попыток вызова.
- В продакшине подобный bash-скрипт должен вызываться через планировщик Crontab. В нашем случае — простой пример для лабораторной.
7. Конференции
- Настроить базовую функциональность ConfBridge().
- Настроить профили пользователей.
- Обзор функции CONFBRIDGE().
Базовая конференция
- Откройте extensions.conf и добавьте в контекст [features]:
exten => 8005,1,Answer()
same => n,ConfBridge(1234)
same => n,HangUp()
- Сохраните файл и перезагрузите диалплан, после этого позвоните на номер 8005 с вашего Digium телефона.
- Пока первый телефон в конференции, наберите тот же номер конференции со следующего телефона - Zoiper. Хотя участники в конференции, но нет музыки на удержании и меню DTMF не доступно. Приложенение ConfBridge использует системные значения по умолчанию, когда не заданы другие, и это всё не очень интересно.
Для добавления функциональности конференции, используем три независимых профиля. Когда конференция создана и пользователи присоединились, эти три профиля будут использоваться для управления ConfBridge: закрытие, удаление и/или добавление пользователей и прочее:
Bridge Profiles. Определяет, как конференция будет вести себя для всех участников, и включает в себя такие опции, как запись на конференции, какие звуки использовать для подсказки и другие варианты.
User profiles. Определяет, как пользователь ведет себя в конференции. Это включает в себя варианты, например, является ли или нет пользователь администратором, следует ли воспроизводить звуковые подсказки, когда они входят, и т.д.
Conference Menus. Каждый, кто зайдет в конференцию, будет иметь пользовательское DTMF меню, позволяющее контролировать различные функции для себя и других пользователей, если есть такая возможность.
Настройка ConfBridge Profiles
1. Создание bridge profile для участников конференции.
- Откройте confbridge.conf и добавьте:
[my_conference]
type=bridge
record_conference=yes
Поле “type” самое главное — оно определяет тип, как bridge в данном случае.
2. Создание user profile для участников конференции.
- В confbridge.conf добавьте:
[normal_user]
type=user
announce_user_count=yes
music_on_hold_when_empty=yes
- Из консоли Астера перезагрузите соответствующий модуль:
module reload app_confbridge.so
Вы добавили две настройки к настройкам по умолчанию. Во-первых, сделайте так, чтобы при входе в конференцию, имелась возможность узнать количество её участников. Во-вторых, сделайте поддержку музыки на удержании, если в конференции находится всего один участник.
3. Применение профилей конференции к экстеншену
- Создайте другую конференцию в контексте [features] вашего диалплана:
exten => 8006,1,Verbose(1,Now entering a conference!)
same => n,ConfBridge(demo_conference,my_conference,normal_user)
same => n,Hangup()
- Перезагрузите диалплан и наберите 8006 с вашего первого телефона, а потом со второго наберите тот же номер.
- Пока ваши телефоны в конференции, напишите в CLI Asterisk:
confbridge list demo_conference
Вы увидите информацию о всех участниках конференции. Тем не менее, пользователи с различными профилями могут присоединяться к конференции. Те пользователи, которые имеют привилеги администратора, могут создавать закрытые конференции. Теперь создайте новый профиль для ввода в конференцию админа.
4. Создание профиля для администратора конференции
- Откройте confbridge.conf и добавьте следующее:
[admin_user]
type=user
admin=yes
announce_user_count=yes
music_on_hold_when_empty=yes
У вас уже создан экстеншен 8006 в контексте [features] для обычных пользователей. Теперь создайте экстеншен 8007 в том же контексте для админа. Так как юзер-админ нуждается в DTMF меню для выполнения привилегий, добавьте 4 аргумент к приложению - sample_admin_menu (шаблон находится в том же confbridge.conf).
- Откройте диалплан и добавьте:
exten => 8007,1,Verbose(1,Now entering a conference!)
same => n,ConbBridge(demo_conference,my_conference,admin_user,sample_admin_menu)
same => n,Hangup()
- В CLI Asterisk перезагрузите диалплан и модуль app_confbridge.so:
- Наберите 8007 с первого телефона. Наберите 8006 со второго телефона. В консоли Астера:
confbridge list demo_conference
Вы увидите, что ваш первый телефон использует профиль админа и имеет DTMF меню.
- Наберите 8007 с первого телефона. Наберите 8006 со второго телефона. В консоли Астера:
- На первом телефоне нажмите ”*”, чтобы услышать доступные команды для администратора. Нажмите 3, чтобы отключить последнего участника конференции.
Помните: меню отличаются от user и bridge профилей тем, что они должны быть созданы и присвоенный каналу — меню по умолчанию нет. В продакшине вы можете настроить свои собственные пользовательские меню и меню звуковых файлов, которые вам требуются.
5. Создание и применение пользовательского меню
- Откройте confbridge.conf и добавьте строки:
[user_menu]
type=menu
*=playback_and_continue(conf-usermenu)
*1=toggle_mute
1=toggle_mute
*2=leave_conference
2-leave_conference
- Откройте extensions.conf и отредактируйте экстеншен 8006, чтобы добавить ваше новое меню:
exten => 8006,1,Verbose(1,Now entering a conference!)
same => n,ConfBridge(demo_conference,my_conference,normal_user,user_menu)
same => n,Hangup()
Сохраните файл и перезагрузите диалплан и модуль app_confbridge.so Протестируйте ваше новое меню, набрав 8006 с вашего телефона.
Примечание: когда пользователи нажимают ”*”, начинает играть фоновая музыка. Часто пользователи знают, какую кнопку нажимать ещё до того, как меню будет озвучено, поэтому полезно делать одно и тоже меню для обоих кнопок сразу.
Маркированные пользователи конференции
Админы имеют больше полномочий, чем обычные пользователи, но при входе в конференцию это никак не отображается, что зашёл админ. Существует ещё один параметр, независимый от “обычного” юзера или “админа”, который определяет поведение пользователей в конференции. Это “marked” пользователи, “wait marked” пользователи и “end marked” пользователи (то есть с маркировкой).
Marked users — лидеры конференции, при входе которых в конференцию пользователи со статусом “wait marked” также входят в конференцию. Когда последний “marked user” уходит, все оставшиеся “marked users” будут кикнуты.
Wait marked users — последователи конференции. Пока не зайдет лидер, они будут в состоянии ожидания.
End marked users — аналогичны предыдущим, но автоматически кикаются из конференции, когда последний “marked user” уходит.
Вы можете комбинировать wait marked и end marked свойства пользователей, если вам нужны оба свойства. Давайте посмотрим, как они используются вместе друг с другом:
- Откройте confbridge.conf и добавьте админу и обычным пользователям маркировку:
[normal_user]
type=user
announce_user_count=yes
music_on_hold_when_empty=yes
wait_marked=true
end_marked=true
[admin_user]
type=user
admin=yes
announce_user_count=yes
music_on_hold_when_empty=yes
marked=true
- Сохраните файл и перезагрузите диалплан и модуль app_confbridge.so
- Наберите 8007 с первого телефона.
- Наберите 8006 со второго телефона.
- Положите трубку первого телефона - второй телефон должен отключиться.
- Теперь наоборот: звоните 8006 с первого и 8007 со второго.
- Конференция начнется тогда, когда зайдет лидер (marked user).
- Установка динамических опций в диалплане
Используя CONFBRIDGE() функцию с приложением Set() диалплана, вы можете менять опции пользователей динамически, когда канал уже создан. Например, если админ хочет иметь стандартный профиль без настроек маркировки в файле confbridge.conf, то это можно сделать прямо из диалплана.
- Измените в extensions.conf экстеншен 8007:
exten => 8007,1,Verbose(1,Now entering a conference!)
same => n,Set(CONFBRIDGE(user,template)=admin_user)
same => n,Set(CONFBRIDGE(user,marked)=true)
;same => n,ConfBridge(demo_conference,my_conference,admin_user,sample_admin_menu)
same => n,ConfBridge(demo_conference,my_conference,,sample_admin_menu)
same => n,Hangup()
Сохраните файл и перезагрузите диалплан и модуль app_confbridge.so Повторите предыдущие действия и убедитесь, что звонящий на 8007 все ещё промаркирован.
Обзор
- ConfBridge() предлагает мощные инструменты Астеру по организации и управлению конференциями.
- Серьезно отличается от MeetMe.
- Посмотрите
core show application confbridge
и /etc/asterisk/confbridge.conf.sample для изучения других возможностей.
Дополнительные вопросы и задания
- Limit the maximum number of users in your conference to 1 user. What happens when the second user tries to dial in? An admin user?
- Use a channel variable with a subroutine to direct a user into your conference with admin and marked user choices turned on.
- Use a single extension for a conference, and use an expression to route the caller into the conference with an admin/marked user or normal user profile based on caller id.
- Use templates in confbridge.conf to simplify common menu and profile options. For instance, if announce_user_count=yes is an option you want more than one user profile to have, create a template and apply to the appropriate profiles.
- Conference in a classmate. Set up a SIP trunk to your neighbor and modify your dialplan to allow access to your conference.
8. Настройка features.conf
- Настройка записи одним нажатием кнопки, используя
Dial()
и features.conf - Обзор features.conf
- Экспериментирование с функцией диалплана PITCH_SHIFT
Тестирование automixmon feature
- Откройте /etc/asterisk/features.conf и посмотрите на секции [general] и [featuremap]
- “automixmon” - хардкодовое название фичи.
- ”*3” - комбинация для активации (может быть изменена).
- Комментарий, напоминающий, что для активации фичи, в диалплане необходимо добавить “хХ”.
- Измените экстеншен 7002, добавив в Dial() третий параметр “xX”
- Перезагрузите диалплан, наберите 7002 с вашего Digium телефона и нажмите “*3”, вы должны увидеть, что началась запись:
-- Executing [7001@outbound:1] Dial("PJSIP/7003-0000002f", "PJSIP/7001,20,xX") in new stack
-- Called PJSIP/7001
-- PJSIP/7001-00000030 is ringing
-- PJSIP/7001-00000030 answered PJSIP/7003-0000002f
== Begin MixMonitor Recording PJSIP/7003-0000002f
- Скажите что-нибудь и положите трубку, вы увидите, что запись остановилась:
== MixMonitor close filestream (mixed)
== End MixMonitor Recording PJSIP/7003-0000002f
- В терминале Linux:
ls /var/spool/asterisk/monitor/
Вы должны увидеть что-то похожее:
[student@pc1 atp-files]$ ls /var/spool/asterisk/monitor/
auto-1488277184-7001-7003.wav
- Если хотите, вы можете прослушать запись.
- Если у вас есть динамики, напишите
play /var/spool/asterisk/monitor/auto*
в терминале Linux. - Или добавьте новый экстеншен в контекст [features], чтобы проиграть файл.
- Файл переместите в /var/lib/asterisk/sounds
- Если у вас есть динамики, напишите
- Теперь позвоните с Zoiper на 7001.
- Когда выбираете в DTMF кнопку для записи:
- В консоли Астера ничего не происходит, почему?
- Вы не добавили флаг “xX” к Dial() экстеншена 7001.
Applicationmap
Automixmon является встроенной фичей. Вы можете создавать свои собственные, используя applicationmap. Нижеследующий пример использует функцию диалплана PITCH_SHIFT, чтобы увеличивать или уменьшать громкость аудио “на лету”.
- Откройте features.conf и посмотрите секцию [applicationmap]:
- 2 отдельные фичи для понижения и увеличения уровня громкости.
- ”pitchUp/pitchDown” - пользовательские имена для использования в Dialplan.
- ”_1”/“_2” - настраиваемые команды для DTMF.
- ”self” - означает, что фича будет активированна на том же канале, на котором была инициализирована.
- ”both” - позволяет активировать фичу обоим звонящим.
- ”Set(PITCH_SHIFT(both)=high)” - приложение диалплана с аргументами
- ”high\low” - соответственно, повышение или понижение.
- Applicationmap не может быть использован, пока не активируется в диалплане в специальном экстеншине.
- Отредактируйте экстеншен 7002, добавив с более высоким приоритетом:
exten => 7002,1,Set(__DYNAMIC_FEATURES=pitchUp#pitchDown)
...
- Функции
Dial()
задайте следующий приоритет в порядке возрастания. - Помните, что используются два нижних подчеркивания в
__DYNAMIC_FEATURES
. - Перезагрузите диалплан и позвоните 7002 с Digium телефона, примите вызов на Zoiper.
- Нажмите *1 на Digium, когда разговариваете и убедитесь, что уровень увеличился.
- Нажмите *2 на Digium, когда разговариваете и убедитесь, что уровень уменьшился.
- Какие еще интересные фичи могут быт полезными и интересными в контексте обсуждаемой темы?
9. Макросы
Рекомендуемый метод создания подпрограмм для вашего диалплана - использовать GoSub. Макросы все ёщё поддерживаются, и их можно много где встретить, по-этому данная лабораторная познакомит вас с макросами.
- научиться использовать макросы для более эффективной настройки Dialplan
Посмотрите на ваши существующие экстеншены 7001 и 7002 в контексте [phones]. Они оба выглядят очень простыми, но поддерживать их всегда в таком состоянии затруднительно. В продакшине используется много функций, которые заставят ваш диалплан разрастись до неимоверных размеров. Макросы позволят оптимизировать экстеншены, приведя огромное количество настроек в удобный и читабельный вид.
Шаг 1. Объявите новый макрос
- В следующем терминале откройте extensions.conf и добавьте новый контекст с названием [macro-standard] в конце [phones] и перед началом [features].
- Начните с добавления
Set(__DYNAMIC_FEATURES)
, который был с первым приоритетом в экстеншине 7002:exten => s,1,Set(__DYNAMIC_FEATURES=pitchUp#pitchDown)
- Теперь добавьте измененный аргумент Dial(). Вы увидите специальную переменную “ARG1”, которая установится, когда макрос будет вызываться из диалплана:
same => n,Dial(${ARG1},20,xX)
Здесь добавляется таймаут вызова длинной в 20 секунд, после чего вызов завершается, если на него не ответили. Остальные параметры не изменяются.
Теперь добавьте несколько GotoIf строк, которые проверяют возвращаемое значение,устанавливаемое приложением Dial(). Вы перенаправите вызов, основываясь на этом значении. * Конечный вид макроса:
exten => s,1,Set(__DYNAMIC_FEATURES=pitchUp#pitchDown)
same => n,Dial(${ARG1},20,xX)
same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
same => n(unavail),Voicemail(${MACRO_EXTEN},u)
same => n,Hangup()
same => n(busy),Voicemail(${MACRO_EXTEN},b)
same => n,Hangup()
Шаг 2. Пропустите звонки через новый макрос
- Теперь ваш макрос готов, но ещё нигде не вызывается из диалплана.
- Закомментируйте строки с экстеншенами 7001 и 7002.
- Теперь вы можете заменить их всего лишь одним вызовом макроса:
exten => 7001,1,Macro(standard,PJSIP/XX_digium_phone)
exten => 7002,1,Macro(standard,PJSIP/XX_zoiper)
Все логика живет в макросе под названием “standard”, поэтому вам нет необходимости указывать имя целиком. Посмотрите на формат. Нумерация экстеншенов та же самая, и вы всё ещё с первым приоритетом. Вы вызываете Macro()
, далее первый аргумент — имя макроса — “standard”. Астер будет знать, что ему нужен контекст с названием [macro-standard]
. Следующим параметром идёт имя вызываемого девайса.
- Сохраните диалплан и перезагрузите.
- Проверьте ошибки, особенно названия контекстов.
- Позвоните с одного телефона на другой, и убедитесь, что вызов проходит.
- Теперь звоните с одного телефона на другой до окончания таймаута вызова — вы должны услышать сообщение о недоступности устройства.
- Снова позвоните и на втором телефоне отклоните вызов — на первом телефоне услышите сообщение, что устройство занято.
Эта конфигурация использует только около десятка строк + строки вызова самого макроса. Если бы у вас было даже 30, ну, или еще хуже - 300 телефонов, в таком диалплане вы бы точно запутались. В любом случае, редактировать такой огромный объем текста очень неудобно и затруднительно. Подумайте, сколько времени можно сохранить, изменив 12 строк в одном макросе, который применяется к огромных количествам конечных устройств? В этом вся сила макросов.
10. GoSub
- Изучить, как использовать GoSub в Dialplan.
Шаг 1. Создание контекста
- В первом терминале откройте extensions.conf и добавьте новый контекст [subDialer] в самом низу файла.
- Сюда вы добавите некоторые экстеншены, которые были в [macro-standart]
[subDialer]
exten => begin,1,Set(__DYNAMIC_FEATURES=pitchUp#pitchDown)
same => n,Dial(${ARG1},20,xX)
same => n,GotoIf($["${DIALSTATUS}"="BUSY"]?busy:unavail)
same => n,(unavail),Voicemail(${ARG2},u)
same => n,Hangup()
same => n(busy),Voicemail(${ARG2},b)
same => n,Hangup()
Теперь ваша подпрограмма определена и ждёт вызова GoSub().
Шаг 2. Звонок через новую подпрограмму
- Закомментируйте текущие 7001 и 7002 экстеншены, вызываемые Macro() и замените их на:
exten => 7001,1,GoSub(subDialer,begin,1(PJSIP/7001,${EXTEN}))
exten => 7003,1,GoSub(subDialer,begin,1(PJSIP/7003,${EXTEN}))
- Помните, что здесь не используются переменные канала. Вы пропускаете переменную
${EXTEN}
в качестве аргумента дляGoSub()
приложения и она может быть передана в пределах подпрограммы с помощью${ARG2}
. - Сохраните диалплан и перезагрузите его.
- Позвоните на разные телефоны, чтобы убедиться в правильной настройке.
- Теперь раскомментируйте строки, отвечающие за Macro(), не забыв закомментировать GoSub():
- Вы будете использовать macro для ваших подпрограмм во всех остальных задачах этого курса.
Целью данной лабораторной было показать вам основы GoSub и познакомить вас с новым методом подпрограмм. Теперь вы обладаете навыками для создания подпрограмм, которые могут потребоваться в вашей организации. Вы не будете ограничены в знаниях исключительно одних макросов - можете использовать то, что наиболее оптимально.
11. Аналоговые линии
- Настроить аналоговую плату (TDM410 / AEX410 / A4B00F).
- Понять значимость двух частей конфигурации оборудования, system.conf и chan_dahdi.conf.
- Научиться работать с утилитами применения конфигурации и проверки статуса.
В этой лабораторной работе вам предстоит настроить аналоговую плату Digium. Шаги, описанные здесь можно использовать для настройки любой аналоговой платы Digium. По мере выполнения этой лабораторной вам предстоит разобраться с конфигурационными файлами system.conf и chan_dahdi.conf и утилитами для настройки плат. Настройка плат состоит из двух частей: настройка модулей DAHDI ядра Linux, и настройка Asterisk.
Шаг 1: Проверка правильной установки платы
- В отдельном терминале выполните:
# lspci
- Cмотрите на строки со словом Digium. Наличие такой строки подтверждает, что Linux плату “видит”:
04:00.0 Ethernet controller: Digium, Inc. Wildcard TDM410 4-port analog card (rev 11)
У вас должно быть всего две платы Digium, одна - аналоговая, другая - цифровая. Цифровую мы будем настраивать в следующей лабораторной работе.
Шаг 2: Загрузка модулей ядра, работающего с платой
Модуль ядра — это “драйвер” платы и он может быть загружен обычной командой Linux — modprobe
- Убедимся, что сервис DAHDI не запущен (после установки он автоматически добавляется в автозагрузку системы):
# systemctl stop asterisk
# systemctl stop dahdi
- Наблюдайте за логами системы в отдельной консоли:
# tail -f /var/log/syslog
- Теперь вручную загружаем нужный нам модуль ядра. Поддержку платы TDM410 обеспечивает модуль wctdm24xxp (wcaxx для платы A4B00F):
# modprobe wctdm24xxp
- В другой консоли читаем логи ядра при загрузке модуля. Там должна содержаться информация об установленных модулях FXO/FXS.
- Также можно убедиться что модуль загружен командой
# lsmod | grep wctdm
:
wctdm24xxp 117170 0
dahdi_voicebus 59129 1 wctdm24xxp
dahdi 227771 2 wctdm24xxp,dahdi_voicebus
crc_ccitt 12707 2 wctdm24xxp,dahdi
Шаг 3: Настройка платы для работы в Linux
Сперва нужно правильно настроить плату для корректной работы операционной системы Linux с ней. Настройка осуществляется в /etc/dahdi/system.conf.
- В новой вкладке gedit откройте файл /etc/dahdi/system.conf.
- Пролистайте его, в нем содержится все возможные настройки для всех поддерживаемых плат.
- Скопируйте его для того, что бы позже можно было обратиться к оригинальному файлу:
# cd /etc/dahdi/
# cp system.conf system.conf.orig
- Выполните “волшебную” команду авто-конфигурации DAHDI:
# dahdi_genconf
- Команда
dahdi_genconf
автоматически вносит в system.conf все нужные изменения. Gedit уведомит вас об изменении этого файла и предложит его перечитать. Посмотрите на то, какие изменения команда выполнила в данном файле:
# Span 1: WCTDM/0 "Wildcard TDM410P" (MASTER)
fxoks=1
echocanceller=mg2,1
# channel 2, WCTDM/0/1, no module.
# channel 3, WCTDM/0/2, no module.
fxsks=4
echocanceller=mg2,4
# Global data
loadzone = us
defaultzone = us
Нам остается изменить loadzone и defaultzone на ru и выполнить команду, которая загружает настройки из этого файла в активную конфигурацию операционной системы:
# dahdi_cfg -v
Вывод команды должен быть похожим на следующее:
# dahdi_cfg -v
DAHDI Tools Version - 2.9.1
DAHDI Version: 2.9.1.1
Echo Canceller(s):
Configuration
======================
2 channels to configure.
Setting echocan for channel 1 to mg2
Setting echocan for channel 4 to mg2
Отсутствие ошибок говорит о том, что изменения применены успешно и только в таком случае можно переходить к следующим шагам.
Шаг 4: Настройка платы для работы с Asterisk
Теперь настроим Asterisk для работы с платой. За работу с платами Digium отвечает конфигурационный файл /etc/asterisk/chan_dahdi.conf
- Открываем его на редактирование.
- Листаем, видим все возможные настройки для всех поддерживаемых плат. Опять копируем оригинал, для того, что бы в будущем можно было к нему обратиться за помощью:
# cd /etc/asterisk/
# cp chan_dahdi.conf chan_dahdi.conf.orig
- Стираем все содержимое.
- Создаем секцию [channels]. Будем придерживаться старого синтаксиса и все настройки производить в одной секции.
- Открываем файл /etc/asterisk/dahdi-channels.conf. Этот файл не читается Asterisk’ом. Он был создан “волшебной” командой
dahdi_genconf
нам в помощь. Поэтому мы просто копируем его содержимое в секцию[channels]
в файл chan_dahdi.conf и правим под себя. На выходе получим такой конфигурационный файл:
[channels]
signalling=fxo_ks
callerid="YOUR NAME HERE" <7003>
mailbox=7003
group=5
context=outbound
channel => 1
signalling=fxs_ks
callerid=asreceived
group=0
context=inbound
channel => 4
- Пришло время запустить Астериск и проверить работу аналоговых линий:
# systemctl start asterisk
- Подключаемся снова к консоли Астериск:
# asterisk -rvvv
*CLI> dahdi show channels
Chan Extension Context Language MOH Interpret Blocked State
pseudo default default In Service
1 outbound default In Service
4 inbound default In Service
Мы видим те каналы, которые мы настроили на предыдущих шагах.
Шаг 5: Настройка диалплана
- В extensions.conf добавляем новую глобальную переменную в секции_[globals]_:
FXOTrunk=DAHDI/4
.
- Добавляем экстеншен для исходящих вызовов через новый транк:
exten => _65XXXXXX,1,Dial(${FXOTrunk}/${EXTEN})
same => n,Hangup()
- Добавляем возможность звонить на аналоговый телефон с других телефонов:
exten => 7003,1,Dial(DAHDI/1)
- Перезагружаем диалплан:
*CLI> dialplan reload
- Для проверки FXS интерфейса:
- Наберите с аналогового телефона номер любого другого телефона.
- С других телефонов вы должны дозвониться на аналоговый телефон по номеру 7003.
- Для проверки исходящих звонков через FXO транк:
- Наберите проверочный номер 65990000. Вы должны услышать цифры набранного номера.
- Для проверки входящих из FXO звонков попросите соседа набрать номер 65XX0000, где XX — номер вашей станции:
- Как думаете, почему вы сами не можете себе позвонить на номер 65XX0000?
- Входящие звонки из FXO всегда поступают на экстеншен s.
- Решите, как вы хотите распорядиться входящими звонками и добавьте в [inbound] строчку:
exten => s,1,Goto(...)
На этом настройка аналоговой платы завершена. Теперь вы знакомы со всеми конфигурационными файлами, отвечающими за настройку DAHDI и главными командами.
Дополнительное задание
- Проверьте как влияют на работу:
- Опция
busydetect
для FXO интерфейса. - Опция
immediate=yes
для FXS интерфейса.
- Опция
12. Поток Е1
- Настроить цифровую плату.
- Поднять Е1 поток между своей станцией и станцией вашего напарника.
Данная лабораторная работа проводится в парах. Для начала выясните, к какому компьютеру подключен E1 кабель от вашего компьютера. Затем договоритесь с вашим напарникам, кто из вас будет “провайдером” и кто - “клиентом”. И приступим к настройке платы.
Шаг 1: Загрузка драйверов для платы
- Остановите Asterisk. В CLI:
CLI> core stop now
- Наблюдайте за логами системы в отдельной консоли:
# tail -f /var/log/syslog
- Остановите сервис DAHDI (если вы не сделали этого на предыдущей лабораторной):
#service dahdi stop
- Вручную перезагрузите модули ядра для плат:
# modprobe wctdm24xxp
# modprobe wcte12xp (если у вас TE121/TE122)
# modprobe wcte13xp default_linemode=e1 (если у вас TE131/TE132/TE133)
Причина загрузки модулей в ручном режиме заключается в том, что вы ранее уже настроили аналоговую плату на использование портов 1-4. А порядок загрузки модулей диктует, какие номера каналов назначаются соответствующей плате.
Для того, что бы в дальнейшем, после перезагрузки сервера, сохранить последовательность загрузки модулей необходимо отредактировать /etc/dahdi/modules и указать модуль аналоговой платы раньше чем модуль цифровой платы. Когда инициализационный скрипт /etc/init.d/dahdi выполняется при загрузке системы, или при выполнении service dahdi restart
, читается файл /etc/dahdi/modules и модули загружаются в указанном порядке.
- В новых платах Digium (TE131/TE132/TE133) выбор Е1/Т1 осуществляется не джампером на плате, а передачей параметра при загрузке модуля ядра. Так что если у вас одна из таких плат, в /etc/modprobe.d/dahdi.conf нужно добавить строчку:
options wcte13xp default_linemode=e1
- Для проверки запустите
lsmod
:lsmod | grep wct
Вывод должен быть примерно таким:
wcte12xp 37060 0
wctdm24xxp 140800 0
dahdi_voicebus 46016 2 wcte12xp,wctdm24xxp
dahdi 196680 5 wcte12xp,wctdm24xxp,dahdi_voicebus
crc_ccitt 6337 2 wctdm24xxp,dahdi
Заметьте, что оба драйвера для обеих плат загружены. Теперь приступим к настройке платы в части Linux.
Шаг 2: Настройка платы в Linux
- Откройте system.conf и посмотрите как он выглядит.
- Запустите из-под рута
dahdi_genconf
- Заметьте, какие изменения в данном файле произвела эта команда. Примерно такие:
# Span 2: WCT1/0 "Wildcard TE121 Card 0"
span=2,1,0,ccs,hdb3,crc4
# termtype: te
bchan=5-19,21-35
dchan=20
echocanceller=oslec,5-19,21-35
Опция span устанавливает timing, framing и encoding параметры. Bchan и dchan — какие каналы этой платы служат для передачи голоса и данных соответственно.
- Замените
span=2,1,0,ccs,hdb3,crc4
наspan=2,0,0,ccs,hdb3
иcrc4
, если вы “провайдер”. - Для применения новой конфигурации system.conf обязательно нужно запустить в CLI:
dahdi_cfg -v
Чем больше флагов v — тем больше уровень verbosity. Если сообщения об ошибке нет — мжно продолжать. Если есть ошибки — проверьте system.conf и запустите команду снова.
Шаг 3: Настройка платы в Asterisk
- Откройте chan_dahdi.conf — конфигурационный файл, читаемый модулем chan_dahdi.so.
- Откройте dahdi-channels.conf — файл, который сгенерировала утилита dahdi_genconf.
- Скопируйте из dahdi-channels соответствующий блок в chan_dahdi.conf и подправьте его немного, что бы он выглядел так:
; Span 2: WCT1/0 "Wildcard TE121 Card 0"
group=1
context=inbound
switchtype = euroisdn
signalling = pri_cpe ;if you are client
;signalling = pri_net ;if you are provider
channel => 5-19,21-35
Пожалуй, можно снова запустить Asterisk. Для того, что бы сразу отловить возможную критичную ошибку в chan_dahdi.conf, запустим Asterisk так:
# asterisk -vvvc
- В CLI проверяем настройки DAHDI:
*CLI> dahdi show channels
- Если в ответ получаем “No such command dahdi…” - значит в конфигурации проблема. Грузим модуль chan_dahdi.so вручную и внимательно читаем сообщения об ошибке:
*CLI> module load chan_dahdi.so
Если все в порядке, то вы должны увидеть все 30 каналов Е1 платы в придачу к FXS и FXO каналам, которые мы настроили ранее.
Шаг 4: Настройка диалплана
Что ж, прекрасно, карта настроена и в Asterisk появились новые каналы, которые мы можем использовать. Дальше вы знаете, что делать. Открывайте extensions.conf и добавляйте:
[globals]
PRITrunk=DAHDI/g1
[outbound]
exten => _66XXXXXX,1,Dial(${PRITrunk}/${EXTEN:4})
same => Hangup()
Обратите внимание на то, что мы отрезаем первые 4 цифры из номера, отправляемого в E1 поток. В случае с SIP и FXS это делал “провайдер”, но т. к. вы с напарником подключены напрямую, это приходится делать самим.
- Позвоните на 66XXYYYY, ваш напарник должен принять входящий вызов на номер YYYY.
- Если вы справились раньше, помогите с настройкой вашему напарнику.
- Включите PRI debug и понаблюдайте за служебными сообщениями:
*CLI> pri set debug on span 2
Дополнительное задание
Поменяйте “клиента” и “провайдера” местами.
13. SIP Realtime
- Понять, что Астериск может читать конфигурационные данные из базы данных (далее - БД) MySQL.
- Понять различие между конфигурированием Астериск через конфигурационные файлы и из БД.
- Понять связь между:
- Настройкой конфигов Астериск.
- Настройкой конфигов ODBC.
- данными в БД MySQL.
- Выполнить практическую настройку Астериск, ODBC и MySQL так, чтобы информация о SIP устройствах хранилась в БД.
- Понять сущность абстрактного слоя, который работает с PJSIP.
Шаги
- Отключить (в данном случае - закомментировать конфиги) девайсы в pjsip.conf.
- Установить Alembic и SQL Alchemy - инструменты БД для Python.
- Создать БД MySQL.
- Создать таблицы для элементов PJSIP через готовые скрипты.
- Заполнить таблицы информацией о существующих эндпоинтах.
- Убедиться что все работает.
Что же такое Realtime? Используя БД, мы будем хранить в ней информацию из файла pjsip.conf. А конкретно - данные из секций, таких как endpoints, auth и aors. Мы сконфигурируем Астериск так, чтобы информация в БД могла “на лету” изменяться в режиме реального времени - по сути, это и есть Realtime. На каждую секцию конфигурационного файла в БД будет заведена отдельная таблица со своими полями, значения которых будут изменяться. Это всё возможно реализовать посредством абстрактного слоя, который позволяет общаться Астериску и БД друг с другом. Этот слой называется Open Database Connectivity (ODBC) - открытый стандарт программируемого интерфейса приложений или проще - API, с помощью которого мы получаем доступ к БД. Это значит, что мы можем задействовать этот API для работы с различными СУБД, которые поддерживают ODBC.
Значительные изменения в Астериск для работы с Realtime были внесенены с релизом 12 версии. Таким образом, мы можем использовать утилиты с октрытым исходным кодом, позволяющие автоматизировать процесс для простоты настройки нужных нам БД и таблиц. Вы также можете делать все необходимые настройки вручную, но использование готовых скриптов и утилит значительно улучшает возможность контроля версий, переноса БД и развертывания сервера Астериск в режиме реального времени.
Зависимости Realtime
Все необходимые зависимости уже установлены, но вам стоит знать и понимать, для чего каждый их них необходим. Вы можете повторить это задание вне данной лабораторной самостоятельно. Нижеперечисленные пакеты установлены для CentOS и могут различаться для других дистрибутивов Linux:
- unixodbc и unixodbc-devel — движок ODBC.
- mysql-connector-odbc — связующий элемент между БД и движком ODBC.
- mysql-server — движок БД.
- libtool-ltdl and libtool-ltdl-devel — динамический модуль загрузчика, требуемый ODBC.
После установки зависимостей, Астериск необходимо пересобрать - в “menuselect” требуется выбрать модули ODBC. На лабораторных станциях это уже сделано за вас и модули включены в состав Asterisk.
Отключение pjsip.conf
- Откройте файл pjsip.conf и закомментируйте секции, отвечающие за подключение конечных устройств и транков ([7001], [7002], [7003], [servertrunk] и тому подобные, которые написаны в вашем случае.
- Перезагрузите pjsip.conf командой в CLI:
*CLI> pjsip reload
- Попробуйте позвонить на номер 8001 с каждого телефона, чтобы убедиться, что они не сконфигурированы - звонок не должен проходить.
- Запустите в консоли Астера
pjsip show endpoints
- не должно отражаться ни одного телефона.
Почему мы удаляем существующие настройки SIP-аккаунтов? Потому что вся информация из этих файлов будет перемещена в БД MySQL и желательно избегать наличия одного типа конфигурации в разных источниках. Так будет более очевидно, что все работает корректно.
Конфигурация Realtime
Наши действия:
- Установить MySQL и создать БД.
- Заполнить таблицы БД.
- Настроить Asterisk для работы с базой.
- Настроить ODBC для соединения MySQL и Астериска.
Шаг 1: Установка MySQL и создание БД
Для удобства назовем нашу БД “asterisk”. В конце лабораторной она будет содержать несколько таблиц с различными типами конфигурационных данных.
Best practise: пользователя БД наделяйте только теми полномочиями, которые действительно требуются. Более подробная информация о правильной настройке БД для их реального применения в продакшене в данном курсе не рассматривается.
В нашем случае БД находится на том же хосте, что и сервер Астериск, что многое упрощает. В реальности же она может располагаться где угодно.
- Прописываем в автозапуск MariaDB и сразу запускаем (флаг —now):
# systemctl enable --now mariadb
- Задаем пароль password для пользователя root (не используйте такие пароли в продакшине):
# mysqladmin -u root password password
- Логинимся в базу:
# mysql -u root -p
- Проверка наличия базы и таблиц:
- Показываем все существующие БД -
> show databases;
- Создаем БД “asterisk”:
> create database asterisk;
- Выбираем созданную базу -
> use asterisk;
- Убеждаемся, что таблиц нет (empty) -
> show tables;
- Показываем все существующие БД -
У вас должен быть примерно такой вывод в консоли:
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.01 sec)
MariaDB [(none)]> create database asterisk;
Query OK, 1 row affected (0.01 sec)
MariaDB [(none)]> use asterisk;
Database changed
MariaDB [asterisk]> show tables;
Empty set (0.00 sec)
- Выходим из базы:
> exit
Не забывайте ставить точку с запятой в конце каждой команды - таков синтаксис MySQL.
Наша база создана и теперь ей необходимы таблицы. Вместо создания их вручную, будем использовать скрипты на Python от сообщества разработчиков Астериск. Эти скрипты были написаны для утилит SQLAlchemy и Alembic (которые уже установлены в вашей системе). Больше информации об этих утилитах можете найти по ссылке: http://wiki.asterisk.org/wiki/display/AST/Managing+Realtime+Databases+with+Alembic.
- Настройка доступа к базе скриптами SQLAlchemy и Alembic:
- Перейдите в директорию:
# cd /usr/src/asterisk-X.X.X/contrib/ast-db-manage
- Скопируйте config.ini.sample в config.ini (наберите yes для перезаписи файла):
cp config.ini.sample config.ini
- Откройте config.ini текстовым редактором и поправьте строчку, которая отвечает за то, как SQLAlchemy подключается к нашей базе:
- Перейдите в директорию:
sqlalchemy.url = mysql://root:password@localhost/asterisk
- Ознакомьтесь с файлом
config/versions/<revisionid>_create_tables.py
.
Просмотрев его вы поймете, что он создает несколько таблиц с определенными типами полей и стандартными значениями. Запустив alembic вы создадите все таблицы, которые прописаны в этом скрипте, в том числе iax_friends
, voicemail, musicon hold и пр. Вы можете отредактировать скрипты по своему усмотрению. В данном курсе мы оставим все таблицы, которые создаются, по умолчанию.
- Создаем таблицы в нашей базе:
alembic -c config.ini upgrade head
- Логинимся в базу после выполнения скрипта:
# mysql -u root -p -D asterisk
> show tables;
Все таблицы, которые вы видите, были созданы скриптом. Те, которые начинаются с ps_, созданы для конфигурации pjsip.
Примечание: все таблицы, которые вы не включали в создание посредством скрипта, могут быть дропнуты. Для удобства держите окно консоли, где вы залогинены в mysql, открытым. Мы туда еще вернемся.
Шаг 2: заполнение базы
Вы можете вводить необходимые данные в таблицы, используя графическую оболочку для БД (phpmyadmin, например), или же работать напрямую из консоли, используя команду INSERT into: MariaDB [asterisk]> insert into ps_aors (id, max_contacts) values (7001,1);
Также, чтобы быстрее работать с таблицами, можно заполнять файл необходимыми запросами, а потом, “скормив” его базе, получить результат. Используйте рабочий пример, расположенный по адресу: /root/insert_ps_endpoints.sql
- Откройте этот файл текстовым редактором. Вы увидите шаблоны подготовленных SQL-запросов, которые необходимо отредактировать для настройки наших endpoint`ов (аналогичные настройкам в pjsip.conf).
- Внимательно просмотрите все значения и замените значения username и прочие при необходимости.
- Для импорта файла с запросами, перейдите в открытое окно консоли с БД, и введите команду:
> source /root/insert_ps_endpoints.sql
- Проверьте содержимое ваших таблиц (ваши данные могут отличаться):
MariaDB [asterisk]> select * from ps_auths;
+------+-----------+----------------+----------+----------+-------+--------------+
| id | auth_type | nonce_lifetime | md5_cred | password | realm | username |
+------+-----------+----------------+----------+----------+-------+--------------+
| 7001 | userpass | NULL | NULL | digium | NULL | 02_sip_phone |
| 7002 | userpass | NULL | NULL | digium | NULL | 7002 |
| 7003 | userpass | NULL | NULL | digium | NULL | 7003 |
+------+-----------+----------------+----------+----------+-------+--------------+
3 rows in set (0.00 sec)
MariaDB [asterisk]> select id,max_contacts from ps_aors;
...
MariaDB [asterisk]> select id, transport, aors, auth, context, disallow, allow, direct_media from ps_endpoints;
...
Теперь у вас есть БД с заполненными таблицами. Но мы до сих пор не настроили Астериск для взаимодействия с MySQL через ODBC.
Шаг 3: Настройка Asterisk для работы с базой
Астеру нужно знать, какую конфигурацию читать из базы. Чтобы сделать это, мы модифицируем файл /etc/asterisk/extconfig.conf.
- Откройте его и раскомментируйте следующие строчки:
[settings]
sippeers => odbc,asterisk_odbc,sipfriends
ps_endpoints => odbc,asterisk
ps_auths => odbc,asterisk
ps_aors => odbc,asterisk
ps_domain_aliases => odbc,asterisk
ps_endpoint_id_ips => odbc,asterisk
ps_contacts => odbc,asterisk
queue_members => odbc,asterisk
Эти таблицы содержат информацию о секциях различных типов из файла pjsip.conf.
- ”ps_endpoints” сообщает базе имя таблицы и соответствующий pjsip модуль.
- ”odbc” — имя драйвера базы данных.
- ”asterisk” — имя секции из файла конфигурации драйвера БД. В случае odbc это файл /etc/asterisk/res_odbc.conf. Приведите его к следующему виду:
[asterisk]
enabled => yes
dsn => asterisk
username => root
password => password
pre-connect => yes
[asterisk]
— имя секции, соответствующее предыдущей записи в extconfig.conf.enabled
— отвечает за состояние вкл\выкл.dsn
— соответствует предстоящей конфигурации ODBC.pre-connect
— causes the connection to be established when Asterisk is started, instead of waiting for the connection to be needed.
Шаг 4: Конфигурация ODBC для соединения MySQL и Астериск
ODBC является прослойкой между базой данных и Asterisk. Откройте файл /etc/odbc.ini и добавьте строчки:
[asterisk]
Description = MySQL Connection to 'asterisk' database
Driver = MySQL
Server = localhost
Port = 3306
Database = asterisk
User = root
Password = password
Socket = /var/lib/mysql/mysql.sock
Charset = utf8
- “[asterisk]” — имя секции. Должно соответствовать настройке dsn в /etc/asterisk/res_odbc.conf.
- ”Description” — общее описание
- ”Driver” — сообщает ODBC, какой тип драйвера БД используется (MySQL, PostGRES и т.д.)
- “Server” — адрес сервера базы. Не обязательно “localhost”, можно указать IP или доменное имя.
- ”Socket” - сообщает ODBC расположение сокета базы для соединения.
- ”Database” - текущее имя БД, которое мы установили ранее.
- ”Password” и “User” — пароль и имя пользователя соответственно. Они могут быть указаны либо в /etc/odbc.ini, либо в /etc/asterisk/res_odbc.conf.
ODBC также должен знать, где в системе лежат драйвера MySQL. Откройте файл /etc/odbcinst.ini и проверьте эти строки:
[MySQL]
Description = ODBC for MySQL
Driver = /usr/lib/libmyodbc5.so
Setup = /usr/lib/libodbcmyS.so
Driver64 = /usr/lib64/libmyodbc5.so
Setup64 = /usr/lib64/libodbcmyS.so
FileUsage = 1
- “[MySQL]” — имя секции. Должно соответствовать настройке Driver в /etc/odbc.ini.
- ”Driver” и “Setup” — модули Linux, которые использует ODBC для коннекта к базе.
- Модули в данном файле перечислены для 32 и 64-битных версий CentOS — это в порядке вещей и не требует никаких изменений.
Sorcery
Конфигурацией pjsip управляет Sorcery — абстрактный фреймворк. Его абстрактный уровень должен сообщить запрос для Realtime, когда pjsip запрашивает данные. Конфигурация файла содержит отображение прямых типов запросов к специальным таблицам в базе. Откройте файл sorcery.conf и проверьте, что нижеописанные строки раскомментированны:
[res_pjsip]
endpoint=realtime,ps_endpoints
auth=realtime,ps_auths
aor=realtime,ps_aors
domain_alias=realtime,ps_domain_aliases
[res_pjsip_endpoint_identifier_ip]
identify=realtime,ps_endpoint_id_ips
Realtime и кэширование данных с pjsip
Realtime очень гибкий и мощный, но имеет компромиссы. Он вводит дополнительную точку отказа, но дает дополнительные способы конфигурации Asterisk. Более старый драйвер канала, chan_sip, мог кэшировать данные в режиме реального времени локально в AstDB. Для сравнения, chan_pjsip не кэширует локально в 12 и 13 версия Астера. С 14 версией, Астер может использовать sorcery не только для записи и чтения конфигов из базы, но и кэшировать информацию в память. Преимуществом кэширования является более быстрое время отклика, что актуально для частоиспользуемых данных.
Проделанная работа
- Отключение pjsip.conf конфигурации.
- Настройка соединения между Астером и БД, используя ODBC.
- Установка и настройка БД.
- Добавление конфигурации для SIP-девайсов в таблицы.
- Проверка отображения нужных для pjsip объектов в БД.
Теперь время проверять! Напишите reload
в консоли Астера и наблюдайте что-то похожее:
res_odbc.c:617 load_odbc_config: Registered ODBC class 'asterisk' dsn->[asterisk]
...
- Если все настроено правильно, ваши телефону будут регистрироваться в Астере.
- Позвоните 8001 с каждого телефона:
- Если услышите демонстрационные поздравления о настройке Астера, то всё работает!
- Если нет, смотрите в консоль Астера и проверьте конфигурацию.
- Проверьте, что телефоны могут звонить друг другу: наберите 7001 или 7002 и убедитесь, что вызов проходит.
Финальная демонстрация: обновление настроек в режиме реального времени
- Откройте консоль БД:
# mysql -u root -p -D asterisk
- Проверьте ваши записи для телефонов:
> select id,auth_type,password,username from ps_auths;
- Измените пароль для 7002 на “123”:
> update ps_auths set password='123' where id=7002;
.- Перезапустите SIP клиента и при его попытке зарегистрироваться вы увидите сообщение
Request 'REGISTER' from ... failed for...
- Изменения вступили в силу без команды
reload
- это огронмый плюс использования Realtime.
- Перезапустите SIP клиента и при его попытке зарегистрироваться вы увидите сообщение
- Чтобы абонент 7002 снова смог звонить:
- Поменяйте пароль обратно в БД.
- Или же измените настройки SIP-телефона, указав ему новый пароль “123”.
Дополнительное задание
Добавьте поддержку голосовой почты в таблице ps_aors. Заметьте, что изменение настроек MWI могут не вступить в силу до pjsip reload
14. Переадресация звонков
В этой лабораторной вы отработаете взаимодействие БД ODBC напрямую из диалплана Asterisk. Возможность доступа и управления контентом из БД во время вызова - это мощный инструмент. Вы создадите набор пользовательских функций, которые в сочетании с dialplan позволят осуществлять перенаправление вызовов на аналоговых телефонах, которые изначально этого не умеют. Использование func_odbc и реляционных баз данных для создания переадресации дает нам некоторые другие преимущества по сравнению с другими методами (AstDB, диалплан и прочими). Такое решение легко масштабируется на множество серверов Asterisk.
Хранение телефонных номеров в реляционной БД облегчает интеграцию со сторонними решениями, например, отдельный веб-интерфейс для управления переадресацией.
- Изучить, как использовать
func_odbc
, ODBC и MySQL для управления БД из диалплана Астера. - Узнать, как можно использоваться эти связи для создания дополнительных возможностей.
Зависимости
- Лабораторная по настройке IP-телефона и софтфона.
- Лабораторная по настройке транка.
- Лабораторная по настройке DAHDI.
- Лабораторная по конфигурации Realtime.
- Эта лабораторная объясняет основные зависимости, которые необходимы Астеру до его подключения БД.
Порядок выполнения
- Создание БД для хранения номеров переадресации.
- Создание таблицы в новой БД для организации переадресации.
- Настройка /etc/odbc.ini для использования драйвером Линуксом вновь созданной БД.
- Настройка /etc/asterisk/res_odbc.conf для доступа Астера к этой БД.
- Создание пользовательских функций в func_odbc.conf.
- В конце вы просмотрите файл /etc/asterisk/extensions.conf-odbc-forward и увидите, как сторонние функции используются в диалплане.
Создание новой БД
- Подключитесь к БД из терминала Linux:
# mysql
- Создайте новую БД для возможности переадресации:
create database asterisk_features;
- Укажите, что хотите использовать новую БД:
use asterisk_features
- Для создания таблиц используйте готовый скрипт:
> source /root/create_forward_table.sql
- Посмотрите на созданную таблицу, запустив:
> describe user_call_forwarding
:- “id” хранит идентификатор строки для БД.
- ”device” хранит имя устройства для переадресации.
- ”fwdnumber” хранит номер для переадресации.
- ”status” хранит два значения - 1 или 0, позволяющие диалплану понять, в каком состоянии переадресация вызовов.
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| device | varchar(40) | YES | | NULL | |
| fwdnumber | varchar(20) | YES | | NULL | |
| status | tinyint(1) | YES | | 0 | |
+-----------+---------------------+------+-----+---------+----------------
- Оставьте этот терминал открытым - вы еще к нему вернетесь.
- Сейчас вы должны отредактировать конфигурационные файлы, позволяющие Asterisk использовать эту таблицу из БД.
Конфигурация odbc.ini:
- Откройте /etc/odbc.ini и раскомментируйте следующие строки:
[asteriskfeatures]
Description = MySQL ODBC Driver used to implement call forwarding functionality with func_odbc
Driver = MySQL
Server = localhost
UserName = root
Password = password
Database = asterisk_features
Socket = /var/lib/mysql/mysql.sock
Charset = utf8
- “[asteriskfeatures]” — заголовок раздела, соответствующий dsn в файле func_odbc.conf.
- ”Description” — свободная форма текста, объясняющая использования этого источника данных.
- ”Driver” — сообщает ODBC, с каким типом БД устанавливать соединение.
- ”Socket” — адрес расположения сокета для соединения.
- ”Server” — адрес сервера БД (не обязательно localhost, можно указать IP-адрес или DNS-имя).
- ”Database” — название текущей БД, которая будет использоваться.
Конфигурация res_odbc.conf
- Теперь необходимо настроить Астер для использования источника данных:
- Откройте /etc/asterisk/res_odbc.conf и расскоментируйте строки:
[features_odbc]
enabled => yes
dsn => asteriskfeatures
pre-connect => yes
[features_odbc]
— заголовок раздела, соответствующий dsn в файле func_odbc.conf.enabled
— состояние соединения с БД.dsn
(data source name) — соответствует заголовку, заданному в odbc.ini.pre-connect
— устанавливает соединения при запуске Asterisk вместо ожидания соединения по необходимости.
Теперь Asterisk успешно настроен для соединения с БД.
Конфигурация func_odbc
Здесь вы создатите пользовательские функции, чтобы использовать диалплан. Для осуществления переадресации, можно взаимодействовать с БД различными методами.
- Необходимо проверить нижеописанное:
- Проверка наличия записи о переадресации вызовов в базе данных.
- Установлена новая запись переадресации вызовов.
- Статус переадресации для текущей записи переадресации.
- Изменение статуса переадресации для текущей записи.
- Получение номера переадресации для записи.
- Изменение номера переадресации для записи.
Пользовательские функции необходимы для каждой из этих задач. Откройте файл func_odbc.conf и посмотрите на запись UPDATE_STATUS:
[UPDATE_STATUS]
prefix=FWD
synopsis=Changes the forwarding satus of the calling device.
dsn=features_odbc
writesql=UPDATE user_call_forwarding SET status = "${VAL1}" WHERE device = "${ARG1}"
[UPDATE_STATUS]
— имя пользовательской функции - будет использоваться в диалплане для её вызова.prefix
— префикс для вызова кастомной функции. Если префикс не указан, вызов должен начинаться с “ODBC_“.synopsis
— описание функции. Можно посмотреть для любой подобной функции, набрав в консоли Астера:CLI> core show function FWD_UPDATE_STATUS
dsn
— указывает на заголовок секции в res_odbc.conf (но не значение параметра dsn в res_odbc.conf) .writesql
— содержит подготовленный SQL-запрос для выполнения.- Если это функция чтения записей из БД, можно использовать “readsql”.
После того, как вы рассмотрели каждую из этих функций, надо двигаться дальше для обзора и настройки диалплана, в котором они используются.
Настройка диалплана
- Откройте /etc/asterisk/extensions.conf-odbc-forward и изучите его содержимое.
- Не пугайтесь множества непонятных строк. В этом файле две основных секции: контексты [forward] и [subForwardCheck].
- Экстеншены в [forward] используются для установки и управления информацией о перенаправлении.
- Экстеншены в [subForwardCheck] используются для проверки статуса перенаправления и вызова соответственно.
- Посмотрите на часть опций в контексте [forward]. Этот раздел касается пользовательских функций, которые упоминались ранее:
same => n(set-status-on),Set(FWD_UPDATE_STATUS(${DeviceName})=1)
same => n,Playback(forward-on&auth-thankyou&goodbye)
same => n,Hangup()
- Когда диалплан дойдет до выполнения этих экстеншенов, Астериск выполнит одну из пользовательских функций —
UPDATE_STATUS
.
Заметьте, что имя начинается с указанного в func_odbc.conf префикса FWD_
. Если префикс не был указан, необходимо использовать стандартный ODBC_
.
- Переменная “
DeviceName
” будет ссылаться на${ARG1}
внутри команды SQL, установленной для этой функции. - Цифра 1 будет использоваться как
${VAL1}
внутри команды SQL, установленной для этой функции.
[UPDATE_STATUS]
prefix=FWD
synopsis=Changes the forwarding satus of the calling device.
dsn=features_odbc
writesql=UPDATE user_call_forwarding SET status = "${VAL1}" WHERE device = "${ARG1}"
- Вы можете предположить, что произойдет при выполнении этой секции диалплана?
- Она установит статус переадресации звонящего девайса на “1” в БД.
- Когда пользовательская функция выполнится, БД незамедлительно обновит свои записи.
- Чтобы сделать extensions.conf-odbc-forward доступным из вашего диалплана, откройте /etc/asterisk/extensions.conf и раскомментируйте эту строку:
#include extensions.conf-odbc-forward
- Теперь подключите контекст [forward] в контексте [features]:
include => forward
- Наконец, вам надо изменить содержимое
GoSub
для звонков на внутренние номера.- Добавьте эту строку с первичным приоритетом вашего
[subDialer]
:exten => begin,1,GoSub(subForwardCheck,s,1(${ARG1}))
- Также добавьте эту переменную в глобальную область видимости:
- Добавьте эту строку с первичным приоритетом вашего
[globals]
LoopDetect=0
- Посмотрите на контекст [subForwardCheck] в extensions.conf-odbc-forward:
- Здесь проверяется статус переадресации - включена или выключена. Если значение 1, то вызов проходит с перенаправлением, если 0 - вызов проходит как обычно.
Проделанная работа
- Создана БД и таблица для хранения информации о переадресации звонков.
- Настроен /etc/odbc.ini для использования драйвером Linux новой БД.
- Настроен /etc/asterisk/res_odbc.conf для связи Астера с БД.
- Настроены пользовательские функции в func_odbc.conf.
- Настроен диалплан для использования этих функций.
В консоли Asterisk наберите reload
и наблюдайте что-то похожее:
NOTICE[10145]: res_odbc.c:617 load_odbc_config: Registered ODBC class 'features_odbc' dsn->[asteriskfeatures]
- Вы также должны увидеть, что пользовательские функции были загружены из модуля func_odbc:
== Registered custom function 'ODBC_FETCH'
== Parsing '/etc/asterisk/func_odbc.conf':
== Found
== Registered custom function 'FWD_CHECK_EXISTS'
== Registered custom function 'FWD_FORWARD_SETUP'
== Registered custom function 'FWD_CHECK_STATUS'
== Registered custom function 'FWD_UPDATE_STATUS'
== Registered custom function 'FWD_UPDATE_NUMBER'
== Registered custom function 'FWD_GET_NUMBER'
== Registered custom function 'SQL_ESC'
Loaded func_odbc.so => (ODBC lookups)
Проверка переадресации вызовов
Убедитесь, что у вас открыто два терминала: один, подключенный к Астеру, а второй — к БД.
1 сценарий: переадресация на внутреннее устройство Это часто используется, когда вы работаете в другой части здания и хотите получать звонки из своего офиса на ближайший телефон:
- В терминале с коннектом к БД введите:
SELECT * FROM user_call_forwarding
- На данный момент ваша таблица пустая (empty).
- Позвоните с аналогового телефона на номер 9000.
- Когда вам будет предложено ввести экстеншен для переадресации, введите 7001 (Digium телефон).
- Астер будет считывать ваш ввод - нажмите 1.
- Теперь снова введите в терминале с БД команду
SELECT * FROM user_call_forwarding
и наблюдайте результат:
+------+-----------+------------+---------+
| id | device | fwd_number | status |
+------+-----------+------------+---------+
| 1 | DAHDI/1 | 7001 | 1 |
+------+-----------+------------+---------+
- Звонки, адресованные на аналоговый телефон, будут перенаправлены на ваш Digium телефон.
- Теперь позвоните с Zoiper на 7003 и убедитесь, что переадресация работает.
- С аналогового телефона позвоните 9000 снова и отключите переадресацию.
- Теперь посмотрите в таблицу БД
SELECT * FROM user_call_forwarding;
:
+------+-----------+------------+---------+
| id | device | fwd_number | status |
+------+-----------+------------+---------+
| 1 | DAHDI/1 | 7001 | 0 |
+------+-----------+------------+---------+
- Заметьте, что статус изменился на “0” - переадресация отключена.
- Позвоните на номер 7003 с Zoiper или Digium телефона и убедитесь, что аналоговый телефон принимает звонки.
Сценарий 2: переадресация звонков с внешнего номера (мобильный или домашний телефоны) Это самый наиболее распространенный способ. Эта лабораторная не рассчитана для звонков на реальные телефонные номера, поэтому вы будете использовать эмуляцию.
- Наберите с аналогового телефона 9000.
- Вам будет предложено сохранить ваш старый номер или ввести новый — нажмите 2, чтобы ввести новый.
- Наберите номер 61ХХ7001,
- где ХХ - номер вашей рабочей станции.
- Астер считает ваш введенный номер, далее нажмите 1 для подтверждения.
- Снова обратимся к консоли с БД, введя
SELECT * FROM user_call_forwarding;
:
+------+-----------+------------+---------+
| id | device | fwd_number | status |
+------+-----------+------------+---------+
| 1 | DAHDI/1 | 61017001 | 1 |
+------+-----------+------------+---------+
- Новый номер переадресации сохранился и статус изменился на “1”.
- Любые вызовы, приходящие на аналоговый телефон, будут направлены на Digium телефон, который выступает в роли мобильного или домашнего телефона.
- Теперь позвоните 7003 с Zoiper - убедитесь, что звонки приходят на Digium телефон.
- С аналогового телефона позвоните на 9000 снова, чтобы отключить перенаправление и снова посмотрите таблицу в БД командой
SELECT * FROM user_call_forwarding;
:
+------+-----------+------------+---------+
| id | device | fwd_number | status |
+------+-----------+------------+---------+
| 1 | DAHDI/1 | 61017001 | 0 |
+------+-----------+------------+---------+
- Позвоните на 7003 с Gigium телефона или Zoiper, чтобы убедиться в готовности аналогового телефона принимать вызовы в штатном режиме.\
15. CDR
- Изучить формат CDR.
- Создать пользовательский CDR, используя
CDR()
и cdr_custom.conf. - Посмотреть размещение CDR.
- Управлять CDR посредством функций CALLERID(), NoCDR и CDR().
Call Detail Records (CDR) - детализированные записи звонков содержат историю вызовов. Информация, содержащаяся в записях включает в себя сами звонки, а также продолжительность вызова. CDR часто используется для биллинга, а также для решения проблем и статистики. В этой простой лабораторной вы настроите CDR для записи в файл, используя cdr.conf и cdr-custom.conf. Старое приложение CDR, app_cdr.so, уже скомпилировано для вашей системы, но не входит в состав ядра Asterisk, начиная с 13 версии. Оно включено сюда для обратной совместимости. По окончани, вы сделаете звонок и проанализируете запись, созданную Астером.
Шаг 1: обзор CDR формата
Формат .csv записанного файла представляет собой список значений, перечисленных через запятую и выглядит примерно вот так:
"","7002","8001","phones","""Jane Jones <7002>""
<7002>","PJSIP/700200000000","","Playback","democongrats","20150804
14:45:36","20150804 14:45:36","20150804
14:45:43",6,6,"ANSWERED","DOCUMENTATION","1438699536.1",""
Значения соответствуют следующим полям:
<accountcode>,<src>,<dst>,<dcontext>,<clid>,<channel>,<dstchannel>,
<lastapp>,<lastdata>,<start>,<answer>,<end>,<duration>,<billsec>,
<disposition>,<amaflags>,[,<uniqueid>][,<userfield>]
accountcode
: какой номер аакаунта используется, (текстовый, 20 символов).src
: Caller*ID number (текстовый, 80 символов).dst
: назначение (текстовый, 80 символов).dcontext
: назначение контекста (текстовый, 80 символов).clid
: Caller*ID с текстом (80 символов).channel
: используемый канал (80 символов).dstchannel
: назначение соответствующщего канала (80 символов).lastapp
: последнее соответствующее приложение (80 символов).lastdata
: последние данные приложения (аргументы) (80 символов).start
: начало звонка (дата/время).answer
: ответ на звонок (дата/время).end
: завершение звонка (дата/время).duration
: общее продолжительность, в секундах (целочисленное), с момента ответа до окончания.billsec
: общее время звонка, в секундах (целочисленное), с момента ответа до окончания.disposition
: что произошло с вызовом: ANSWERED, NO ANSWER, BUSYamaflags
: какие флаги использовать: DOCUMENTATION, BILL, IGNORE etc, specified on a per channel basis like accountcode.uniqueid
: уникальный идентификатор канала (32 символа).user field
: пользовательское поле, максимум 255 символов.
Шаг 2: обзор содержимого /var/log/asterisk/cdr-csv/Master.csv
Откройте /etc/asterisk/cdr.conf текстовым редактором.
- Убедитесь, что эти настройки не закомментированны:
[csv]
usegmtime=yes ; log date/time in GMT. Default is "no"
loguniqueid=yes ; log uniqueid. Default is "no"
loguserfield=yes ; log user field. Default is "no"
accountlogs=yes ; create separate log file for each account code. Default is "yes"
- Закройте файл и перейдите в консоль Asterisk. Убедитесь, что Астер распознает csv, введя
cdr show status
Среди зарегистрированных, вы должны увидеть список для csv. - Откройте файл /var/log/asterisk/cdr-csv/Master.csv
Примечание: если вы еще не совершали звонков, то этого файла не будет. Если CDR включен, файл будет сгенерирован Астером автоматически, когда будет совершен вызов.
- CDRs будут размещены, если в секции [csv] файла cdr.conf и есть хотя бы один параметр: “usegmtime”, “loguniqueid”, “loguserfield”, “accountlogs”.
Где шаг 3??
Шаг 4: размещение новых запией звонков
Для выполнения этой лабораторной будет удобно держать под рукой 3 вкладки в терминале: первую - с консолью Астера, вторую - с Linux Shell, третью - для открытия и редактирования файлов.
- В терминале Linux запустите:
tail -f /var/log/asterisk/cdr-csv/Master.csv
для мониторинга изменений в режиме реального времени
Примечание: до совершения вызова, несколько раз нажмите “enter”, чтобы визуально отделять новые записи от старых. Для остановки процесса tail, нажмите комбинацию “ctrl”+“c”.
- В следующем терминале откройте файл extensions.conf вашим текстовым редактором:
- Расскомментируйте строчку
#include extensions.conf-cdr
- Включите [cdr] в контекст [features].
- Перезагрузите диалплан.
- Расскомментируйте строчку
- Позвоните на 8001. В первом терминале наблюдайте, как появляются новые записи после окончания вызова:
"","7001","8001","outbound","""7001"" <7001>","PJSIP/7001-00000000","",
"Playback","demo-congrats","2017-02-27 10:21:47","2017-02-27 10:21:47",
"2017-02-27 10:21:49",2,2,"ANSWERED","DOCUMENTATION","1488190907.0",""
- В CLI Астера наберите:
dialplan show 8010@features
- Позвоните на 8010 и наблюдайте вывод tail - ничего не происходит, но в консоли Астера выводится информацию о текущем вызове. CDR не отразился, когда вызов был завершен - почему?
- Перезвоните на 8010. Когда вызов активен, напишите в консоли астера
core show channel PJSIP <tab для продолжения>
и нажмите “enter”. Переменные CDR отобразились в терминале. - Сравните поведение c каналом, когда идёт разговор: наберите 8001 и аналогичным методом посмотрите на доступные данные канала.
Шаг 5: управление CDRs
- В CLI Астера наберите:
dialplan show 8011@features
- Смотрите, как CALLERID() функция используется для изменения CID.
- Сделайте звонок на 8011:
- Смотрите в терминал с tail после завершения вызова и сравните различия (вы должны увидеть, что поле cid изменилось на “Jack Black <2564286000>”).
- В следующем терминале откройте extensions.conf-cdr и расскомментируйте приоритет в экстеншене 8011 строку:
same => n,NoCDR()
- Сохраните и перезагрузите диалплан.
- Выполните
dialplan show
в CLI Астера для подтверждения изменений.
- Сделайте звонок на 8011 и посмотрите на вывод tail - нет никаких запией о CDR.
- В терминале Asterisk наберите
core show function CDR
и обратите внимание на синтаксис, используемый для управления полем “amaflags” CDR. - Откройте extensions.conf-cdr:
- Закомментируйте строку
NoCDR()
- Раскомментируйте строку, отвечающую за поле “amaflags”.
- Закомментируйте строку
;same => n,NoCDR()
same => n,Set(CDR(amaflags)=BILLING)
- Сохраните и перезагрузите диалплан.
- Запустите
dialplan show 8011@features
в CLI Астера для подтверждения изменений. - Позвоните на 8011. Наблюдайте в tail размещение записи CDR при завершении вызова и сравните различия (вы должны увидеть поле “amaflags”, принявшее значение “BILLING”).
Настройка пользовательского CDR
- Откройте cdr_custom.conf:
- Расскомментируйте секцию “mappings” и добавьте строку ”,${CDR(custom-field)}” в конец Master.csv, если её там нет:
[mappings]
Master.csv => ${CSV_QUOTE(${CDR(clid)})},
${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},
${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},
${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},
${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},
${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},
${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},
${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},
${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},
${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)},
${CDR(custom-field)}
- Сохраните и перезагрузите cdr_custom.so в CLI Asterisk:
module reload cdr_custom.so
- Откройте extensions.conf-cdr и расскомментируйте в экстеншене 8011 строку, использующую функцию CDR() для установки значения переменной “custom-field”. Можете написать сюда всё, что угодно:
same => n,Set(CDR(custom-field)=<I will take the world!!!>)
- Сохраните и перезагрузите диалплан.
- Запустите в консоли Астера
dialplan show
- В терминале с tail остановите процесс для /var/log/asterisk/cdr-csv/Master.csv, нажав”ctrl + С”, затем сделайте звонок для создания нового файла /var/log/asterisk/cdr-custom/Master.csv
- Астер не создаст пользовательский CDR лог файл, пока не завершится первый звонок после перезагрузки модуля. После тестового звонка снова запустите tail для наблюдения изменений в новом файле:
tail -f /var/log/asterisk/cdr-custom/Master.csv
- Позвоните на 8011. Снова наблюдайте за выводом, замечая различия - вы должны увидеть ваше грозное сообщение о намерениях захватить мир:
- Астер не создаст пользовательский CDR лог файл, пока не завершится первый звонок после перезагрузки модуля. После тестового звонка снова запустите tail для наблюдения изменений в новом файле:
"""Jack Black"" <2564286000>","2564286000","8011",
"outbound","PJSIP/7001-0000000f","","Hangup","",
"2017-02-27 14:30:58","2017-02-27 14:30:58",
"2017-02-27 14:30:59","0","0","ANSWERED",
"BILLING","","1488195058.73","",15,
<I will take the world!!!>
Пример вашей конфигурации
extensions.conf
[features]
...
include => cdr
extensions.conf-cdr
[cdr]
exten => 8010,1,NoOp(This call is started)
same => n,Wait(3)
same => n,NoOp(Call is ending now)
same => n,Hangup()
exten => 8011,1,Answer()
same => n,NoOp(Old CALLERID is ${CALLERID(all)})
same => n,Set(CALLERID(all)=Jack Black<2564286000>)
same => n,NoOp(New CALLERID is ${CALLERID(all)})
;same => n,NoCDR()
;same => n,Set(CDR(amaflags)=BILLING)
;same => n,Set(CDR(custom-field)=<I will take the world!!!>) ;Part of optional Lab
same => n,Hangup()
cdr_custom.conf
[mappings]
Master.csv => ${CSV_QUOTE(${CDR(clid)})},
${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},
${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},
${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},
${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},
${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},
${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},
${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},
${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},
${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)},
${CDR(custom-field)}
cdr.conf
[general]
[csv]
usegmtime=yes ; log date/time in GMT. Default is "no"
loguniqueid=yes ; log uniqueid. Default is "no"
loguserfield=yes ; log user field. Default is "no"
accountlogs=yes ; create separate log file for each account code. Default is "yes"
16. CDR Adaptive ODBC
- Организовать хранение CDR в реляционной БД и взаимодействие с Asterisk.
Шаги
- Использовать ODBC, используемый в предыдущий лабораторных работах.
- Настроить Астер для использования ODBC и CDR .
- Создать таблицу CDR в MySQL.
- Сделать тестовый звонок и убедиться, что записи попали в базу.
Конфигурация Asterisk + ODBC
- В предыдущих лабораторных вы настроили соединение ODBC и MySQL.
- Дальнейшие инструкции не будут выполнены, если нет соединения! Убедитесь, что предшествующие задания успешно выполнены.
- Для удобства откройте 2 терминала: с консолью БД и Asterisk.
- В исходниках Астера также имеются скрипты Alembic для базы с CDR.
- Конфигурационные файлы: res_odbc.conf, odbc.ini и cdr_adaptive_odbc.conf.
Настало время перейти к настройке!
- Откройте /etc/odbc.ini и убедитесь, что секция [asteriskCDR] не закомментированна:
[asteriskCDR]
Description = MySQL Connection to 'asterisk' database
Driver = MySQL
Server = localhost
Port = 3306
Database = cdr
UserName = root
Password = password
Socket = /var/lib/mysql/mysql.sock
Charset = utf8
- Откройте /etc/asterisk/res_odbc.conf и убедитесь, что нижеуказанная секция также не закрыта комментариями:
[asteriskCDR]
enabled => yes
dsn => asteriskCDR
username => root
pasword => password
share_connections => yes
sanitysql => select 1
pre-connect => yes
- Откройте /etc/asterisk/cdr_adaptive_odbc.conf и напишите в начале файла следующие строки:
[basiccdr]
connection=asteriskCDR
table=cdr
alias src => source
alias channel => source_channel
alias dst => dest
alias dstchannel => dest_channel
Сохраните файл и закройте. Перезагрузите Asterisk.
- Создайте базу из терминала Linux:
- Залогиньтесь в БД -
mysql -u root -p
- Создайте новую базу с именем “cdr” -
create database cdr;
- Выбор новой базы -
use cdr
- Залогиньтесь в БД -
- Переключитесь на другой терминал. Теперь настройте доступ скриптам SQLAlchemy и Alembic к вашей БД:
- Перейдите в директорию:
cd /usr/src/asterisk-13.13.0/contrib/ast-db-manage
- Скопируйте файл:
cp cdr.ini.sample config.ini
- Откройте config.ini текстовым редактором и найдите строчку, отвечающую за соединение с базой, и измените её на
sqlalchemy.url = mysql://root:password@localhost/cdr
- Сохраните и закройте файл.
- Перейдите в директорию:
- Используем Alembic для создания таблиц:
- Перейдите в директорию:
cd /usr/src/asterisk-13.13.0/contrib/ast-db-manage
- Выполните в терминале:
alembic -c config.ini upgrade head
- Перейдите в директорию:
- Переключитесь на терминал с БД или залогиньтесь, если закрыли его -
# mysql -u root -p -D cdr
и теперь посмотрите существующие таблицы:
MariaDB [cdr]> show tables;
+---------------------+
| Tables_in_cdr |
+---------------------+
| alembic_version_cdr |
| cdr |
+---------------------+
2 rows in set (0.01 sec)
Вы должны видеть таблицу cdr. Если выполнить SELECT * FROM cdr
, то получите пустой результат - таблица ещё не заполненна данными, потому что не было совершено тестового звонка после настройки.
- Позвоните на 8001. После того, как как вызов будет завершен, CLI Asterisk не покажет ничего происходящего касательно вашей конфигурации.
- Проверьте БД:
SELECT * FROM cdr;
- Если вывод получился беспорядочным и не читабельным, используйте
SELECT Accountcode,channel,start,end,lastapp,uniqueid from cdr;
- Если вывод получился беспорядочным и не читабельным, используйте
Процесс соединения можно изобразить так: cdr_odbc → res_odbc → odbc.ini
cdr_odbc не соединяется напрямую c odbc.ini
- Если CDR так и не появились в БД, вы увидите пустую таблицу. Возможные варианты решения проблем:
- Проверьте конфигурацию ещё раз.
- Перезагрузите Астер.
- Поклонитесь преподавателю и любезно попросите помощи - он обязательно вам поможет!
17. CEL Basics
- Посмотреть конфигурацию CEL.
- Узнать различия между CEL и CDR.
Обзор CEL
CEL — Channel Event Logging (логирование событий канала). Такой подход является усовершенствованным и более продвинутым относительно CDR, который используется в более простых системах. CDR, как правило, создает одну запись на звонок - это удобно и просто. Но когда возникает необходимость отслеживать и записывать звонки, где используется парковка вызова или удержание, на помощь как раз и приходит CEL, который регистрирует каждое событие на канале, создавая несколько записей на один звонок. Повышенная точность достигается засчёт более крупных и сложных файлов.
Так что же использовать: CDR или CEL? Все зависит от необходимых требований, задач и возможностей. Если требуется обычное ведение записи, то CDR вполне подойдет. Для более продвинутого управления записанными вызовами, анализа ведения статистики используется CEl.
Шаг 1: обзор конфигурации CEL
Также как и CDR, CEL может использовать различные движки, такие как csv, odbc, AMI и RADIUS. В отличие от CDR, у CEL нет базового модуля “cel-csv.so”, поэтому вы будете настраивать модуль cel_custom.so через cel_custom.conf
- Откройте cel.conf и расскомментируйте базовые настройки:
[general]
enable=yes
apps=dial,park
events=APP_START,CHAN_START,CHAN_END,ANSWER,HANGUP,BRIDGE_ENTER,BRIDGE_EXIT
- Три описанных значения необходимы для логирования событий:
- “enable” - должен принимать параметр “yes”. +. “apps” - должен содержать список приложений, который вы хотите отслеживать. +. “events” - долэен принимать список событий для их отслеживания.
Более подробные детали можно посмотреть в файле cel.conf.sample
- Сохраните и закройте файл cel.conf и откройте cel_custom.conf:
- Убедитесь, что секция “mappings” не закомментированна.
Различные функции диалплана в строке указывают, что необходимо хранить как CEL запись. Каждая из них обернута в функцию CSV_QUOTE, так что встроенные кавычки записаны должным образом. Многие функции знакомы вам уже по CDR, но имеются некоторые различия.
- Сохраните и закройте cel_custom.conf.
- Перезагрузите cel и cel_custom.so в CLI Asterisk:
module reload cel
module reload cel_custom.so
- Сделайте звонок для создания Master.csv.
Шаг 2: тестирование CEL
- Откройте, как обычно, 3 вкладки с терминалом для удобства.
- В первом терминале запустите
# tail -f /var/log/asterisk/cel-custom/Master.csv
- Во втором терминале -
tail -f /var/log/asterisk/cdr-csv/Master.csv
- Позвоните на 7001 с Zoiper и переведите вызов на 8001:
- Заметьте, что CDR записи передаются с параметрами “duration” и “billsec”, когда вызов всё ещё активен.
- Несколько записей CEL были размещены, несмотря на созданный файл CDR.
- Повесьте трубки и убейте процессы tail в двух терминалах, нажав “ctrl+c”.
Пример вывода
- CDR:
"","7001","8001","outbound","""7001"" <7001>","PJSIP/7001-00000005","",
"Playback","demo-congrats","2017-02-28 05:18:11","2017-02-28 05:18:11",
"2017-02-28 05:18:12",0,0,"ANSWERED","DOCUMENTATION","1488259091.28",""
- CEL:
"CHAN_START","1488258575.607759","7001","7001","","","","8001","outbound",
"PJSIP/7001-00000004","","","3","","1488258575.22","1488258575.22","","",""
"ANSWER","1488258575.613040","7001","7001","7001","","","8001","outbound",
"PJSIP/7001-00000004","Playback","demo-congrats","3","","1488258575.22",
"1488258575.22","","","""HANGUP","1488258576.751149","7001","7001","7001",
"","","8001","outbound","PJSIP/7001-00000004","","","3","","1488258575.22",
"1488258575.22","","","{""hangupcause"":16,""hangupsource"":""PJSIP/7001-00000004"",
""dialstatus"":""""}""CHAN_END","1488258576.755372","7001","7001","7001","","","8001",
"outbound","PJSIP/7001-00000004","","","3","","1488258575.22","1488258575.22","","",""
18. Мониторинг звонков
- Рассмотреть различные механизмы мониторинга в режиме реального времени Asterisk.
ChanSpy()
.ExtenSpy()
.
Мониторинг в режиме реального времени
ChanSpy()
— прослушивает аудио на выбранном канале:
- Опционально имеется возможность “вклиниться” в канал, но прослушивать можно только с одной стороны канала.
- Можно указать префикс канала (SIP, например), для контроля определенного канала.
- Будьте осторожны! Без указанного “chanprefix”, можно прослушивать любой канал.
- Для более подробного изучения, наберите в консоли Астера
core show application chanspy
ExtenSpy()
— прослушивает аудио на канале с определенным экстеншеном:
- Очень похожая функциональность, как и в
ChanSpy()
. - Менее безопасна, чем
ChanSpy()
. - Можно указать, чтобы прослушивать только те экстеншены, которые вызывают очереди.
Простая демонстрация ChanSpy()
- Класс будет разделен на 2 группы:
- Одна половина присоединится к конференции на сервере.
- Другая половина вызовет ChanSpy() для прослушивания.
- Сервер в классе имеет следующий диалплан:
...
exten => _6X990002,1,Answer()
same => n,ChanSpy()
same => n,Hangup()
- Если ваша рабочая станция четная, наберите 61990001 (или 63990001) для соединения с конференцией (вспомните одну из лабораторных). Каждый может разговаривать друг с другом.
- Если ваша рабочая станция нечетная, наберите 61990002 (или 63990002) для выполнения
ChanSpy()
, указанного в диалплане сервера. Вы сможете слушать участников конференции, но они вас — нет:- Нажмите ”*” на клавиатуре телефона для переключения на другой канал, если вы ничего не слышите.
- После этого поменяйтесь ролями: теперь другая половина класса заходит в конеренцию, а другая — шпионит.
19. AstDB
- Научиться работать с AstDB.
- Оценить простоту использования AstDB.
- Реализовать функцию «личный менеджер».
- Внутренние абоненты обзванивают клиентов, то есть звонят «в город» на разные номера.
- Все вызовы «в город» уходят с единого городского номера компании — 61XX7200.
- Иногда менеджер не дозванивается до клиента, и клиент позже перезванивает обратно на номер компании.
- Нужно сделать так, что бы клиент сразу попал на менеджера, который ему звонил ранее.
Подготовка
Начнем с того, что заменим realtime конфигурацию обратно на конфигурацию из файлов:
- Раскомментируйте то, что закомментировали в pjsip.conf ранее.
- Закомментируйте ваши изменения в extconfig.conf.
- Перезапустите Asterisk.
Эти шаги переключат Asterisk обратно на использование SIP пиров из файла pjsip.conf. Так будет проще изменять опции SIP аккаунтов.
Далее, для того, что бы выполнялось условие “Все вызовы в город уходят с единого городского номера компании — 61XX7200”, нужно в endpoint секцию [server-trunk] добавить: from_user=61017200
После изменений перезагрузите pjsip и сделайте тестовый звонок, чтобы убедиться, что это условие выполняется.
Создайте тестовую запись в AstDB
Нам нужно продумать, в каком виде хранить значения в AstDB. Когда из города будет поступать входящий звонок, мы будем выполнять поиск в базе по callerid номеру. Значит, частью ключа должен быть номер звонящего. Хранить свои ключи будем внутри Family, например, last_caller. Для начала внесем в базу первое значение вручную, из CLI:
*CLI> database put last_caller 61YY7200 7002
Updated database successfully
*CLI> database show
...
/last_caller/61YY7200 : 7002
- 61YY7200 — это внешний номер, на который якобы звонил абонент вашей АТС с внутренним номером 7001.
- Вместо YY в данной лабораторной нужно указать номер станции вашего коллеги, который будет потом вам звонить для проверки
- Для Asterisk “last_caller/61YY7200” - это ключ, а “7001” - его значение.
Диалплан, выполняющий поиск по AstDB
Все звонки, приходящие на ваш “единый” номер попадают к вам от оператора на 7200@inbound. Именно здесь нужно добавить поиск по AstDB, и если запись найдена, то вместо IVR вызов нужно перенаправить на внутреннего абонента (личого менеджера):
exten => 7200,1,NoOp(===== CALLERID(num) is equal ${CALLERID(num)})
same => 2,Set(private_manager=${DB(last_caller/${CALLERID(num)})})
same => 3,GoToIf(${private_manager}?phones,${private_manager},1:ivr,s,1)
- Выводим в CLI номер звонящего.
- Ищем в AstDB ключ last_caller/${CALLERID(num)} и присваиваем его значение переменной private_manager. Если значение в базе не найдено, переменная
private_manager
будет пустой - В команде GoToIf осуществляем условный переход:
- По условию true мы переходим на phones,${private_manager},1.
- По условию false мы переходим на ivr,s,1.
Обратите внимание, что пустое значение знаком ”?” в команде GoToIf() расценивается как false. Любое значение, кроме нуля и пустой строки, расценивается как true. Попросите вашего коллегу со станции YY набрать вас на номер 61XX7200. К вам придет вызов на номер 7200:
-- Executing [7200@inbound:1] NoOp("PJSIP/server-trunk-00000000", "===== CALLERID(num) is equal 61017200") in new stack
-- Executing [7200@inbound:2] Set("PJSIP/server-trunk-00000000", "private_manager=7002") in new stack
-- Executing [7200@inbound:3] GotoIf("PJSIP/server-trunk-00000000", "7002?phones,7002,1:ivr,s,1") in new stack
-- Goto (phones,7002,1)
-- Executing [7002@phones:1] Dial("PJSIP/server-trunk-00000000", "PJSIP/7002") in new stack
-- Called PJSIP/7002
-- PJSIP/7002-00000001 is ringing
Отлично! Переадресация сработала. Осталось дело за малым: автоматически добавлять значения в AstDB во время исходящих вызовов.
Диалплан, выполняющий запись в AstDB
Установить автоматическое обновление базы AstDB:
- Номер абонента должен быть значением ключа, который нам нужно сохранить, перед тем, как отправить звонок в город.
- Если у вас имя endpoint секции внутреннего абонента не совпадает номером абонента, вы можете воспользоваться опцией callerid.
- Набранный номер должен использоваться в имени ключа.
[outbound]
exten => _61XXXXXX,1,Set(DB(last_caller/${EXTEN})=${CALLERID(num)})
same => n,Dial(${SIPTrunk}/${EXTEN})
Проверка
- Отправьте вызов на номер 61YY7200 с телефона 7002:
-- Executing [61017200@outbound:1] Set("PJSIP/7002-0000000a", "DB(last_caller/61017200)=7002") in new stack
-- Executing [61017200@outbound:2] Dial("PJSIP/7002-0000000a", "PJSIP/61017200@server-trunk") in new stack
- Наблюдайте изменения базы данных:
*CLI> database show
- Попросите коллегу со станции YY набрать нас на 61XX7200 и наблюдайте звонок в консоли:
-- Executing [7200@inbound:1] NoOp("PJSIP/server-trunk-0000000c", "===== CALLERID(num) is equal 61017200") in new stack
-- Executing [7200@inbound:2] Set("PJSIP/server-trunk-0000000c", "private_manager=7002") in new stack
-- Executing [7200@inbound:3] GotoIf("PJSIP/server-trunk-0000000c", "7002?phones,7002,1:ivr,s,1") in new stack
-- Goto (phones,7002,1)
-- Executing [7002@phones:1] Dial("PJSIP/server-trunk-0000000c", "PJSIP/7002") in new stack
- Сработала переадресация на номер 7001.
- Потом снова наберите номер 61YY7200 уже с телефона 7002. Обратный вызов после этого должен попасть на абонента 7002.
Попробуйте также позвонить на станции других студентов на номера 61ZZ7200 с разных телефонов. Все будут видеть ваш “единый” номер в качестве callerid. А при обратном звонке на этот номер они будут попадать именно на того внутреннего абонента, который им ранее звонил.
Дополнительное задание
Добавьте в крон задачу по удалению из базы данных Астериска все записи в family “last_caller” каждую ночь.
20. Twitter Python AGI
- Использовать AGI интерфейс Asterisk.
- Получить представления о возможностях связки Asterisk с внешними программами.
Зависимости:
- Python 2.7 & setuptools.
- Pyst 0.6.5 – Asterisk AGI Python Library.
- Tweepy 2.1 – Twitter Python Library.
- AGI скрипт “agi_tweet.py”, который должен находиться в “/var/lib/asterisk/agi-bin/“
Все из вышеперечисленного уже установлено на лабораторном сервере, но вам понадобится установить все самостоятельно, чтобы повторить на другом сервере.
Обзор AGI скрипта
- Откройте /var/lib/asterisk/agi-bin/agi_tweet.py:
# cd /var/lib/asterisk/agi-bin/
.# gedit agi_tweet.py &
.
- Внимательно прочтите весь скрипт.
- Строчки, начинающиеся с решетки (#) - это комментарии. Даже если вы не знаете Python вы можете понять как работает скрипт из комментариев.
- Обратите внимание, что скрипт использует функцию “get_variable” чтобы получить переменную “status”.
- Скрипт так же использует функцию “set_variable”, чтобы установить переменную диалплана “tweet_success”.
- Обе из этих переменных уровня канала вы используете в вашем диалплане.
Обновите диалплан
Откройте extensions.conf и добавьте экстеншен 8401 в контекст [features]:
- Устанавливаем переменную “status” равную сообщению, которое будет отправлено в Твиттер.
- Вызываем agi скрипт — AGI(agi_tweet.py).
- В зависимости от значения переменной “tweet_success” проигрываем сообщение об успехе или об ошибке.
- Завершаем вызов.
exten => 8401,1,NoOp("Post to twitter via AGI")
same => n,Set(status="Your custom message here!")
same => n,AGI(agi_tweet.py)
same => n,Playback(${IF(${tweet_success}?demo-congrats:tt-somethingwrong)})
same => n,Hangup()
Тестируем AGI
- dialplan reload.
- Звоним! Набираем 8401 с любого нашего телефона.
- Наблюдаем в CLI результат.
- В случае успеха вы должны заметить строчку:
agi_tweet.py: SUCCESS!
А также ссылку на ваш твит. Скопируйте ее и вставьте в браузер чтобы открыть на сайте Твиттера. - Вы можете прочитать твиты всех остальных на странице Твиттер аккаунта.
Вопросы
- Что случится, если вы попытаетесь запостить одно и то же сообщение дважды? Почему?
- Как вы могли бы увидеть сообщение об ошибке от Твиттер сервера в Asterisk CLI? А сообщение о синтаксической ошибке скрипта?
- Этот пример — просто демонстрация возможностей AGI. Какие другие примеры вы можете придумать?
Дополнительное задание
- Включите дебаг AGI:
pc1*CLI> agi set debug on
AGI Debugging Enabled
- Отправьте очередной твит.
- Обратите внимание на строчки Rx и Tx.
- Найдите связь между функциями библиотеки agi (get_variable, verbose, set_variable) и debug сообщениями AGI интерфейса.