# Глава 11. Функции АТС, включая парковку, пейджинг и конференц-связь

> _Я не верю в ангелов, нет. Но у меня есть крошечный парковочный ангел. Он у меня на приборной панели, и ты его заводишь. Крылья хлопают, и это должно дать вам место для парковки. Это работало до сих пор._
>
> -- Билли Коннолли

В этой главе рассматриваются некоторые периферийные функции, общие для бизнес-телефонных сред. Мы кратко рассмотрим  файл _features.conf_, а затем посвятим несколько разделов пейджингу и парковке и, наконец, немного поработаем с механизмом конференц-связи Asterisk - `confbridge`.

Во-первых, давайте скопируем файл _features.conf_ из каталога установки и рассмотрим его:

```text
$ sudo cp ~/src/asterisk-16.<TAB>/configs/samples/features.conf.sample \
/etc/asterisk/features.conf
$ sudo chown asterisk:asterisk /etc/asterisk/features.conf
```

## features.conf

Asterisk предоставляет несколько функций, общих для большинства УАТС, многие из которых имеют необязательные параметры. Файл *features.conf* - это место, где вы можете настроить или определить различные параметры объектов в Asterisk.

---
**Функции на основе DTMF**

Многие параметры в _features.conf_ применяются только при вызовах, которые были совершены с помощью приложений диалплана `Dial()` или `Queue()`, используя один или несколько параметров `k`, `K`, `H`, `h`, `T`, `t`, `W`, `w`, `X` или `x`. Функции доступны путем передачи DTMF-сигналов (т.е. они не могут быть доступны через SIP-сообщения, а только в аудиоканале через тональные сигналы, запускаемые пользователями, набирающими необходимые цифры на своих клавиатурах).[1](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406491144)

Трансферы SIP-каналов (например через SIP-телефон) могут быть обработаны с использованием возможностей самого телефона и не будут затронуты файлом `features.conf`.

---
### Раздел [general]

В разделе `[general]` _features.conf_, вы можете определить параметры, которые точно настраивают поведение функции трансфера в Asterisk. Они не имеют ничего общего с тем, как SIP-телефоны обрабатывают трансфер вызовов. Вместо этого вы получаете доступ к этим функциям с помощью DTMF во время вызова (вызов должен быть установлен, поэтому звонящие или выполняющиеся вызовы, не будут иметь доступа к этим функциям).

Пример файла _features.conf.sample_ в папке _~/asterisk/_ содержит подробные сведения о различных параметрах и примеры их установки.

Эти функции не так часто используются как в прошлом, главным образом потому, что многие из этих вещей могут быть обработаны более продвинутыми способами чем набор DTMF с телефонного аппарата (например, через какую-то внешнюю интеграцию или, если на то пошло, с самого телефона, используя свои собственные внутренние функции трансфера).

### Раздел [featuremap]

Раздел `[featuremap]`, приведенный в Таблице 11-1, позволяет определить определенные последовательности DTMF, которые будут запускать функции на каналах, соединенных с помощью опций в приложении `Dial()` или `Queue()`. Два варианта, которые вы, скорее всего, будете использовать, это `parkcall` и `automixmon`.

_Таблица 11-1. features.conf раздел \[featuremap\]_

| Параметр | Значение/пример | Примечание | флаги Dial\(\)/Queue\(\) |
| :--- | :--- | :--- | :--- |
| `blindxfer` | `#1` | Вызывает слепой (неконтролируемый) трансфер | `T, t` |
| `disconnect` | `*0` | Завершает вызов | `H, h` |
| `automon` | `*1` | Запускает запись текущего вызова с помощью приложения Monitor() (повторное нажатие этой последовательности клавиш останавливает запись) | `W, w` |
| `atxfer` | `*2` | Выполняет автоматический трансфер | `T, t` |
| `parkcall` | `#72` | Паркует вызов | `K, k` |
| `automixmon` | `*3` | Запускает запись текущего вызова с помощью приложения MixMonitor() (повторное нажатие этой последовательности клавиш останавливает запись) | `X, x` |

### Раздел [applicationmap]

Раздел `[applicationmap]` в _features.conf_ возможно, является самым изящным, поскольку он позволяет сопоставлять коды DTMF с приложениями диалплана. Вызывающий абонент будет поставлен на удержание, пока приложение не завершит выполнение.

Синтаксис для определения сопоставления приложения выглядит следующим образом (оно должно отображаться в одной строке; разрывы строк недопустимы):[2](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178)

```
Name => DTMF_sequence,ActivateOn[/ActivatedBy],App([Args])[,MOH_Class]
```

То, что вы делаете, заключается в следующем:
1. Присвоение сопоставлению имени, позволяющему включить его в диалплан с помощью переменной канала `DYNAMIC_FEATURES` (подробнее об этом чуть позже).
2. Определение последовательности DTMF, которая активирует эту функцию (мы рекомендуем использовать для этого по крайней мере две цифры).
3. Определение того, на каком канале будет активирована функция и (необязательно) какому участнику разрешено активировать её (по умолчанию обоим каналам разрешено использовать/активировать).
4. Задает имя приложения, которое вызовет это сопоставление, и его аргументы.
5. Предоставление дополнительного класса музыки на удержание (MOH) для назначения этой функции (который будет слышать противоположный канал при выполнении приложения). Если вы не определяете какой-либо класс, вызывающий абонент будет слышать просто тишину.

Вот пример сопоставления приложения, которое вызовет скрипт AGI:[3](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406440184)

```
agi_test => *6,self/callee,AGI(agi-test.agi),default
```

Вы можете добавить это в свой файл _/etc/asterisk/features.conf_ если пожелаете.

---
**ПРИМЕЧАНИЕ**

Поскольку приложения, вызванные сопоставлением приложений, выполняются вне ядра АТС, вы не можете выполнять приложения, запускающие диалплан (например, `Goto()`, `Macro()`, `Background()` и т.д.). Если вы хотите использовать сопоставление приложений для создания внешних процессов (включая выполнение кода диалплана), то вам нужно будет вызвать внешнее приложение через вызов `AGI()` или приложение `System()`. Дело в том, что если вы хотите выполнить что-то сложное с помощью сопоставления приложения, вам нужно будет это очень тщательно протестировать, так как не все будет работать так, как вам хотелось бы.

---
Чтобы использовать сопоставление приложения, вы должны объявить его в диалплане, установив переменную `DYNAMIC_FEATURES` где-то перед командой `Dial()`, оединяющей каналы. Используйте модификатор двойного подчеркивания в имени переменной для гарантии того, что сопоставление приложения будет доступно обоим каналам в течение всего жизненного цикла вызова. Давайте добавим его в нашу подпрограмму `subDialUser`, чтобы он был доступен всякий раз, когда любое из наших расширений вызывает друг друга:

```
[subDialUser]
exten => _[0-9].,1,Noop(Dial extension ${EXTEN},channel: ${ARG1}, mailbox: ${ARG2})
    same => n,Noop(mboxcontext: ${ARG3}, timeout ${ARG4})
    same => n,Set(__DYNAMIC_FEATURES=agi_test)
    same => n,Dial(${ARG1},${ARG4})
    same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
```

---
**ПРИМЕЧАНИЕ**

Если вы хотите, чтобы при вызове было доступно более одного сопоставления приложения, вам нужно использовать символ \# в качестве разделителя между несколькими именами сопоставлений:
```
Set(__DYNAMIC_FEATURES=agi_test#my_other_map)
```
Причина, по которой символ \# был выбран вместо простой запятой, заключается в том, что более старые версии приложения `Set()` интерпретировали запятую иначе, чем более поздние и синтаксис для сопоставления приложений никогда не обновлялся.

---
Не забудьте перезагрузить модуль `features` после внесения изменений в файл *features.conf*:
```
*CLI> module reload features
```
Вы можете проверить что ваши изменения произошли через команду CLI `features show`.

Кроме того, поскольку мы представляем здесь скрипт AGI, есть некоторые команды, которые необходимо выполнить, чтобы сделать упомянутый скрипт AGI доступным для Asterisk.
```
$ sudo cp ~/src/asterisk-16.<TAB>/agi/agi-test.agi /var/lib/asterisk/agi-bin/

$ sudo chown asterisk:asterisk /var/lib/asterisk/agi-bin/*

$ sudo chmod 755 /var/lib/asterisk/agi-bin/*
```
Убедитесь, что вы протестировали сопоставление приложения, прежде чем передать его в пользование своим пользователям!

---
**Динамическое создание сопоставления приложения из диалплана**

Вы можете создавать сопоставления объектов непосредственно из диалплана, делая динамическое определение объекта (и его DTMF) для каждого канала. Это делается с помощью функций набора номеров `FEATURE()` и `FEATUREMAP()`. Допустимые значения для `FEATUREMAP()` включают следующие, устанавливающие или извлекающие последовательность DTMF, используемую для запуска функциональности:

`atxfer`

  Трансфер с уведомлением

`blindxfer`

  Слепой трансфер

`automon`

  Авто `Monitor()` (запись вызовов)

`disconnect`

  Разъединение вызова

`parkcall`

  Парковка вызова

`automixmon`

  Авто `MixMonitor()` (запись вызова)

Функция `FEATUREMAP()` позволяет получить текущую последовательность DTMF для этой функции:
```
exten => 232,1,Noop(Current DTMF for parkcall: ${FEATUREMAP(parkcall)})
```
Или вы можете использовать последовательность DTMF для особой функции на текущем канале:
```
exten => 233,1,NoOp()
    same => n,Set(FEATUREMAP(parkcall)=*9)
    same => n,Noop(DTMF for parkcall now: ${FEATUREMAP(parkcall)})
```
Если вы хотите установить тайм-аут парковки для канала, то можете сделать это с помощью функции `FEATURE()`. Она будет содержать единственный аргумент - `parkingtime`, который является значением в секундах до того, как припаркованный вызов будет возвращен вызывающему абоненту (или месту назначения, в зависимости от того, как вы настроили парковку):
```
exten => 234,1,NoOp()
    same => n,Set(FEATURE(parkingtime)=60)
```
---
### Группировка сопоставлений приложений

Если у вас есть множество объектов, которое необходимо активировать для определенного контекста или расширения, вы можете сгруппировать несколько объектов в группу сопоставлений приложений, чтобы одно назначение переменной `DYNAMIC_FEATURES` назначило все объекты этого сопоставления.

Группировки сопоставлений приложений добавляются в конце файла *features.conf*. Каждой группе присваивается имя, а затем перечисляются соответствующие объекты:
```
[shifteight]
unpauseMonitor => *1    ; пользовательское сопоставление клавиш
pauseMonitor => *2      ; пользовательское сопоставление клавиш
agi_test =>             ; непользовательское сопоставление клавиш
```
---
**ПРИМЕЧАНИЕ**

Если вы хотите задать пользовательское сопоставление клавиш для объекта в группе сопоставления приложения, просто сопоставьте `=>` с нужным сопоставлением клавиш. Если вы не зададите сопоставление клавиш, то для этого объекта будет использоваться сопоставление клавиш по умолчанию (как указано в разделе `[featuremap]`). Независимо от того, хотите ли вы назначить пользовательское сопоставление клавиш или нет, требуется оператор `=>`.

---
В диалплане эту группировку карт приложений можно назначить через приложение `Set()`:
```
same => Set(__DYNAMIC_FEATURES=shifteight) ; используйте двойное подчеркивание,
                                  ; если хотите убедиться, что обе
                                  ; ветви вызова имеют назначенную переменную.
```
## Парковка и пейджинг

Хотя эти две функции полностью отделены друг от друга, они так часто используются вместе, что мы могли бы рассматривать их как одну отдельную функцию.

Парковка вызовов позволяет удерживать вызовы, а затем извлекать их из места, отличного от того, на котором им первоначально ответили. Пейджинг использует систему громкой связи, позволяющую отправлять объявления из телефонной системы (например, чтобы сообщить для кого предназначен припаркованный вызов и как его можно получить).

Некоторые компании, возможно, с большими складами, открытыми площадками или сотрудниками, передвигающимися по офису, используют функции пейджинга и парковки своих систем для прямых звонков по офису. В этой главе мы покажем вам, как использовать парковку и пейджинг в традиционных настройках (park’n’page), а также несколько более современных подходов к этим часто используемым функциям.

### Парковка вызовов

Парковка позволяет удерживать вызов в системе без привязки к определенному добавочному номеру. Затем вызов может быть извлечен любым, кто знает код парковки для этого вызова. Эта функция часто используется вместе с публичным адресом (PA) или системой «пейджинга». По этой причине его часто называют «park-and-page». Следует отметить, что парковка и пейджинг на самом деле разделены. Мы кратко рассмотрим пейджинг, но сначала давайте поговорим о парковке вызовов.

Давайте возьмем копию файла примера, который будем использовать для настройки парковки вызовов:
```
$ sudo cp ~/src/asterisk-16.<TAB>/configs/samples/res_parking.conf.sample \
/etc/asterisk/res_parking.conf

$ sudo chown asterisk:asterisk /etc/asterisk/res_parking.conf

$ sudo asterisk -rx 'module load res_parking.so'
```
Для парковки вызова в Asterisk Вам необходимо перевести вызывающего абонента на код функции, назначенный для парковки в файле *res\_parking.conf* с помощью директивы `parkext`. По умолчанию это `700`:
```
parkext => 700      ; расширение, набираемое для парковки (все слоты парковки)
```
Вам нужно подождать завершения перевода пока вы не получите номер слота поиска парковки из системы, или у вас не будет возможности получить вызов. По умолчанию слоты поиска, назначенные с помощью директивы `parkpos` в _res\_parking.conf_, нумеруются от `701` до `720`:
```
parkpos => 701-720  ; расширения для парковки вызовов (слоты парковки по умолчанию)
```
После того, как вызов припаркован, любой пользователь системы может получить его, набрав номер слота поиска (`parkpos`), назначенного этому вызову. Затем вызов будет соединен с каналом, который набрал код поиска.

Существует два распространенных способа определения назначения слотов поиска. Это делается с помощью директивы `findlot` в файле _res\_parking.conf_. Метод по умолчанию (`findlot => first`) всегда использует слот с наименьшим номером, если он доступен, и назначает коды с более высоким номером только в случае необходимости. Второй метод (`findlot => next`) будет чередовать слоты поиска при каждой последующей парковке, возвращаясь к первому слоту поиска только после того, как использовался последний. Какой метод вы выберете, будет зависеть от того, насколько загружена ваша парковка. Если вы редко пользуетесь парковкой - лучше всего подойдет `findslot` как `first` по умолчанию (люди будут привыкать к тому, что их припаркованные вызовы всегда находятся в одном и том же слоте). Если вы постоянно используете функцию парковки (например, в автосалоне), гораздо лучше для каждой последующей парковки назначать следующий слот, поскольку вы часто будете парковать более одного вызова одновременно. Ваши пользователи привыкнут внимательно слушать фактический номер парковки (вместо того, чтобы просто набирать 701), и это сведет к минимуму вероятность случайного получения неправильного вызова в занятой системе.

---
**Обработка тайм-аутов припаркованных вызовов с опцией comebacktoorigin**

Этот параметр настраивает поведение парковки вызова, когда время ожидания вызова на парковке истекает (см. параметр `parkingtime`). `comebacktoorigin` может иметь одно из двух значений:

`yes` (по умолчанию)

 Когда тайм-аут припаркованного вызова превышен, Asterisk попытается отправить вызов обратно узлу, который совершил этот вызов. Если канал больше недоступен для Asterisk, вызывающий абонент будет отключен.

`no`

 Эта опция будет использоваться если вы хотите выполнить пользовательские функции диалплана для припаркованных вызовов, превысивших тайм-ауты. Вызывающий абонент будет отправлен в определенную область диалплана, где логика может быть применена для изящной обработки оставшейся части вызова (это может включать в себя простой возврат вызова на другой внутренний номер или выполнение какого-либо вида поиска).

Также может потребоваться учитывать вызовы, когда исходный канал не может обработать возвращенный припаркованный вызов. Если, например, вызов был припаркован каналом, который также является транком для другой системы, не будет достаточно информации, чтобы отправить вызов обратно правильному абоненту в той системе. Действия после тайм-аута будут более сложными, чем при `comebacktoorigin=yes`, которые можно обрабатывать изящно.

"Припаркованные вызовы", с параметром `comebacktoorigin=no` всегда будут отправляться в контекст `parkedcallstimeout`.

---
**Примечание**

 Диалплан (и контексты) были подробно рассмотрены в [Главе 6](glava-06.md).

---

Внутренний номер, на который они будут отправлены, будет построен на основе имени канала, который запарковал вызов. Например, если узел SIP-пир с именем `0004F2040808` запарковал этот вызов, добавочный номер будет `SIP_0004F2040808`.

Если это расширение не существует, вместо этого вызов будет отправлен на расширение `s` в контексте `parkedcallstimeout`. Наконец, если расширение `s` в `parkedcallstimeout` не существует, вызов будет отправлен на расширение `s` контекста `default`.

Кроме того, для любых вызовов, где `comebacktoorigin = no` будет добавлено расширение `SIP_0004F2040808`, созданное в контексте `park-dial`. Это расширение будет настроено для `Dial()` на `SIP/0004F2040808`.[4](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html#idm46178406331512)

Если вы используете парковку, вам также понадобится способ объявить о припаркованных вызовах, чтобы пользователи знали как их получить. В то время как вы можете просто бегать по коридору, крича «Боб, тебе звонят по номеру 701!», Более профессиональный метод - использовать систему пейджинга (более формально известную как система громкой связи), которую мы сейчас обсудим.

### Пейджинг (aka Публичное обращение)

Во многих системах УАТС полезно подключить телефонную систему к какой-либо системе громкой связи. Это включает в себя набор кода функции или добавочного номера, который устанавливает соединение с каким-то общедоступным ресурсом, а затем делает объявление через телефонную трубку, которое транслируется на все устройства, связанные с этим ресурсом пейджинга (возможно, вы слышали продавца в каком-либо магазине запрашивающего проверку цены по телефону). Как правило это будет внешняя пейджинговая система, состоящая из усилителя, подключенного к потолочным динамикам; однако, пейджинг через колонки офисных телефонов также популярен (в основном по соображениям стоимости). Если у вас есть бюджет (или существующая система оповещения), система оповещения обычно лучше, но пейджинг на основе телефонных аппаратов также может хорошо работать во многих случаях. Также возможно иметь комбинацию пейджинга на основе аппаратов и потолочного, где, например, пейджинг на основе аппаратов будет использоваться для офисов, а система оповещения - для склада, коридора, парковки и зоны общего пользования (столовая, приемная и т.д.).

В Asterisk для пейджинга используется приложение `Page()`. Это приложение просто принимает список каналов в качестве аргумента, вызывает все перечисленные каналы одновременно и, когда они отвечают, помещает каждый в конференц-зал. Имея это в виду, становится очевидным, что одним из требований работы пейджинга является то, что _каждый канал назначения должен иметь возможность автоматически отвечать на входящее соединение_ и передавать вызов на какой-то динамик (другими словами, `Page()` не будет работать, если все телефоны будут просто звонить).

Таким образом, хотя само приложение `Page()` является безболезненным и простым в использовании, заставить все каналы назначения правильно обрабатывать входящий пейджинг будет немного сложнее. Мы вернемся к этому в ближайшее время.

Приложение `Page()` принимает три аргумента: 1) группа каналов, к которым должен быть подключен пейджинг, 2) параметры и 3) время ожидания (таймаут):
```
exten => *724,1,Noop(Page)
  same => n,Set(ChannelsToPage=${UserA_DeskPhone}&${UserA_SoftPhone}}&${UserB_DeskPhone})
  same => n,Page(${ChannelsToPage},i,120)
```
Параметры (описанные в Таблице 11-2) дают вам некоторую гибкость в отношении того, как работает `Page()`, но большая часть конфигурации будет зависеть от того, как целевые устройства обрабатывают входящее соединение. В следующем разделе мы рассмотрим различные способы настройки устройств для получения пейджинга.

_Таблица 11-2. Параметры Page()_

| Параметр | Описание | Объяснение |
| :--- | :--- | :--- |
| `d` | Включить полнодуплексный звук | Иногда его называют "пейджингом talkback", использование этого параметра подразумевает, что оборудование, принимающее пейджинг, имеет возможность передавать звук обратно одновременно с получением. Как правило, вы не станете использовать это, если у вас нет в нем потребности. | |
| `i` | Игнорировать попытки перенаправления вызова | Как правило эту опцию включают, потому что переадресованный вызов может направиться куда угодно и это не то место, куда нужно направиться Вашему пейджингу. |
| `q` | Не воспроизводить звуковой сигнал для вызывающего абонента (тихий режим) | Как правило не используется, так как для пейджинга следует подавать звуковой сигнал для предупреждения людей о том, что пейджинг вот-вот установится. Однако, если у вас есть внешний усилитель, который обеспечивает свой собственный сигнал, вы можете установить эту опцию. |
| `r` | Записать пейджинг в файл | Если в будущем вы намеревались использовать один и тот же пейджинг несколько раз, то можете записать его, а затем использовать позже, вызывая с помощью `Originate()` или используя опцию `A(x)` для `Page()`. |
| `s` | Набирать канал только в том случае, если состояние устройства `NOT_INUSE` | Эта опция, вероятно, полезна (и надежна) только для SIP-каналов, и даже в этом случае может не работать, если на одной линии одновременно разрешены несколько вызовов (довольно часто встречается на SIP-телефонах). Поэтому не полагайтесь на эту опцию во всех случаях. |
| `A(x)` | Воспроизвести объявления `х` всем участникам | Вы можете использовать ранее записанный файл для воспроизведения через систему пейджинга. Если вы объедините это с `Originate()` и `Record()`, то могли бы реализовать систему отложенного пейджинга. |
| `n` | Не воспроизводить объявление звонящему (подразумевается `A(x)`) | По умолчанию система будет воспроизводить звук пейджинга как для вызывающего, так и для вызываемого абонента. Если эта опция включена, звук пейджинга не будет транслироваться вызывающему абоненту (человеку, выполняющему пейджинг). |

---
**Предупреждение**

Из-за того, как работает `Page()`, он очень ресурсоемкий. Мы не можем это не подчеркнуть. Внимательно читайте дальше, и мы расскажем, как обеспечить, чтобы пейджинг не вызывал проблем с производительностью в продакшене (что наверняка может случиться, если пейджинг не спроектирован правильно).

---
### Места для отправки Вашего пейджинга

Как мы уже говорили, `Page()` само по себе очень простое. Хитрость в том, как собрать все это вместе. Пейджинги могут быть отправлены на различные виды каналов, и все они требуют различной конфигурации.

#### Внешний пейджинг

Если в здании установлена ​​система громкой связи, общепринято подключать телефонную систему к внешнему усилителю и отправлять пейджинг через вызов на канал. Лучший способ сделать это - использовать какое-либо устройство FXS (такое как ATA), которое подключается через интерфейс пейджинга, такой как Bogen UTI1, [5](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html#idm46178406290408), который затем подключается к усилителю пейджинга. [6](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html#idm46178406289064)

Другой популярный способ подключения к пейджинговой системе - подключить выход звуковой карты вашего сервера Asterisk к усилителю пейджинга и отправлять вызовы на канал с именем `Console/DSP`. Нам не нравится этот метод, потому что, хоть он и может показаться недорогим и простым, на практике может занимать много времени. Предполагается, что звуковые драйверы на вашем сервере работают правильно, уровни звука на этом канале нормализуются правильно, на вашем сервере имеется достойная встроенная звуковая карта, заземление хорошее, и ... ну, на наш взгляд, это путь не рекомендуется. [7](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html#idm46178406286520)

В вашем диалплане пейджинг на внешний усилитель будет выглядеть как простой `Dial()` для устройства, подключенного к пейджинговому оборудованию. Вам необходимо настроить ATA так же, как любой SIP-телефон (через `ps_endpoints`, `ps_auth` и т.д. в базе данных), с именем, похожим на `PagingATA`. Затем вы подключаете ATA к Bogen UTI1, и для пейджинга у вас будет этот код диалплана:
```
exten => *725,1,Verbose(2,Paging to external amplifier) ; '*' является частью того, что вы набираете
    same => n,Set(PageDevice=PJSIP/PagingATA)           ; Это, вероятно, относится к [globals]
    same => n,Page(${PageDevice},i,120)
```

Вы можете назвать это устройство как угодно (например, мы часто используем MAC-адрес в качестве имени SIP-устройства), но для всего, что не является телефоном пользователя, может быть полезно использовать имя, которое выделяет его из других устройств.

На рынке также есть много пейджинговых устройств на основе SIP (динамики пейджинга с поддержкой SIP популярны, но как нам кажется, довольно дороги для того, что вы получаете, особенно в большом развертывании).

#### Аппаратный пейджинг

Пейджинг на основе аппаратов впервые стал популярным в клавишных телефонных системах, где громкоговорители офисных телефонов используются в качестве системы оповещения бедняков. Большинство SIP-телефонов имеют возможность автоматического ответа на вызов по громкой связи, которая выполняет то, что требуется для каждого телефона. В дополнение к этому необходимо передавать звук более чем в одно устройство одновременно. Asterisk использует встроенный механизм конференц-связи для обработки деталей под капотом. Вы используете приложение `Page()`, чтобы это произошло.

Как и `Dial()`, приложение `Page()` может обрабатывать несколько каналов. Поскольку вы захотите чтобы `Page()` сигнализировало сразу на несколько устройств (возможно, даже на все устройства в вашей системе), вы можете получить длинные строки устройств, которые будут выглядеть примерно так:
```
Page(PJSIP/SET1&PJSIP/SET2&PJSIP/SET3&PJSIP/SET4&PJSIP/SET5&PJSIP/SET6&PJSIP/SET7&...
```
---
**Предупреждение**

За пределами определенного размера система Asterisk не сможет создать несколько аппаратных пейджингов. Например, в офисе с 200 телефонами использование SIP для пейджинга каждого устройства будет невозможно; трафик и загрузка процессора на вашем сервере Asterisk были бы просто слишком велики. В таких случаях вы должны смотреть либо на многоадресный пейджинг, либо на внешний.

---

Возможно, самая сложная часть пейджинга для SIP-устройств заключается в том, что вам обычно приходится указывать каждому устройству, что оно должно отвечать на вызов автоматически, но разные производители SIP-телефонов используют разные SIP-сообщения для этой цели. Таким образом, в зависимости от используемой вами модели телефона команды, необходимые для выполнения пейджинговой связи на основе SIP, будут разными. Вот некоторые примеры:

  * Для Mitel (ранее известны как Aastra):
```
exten => *726,1,Verbose(2,Paging to Aastra sets)
    same => n,SIPAddHeader(Alert-Info: info=alert-autoanswer)
    same => n,Set(PageDevice=SIP/00085D000000)
    same => n,Page(${PageDevice},i)
```

* Для Polycom:
```
exten => *727,1,Verbose(2,Paging to Polycom sets)
    same => n,SIPAddHeader(Alert-Info: Ring Answer)
    same => n,Set(PageDevice=SIP/0004F2000000)
    same => n,Page(${PageDevice},i)
```

* Для Snom:
```
exten => *728,1,Verbose(2,Paging to Snom sets)
    same => n,Set(VXML_URL=intercom=true)
; замените 'domain.com' на домен вашей системы
    same => n,SIPAddHeader(Call-Info: sip:domain.com\;answer-after=0)
    same => n,Set(PageDevice=SIP/000413000000)
    same => n,Page(${PageDevice},i)
```

* Для Cisco SPA (бывшие телефоные Linksys, кроме серии 79XX):
```
exten => *729,1,Verbose(2,Paging to Cisco SPA sets, but not Cisco 79XX sets)
    same => n,SIPAddHeader(Call-Info:\;answer-after=0)    ; Cisco SPA phones
    same => n,Set(PageDevice=SIP/0004F2000000)
    same => n,Page(${PageDevice},i)
```
Полагаем вы поняли, что произойдет, если у вас такое сочетание телефонов в рабочей среде? Как вы контролируете, какие заголовки отправлять на определенные телефоны? [8](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html#idm46178406263240)

В любом случае, это некрасиво.

К счастью, многие из этих устройств поддерживают многоадресную IP-рассылку, что является гораздо лучшим способом отправки пейджинга нескольким устройствам (для подробностей читайте далее). Тем не менее, если в вашей системе всего несколько телефонов одного производителя, пейджинг на основе SIP может быть самым простым способом, поэтому мы не хотим вас напугать.

#### Многоадресный пейджинг через канал MulticastRTP

Если вы серьезно относитесь к пейджингу через аппараты в вашей системе, и у вас есть более чем горсть телефонов, вам нужно будет посмотреть на использование IP-многоадресной рассылки. Концепция IP multicast существует уже давно time,[9](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html#idm46178406256840) но он не получил широкого распространения. Тем не менее, он идеально подходит для пейджинга в пределах одного места.

Asterisk имеет канал (`chan_multicast_rtp`), предназначенный для создания многоадресной рассылки RTP. На этот поток затем подписываются различные телефоны, и в результате каждый раз, когда медиапоток появляется в многоадресном потоке, телефоны передают его на свои динамики.

Поскольку `MulticastRTP` является драйвером канала, он не имеет приложения, но вместо этого будет работать в любом месте диалплана, где вы могли бы использовать канал иначе. В нашем случае мы будем использовать приложение `Page()` для инициирования нашей многоадресной рассылки.

Чтобы использовать многоадресный канал, вы просто посылаете ему вызов так же, как и любому другому каналу. Синтаксис канала выглядит следующим образом:
```
MulticastRTP/type/ip address:port[/linksys address:port]
```
Тип может быть либо `basic`, либо `linksys`. Основной синтаксис канала `MulticastRTP` выглядит следующим образом:
```
exten => *730,1,Page(MulticastRTP/basic/239.0.0.1:1234)
```
Не все устройства поддерживают IP multicast, но мы протестировали его на Snom,[10](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html#idm46178406245224) Linksys/Cisco, Polycom(прошивка 4.x или новее) и Aastra и он работает очень хорошо.

---
**Многоадресный пейджинг на телефонах Cisco SPA**

Функция многоадресного пейджинга на телефонах Cisco SPA немного странная, но после настройки она работает отлично. Хитрость заключается в том, что адрес, который вы вводите в телефон, не является адресом групповой рассылки, по которому передается пейджинг, а скорее своего рода сигнальным каналом.

Мы обнаружили, что вы можете сделать этот адрес таким же, как адрес многоадресной рассылки, но просто использовать другой номер порта.

Диалплан выглядит так:
```
exten => *724,1,Page(MulticastRTP/linksys/239.0.0.1:1234/239.0.0.1:6061)
```
В телефоне SPA вам нужно войти в интерфейс администрирования и перейти на вкладку _SIP_. В самом низу страницы вы найдете раздел под названием _Linksys Key System Parameters_. Вам необходимо задать следующие параметры:

* `Linksys Key System: Yes`
* `Multicast Address: 239.0.0.1:6061`

Обратите внимание, что адрес групповой адресации, назначенный телефону, является вторым в определении канала (в нашем примере используется порт 6061).

Обратите внимание, что вы можете написать команду `Page()` в этом формате в среде, где есть сочетание телефонов SPA (ранее Linksys, теперь Cisco) и других типов. Другие телефоны будут использовать первый адрес и будут работать так же, как если бы вы использовали `basic` вместо `linksys`.

---

#### SIP-адаптеры для пейджинга

На рынке существует множество пейджинговых динамиков на основе SIP. Эти устройства адресуются в диалплане точно так же, как SIP ATA, подключенный к UTI1 (другими словами для системы это просто телефонный аппарат), но физически они похожи на внешние пейджинговые динамики. Поскольку они отвечают автоматически, как правило нет необходимости передавать им какую-либо дополнительную информацию, как при использовании SIP-телефона.

Для небольших установок (где требуется не более полудюжины колонок), эти устройства могут быть экономически эффективными, поскольку не требуют никакого другого оборудования. Однако, для чего-либо большего (или для установки в сложной среде, такой как склад или автостоянка), вы получите лучшую производительность при гораздо меньших затратах с традиционной аналоговой системой оповещения, подключенной к телефонной системе через аналоговый (FXS) интерфейс.

У нас не было опыта работы с этими типами устройств, но есть надежда, что они будут поддерживать многоадресную передачу в качестве стандарта. Имейте это в виду, если планируете использовать большое их количество. Обычно лучше заказать одно устройство, протестировать его в прототипной конфигурации, и лишь когда вы убедитесь, что оно делает то, что вам нужно, расчитать количество.

#### Комбинации пейджинга

Во многих организациях может потребоваться как пейджинг на основе аппаратов, так и внешний пейджинг. Например, производственному объекту может потребоваться использовать аппаратный пейджинг для офиса, но потолочный для завода и склада. С точки зрения Asterisk, это довольно просто сделать. Когда вы вызываете приложение `Page()`, то просто указываете различные ресурсы, на которые хотите отправить пейджинг, разделенные символом `&` и все они будут включены в конференцию, которую создает приложение `Page()`.

#### Соберем все это вместе

На данный момент у вас должен быть список различных типов каналов, на которые вы хотите отправить пейджинг. Поскольку `Page()` почти всегда будет сигнализировать о более чем одном канале, мы рекомендуем установить глобальную переменную в разделе `[globals]` вашего файла _extensions.conf_, которая определяет список включаемых каналов, а затем вызвать приложение `Page()` с этой строкой:

```text
[globals]
MULTICAST=MulticastRTP/linksys/239.0.0.1:1234
;MULTICAST=MulticastRTP/linksys/239.0.0.1:1234/239.0.0.1:6061 ; if you have SPA phones

BOGEN=PJSIP/ATAforPaging  ; Assumes an ATA named [ATAforPaging]
PAGELIST=${MULTICAST}&${BOGEN} ; Variable names are arbitrary.
;...

[sets]
; ...
exten => *731,1,Page(${PAGELIST},i,120)
```
Этот пример предлагает несколько возможных конфигураций, в зависимости от оборудования. Хотя строго не требуется, чтобы была определена переменная `PAGELIST`, мы обнаружили, что это будет иметь тенденцию упрощать управление несколькими ресурсами пейджинга, особенно во время процесса настройки и тестирования.

### Зоны пейджинга

Зонирование пейджинга популярно в таких местах, как автомобильные дилерские центры, где отдел запчастей, отдел продаж и, возможно, отдел подержанных автомобилей требуют пейджинга, но не хотят (или не должны) слышать пейджинги друг друга.

В зонировании пейджинга пользователь, отправляющий пейджинг, должен выбрать, в какую зону будет помещен пейджинг. Контроллер зоны пейджинга, такой как Bogen PCM2000, обычно используется для обеспечения сигнализации различных зон: приложение `Page()` сигнализирует контроллеру зоны, контроллер зоны отвечает, а затем отправляется дополнительная цифра для выбора зоны, в которую должен быть отправлен пейджинг. Большинство контроллеров зон позволяют создавать пейджинги для всех зон, в дополнение к объединению зон (например, пейджинги для отделов продаж новых и подержанных автомобилей).

Вы также можете иметь отдельные расширения в диалплане, которые будут разделять ATAs (или группы телефонов), но это может оказаться более сложным и дорогостоящим, чем просто покупка контроллера пейджинга, предназначенного для обработки этого. Зонирование пейджинга не требует каких-либо существенно отличающихся технологий, но оно требует немного больше размышлений и планирования в отношении как диалплана, так и аппаратного обеспечения.

И это парковка и пейджинг. Это тонна информации, которую нужно переварить, но как только вы ее освоите, все покажется вполне логичным.

## Продвинутая конферец-связь

Приложение `ConfBridge()` - это продвинутое приложение для конференц-связи в Asterisk, которое обеспечивает передачу звука высокой четкости и базовых видеоконференций. Ранее мы ввели базовую рабочую настройку для `ConfBridge()`. Если вы создаете свой диалплан во время чтения, то найдете базовый мост конференции в файле _extensions.conf_, который выглядит примерно так:
```
exten => 221,1,NoOp()
    same => n,ConfBridge(${EXTEN})
```
В традиционной конфигурации Asterisk будет файл _confbridge.conf_, в котором мы можем настроить параметры для применения в различных сценариях. Это все еще возможно, но больше не имеет смысла делать это таким образом. Итак, мы собираемся пропустить сразу весь файл конфигурации, за исключением того, чтобы сказать, что файл примера (находится по адресу _~/src/asterisk-15.<TAB>/configs/samples/confbridge.conf.sample_) теперь становится отличным справочный документ, но не более того. Продолжайте читать и поймёте.

Прежде всего, нам нужно объяснить, что для конференции можно настроить три типа элементов, а именно `bridge`, `menu` и `user`.

Тип `bridge` определяет сами конференц-залы, тип `menu` определяет меню, к которому можно получить доступ из конференций, а тип `user` позволяет различным участникам конференции применять к ним определенную конфигурацию. Например, большая конференц-связь может иметь докладчика (который будет вести большую часть разговора), администратора (для помощи докладчику) и десятки участников (которым может быть запрещено выступать).

Давайте для начала создадим подпрограмму:
```text
[subConference]
exten => _[0-9].,1,Noop(Creating conference room for ${EXTEN})
 same => n,Goto(${ARG1})
 same => n,Noop(INVALID ARGUMENT ARG1: ${ARG1})
 same => n(admin),Noop()
 same => n,Authenticate(${ARG2}) ; Можно также использовать ,Set(CONFBRIDGE(user,pin)=${ARG2})
 same => n,Set(ConfNum=$[${EXTEN} - 1]) ; Hack: вычтите 1, чтобы получить номер конференции
 same => n,Set(CONFBRIDGE(bridge,record_conference)=yes) ; Запись, когда прибыл админ
 same => n,Set(RecordingFileName=${ConfNum}-${STRFTIME(,,%Y-%m-%d %H:%m:%S)})
 same => n,Set(CONFBRIDGE(bridge,record_file)=${RecordingFileName}) ; уникальное имя
 same => n,Set(CONFBRIDGE(user,admin)=yes) ; Админ
 same => n,Set(CONFBRIDGE(user,marked)=yes) ; Маркировать этого пользователя
 same => n,Set(CONFBRIDGE(menu,7)=decrease_talking_volume) ; Уменьшить громкость
 same => n,Set(CONFBRIDGE(menu,9)=increase_talking_volume) ; Увеличить громкость
 same => n,Set(CONFBRIDGE(menu,4)=set_as_single_video_src) ; Блокировать видео на меня
 same => n,Set(CONFBRIDGE(menu,5)=release_as_single_video_src) ; Вернуться к докладчику
 same => n,Set(CONFBRIDGE(menu,6)=admin_toggle_mute_participants); Отключить звук у всех, кроме администраторов
 same => n,Set(CONFBRIDGE(menu,2)=participant_count) ; Сколько участников?
 same => n,ConfBridge(${ConfNum})
 same => n,Return()
 same => n(participant),Noop()
 same => n,Set(ConfNum=${EXTEN})
 same => n,Set(CONFBRIDGE(user,wait_marked)=yes) ; Ждите маркированного пользователя
 same => n,Set(CONFBRIDGE(user,announce_only_user)=no) ; Ждите маркированного пользователя
 same => n,Set(CONFBRIDGE(user,music_on_hold_when_empty)=yes) ; Ждите маркированного пользователя
 same => n,Set(CONFBRIDGE(menu,7)=decrease_talking_volume) ; Уменьшить громкость
 same => n,Set(CONFBRIDGE(menu,9)=increase_talking_volume) ; Увеличить громкость
 same => n,ConfBridge(${ConfNum})
 same => n,Return()
```
Мы можем установить параметры `bridge`, `user` и `menu` как в предыдущем примере. Все параметры, которые вы можете использовать, описаны в файле _~/src/asterisk-15.<TAB>/configs/samples/confbridge.conf.sample_.

Когда мы вызываем подпрограмму, то можем передать пользователя в качестве аргумента. Поместите следующий новый код в ваш контекст `[sets]` после `_55512XX` и до `*724`:
```text
exten => _55512XX,1,Answer()
 same => n,Playback(tt-monkeys)
; ConfBridge
exten => *600,1,GoSub(subConference,${EXTEN:1},1(participant)) ;
exten => *601,1,GoSub(subConference,${EXTEN:1},1(admin,4242)) ;
exten => *724,1,Noop(Page)
 same => n,Set(ChannelsToPage=${UserA_DeskPhone}&${UserA_SoftPhone}&${UserB_DeskPhone})
 same => n,Page(${ChannelsToPage},i,120)
```
Если вы наберете *600, то станете участником. Если наберете *601, вас попросят ввести PIN-код (4242) и вы присоединитесь как администратор. Мы использовали метки диалплана для управления потоком вызовов в подпрограмме. Его легко читать и легко администрировать.

В [Главе 15](glava-15.md) мы узнаем, как использовать внешнюю базу данных для хранения и получения этих параметров, а не жестко кодировать их в диалплане.

### Видео-конференцсвязь

Механизм конференций в Asterisk может обрабатывать видео, но это очень упрощенное предложение, и вы должны тщательно оценить его чтобы убедиться, что оно соответствует вашим потребностям. Некоторые из более серьезных ограничений включают в себя:

* Все участники видеоконференции должны использовать один и тот же видеокодек; в Asterisk нет возможности перекодирования видео.
* В Asterisk отсутствует мультиплексирование видео; одновременно участнику может быть показан только один источник видео.

Чтобы пользователь мог использовать видео (будь то в конференции или просто для обычных вызовов), ему необходимо включить видеокодеки. Это можно сделать, изменив поле `allow` в таблице `asterisk.endpoints` и добавив `h264, vp8` в поле `allow`. Убедитесь, что вы не удаляете кодеки, которые уже есть (например, аудиокодек ulaw). Функциональная запись в этом поле может выглядеть следующим образом:
```
ulaw,h264,vp8
```
Прежде чем пытаться использовать видео с вашими конференциями, убедитесь, что ваши устройства могут использовать его с прямыми вызовами. Если вы можете использовать видеоконференции между вашими устройствами, вполне вероятно, что это также будет работать в ваших конференц-залах.

В [Главе 20](glava-20.md) мы погрузимся в WebRTC, где исследуем более мощные концепции в предоставлении мультимедийной коммуникации, включая конференц-связь.

## Вывод

В этой главе мы рассмотрели файл _features.conf_, который содержит функциональные возможности для включения трансфера через набор DTMF, записи звонков во время разговора и настройки парковок для одной или нескольких компаний. Мы также рассмотрели различные способы объявления вызовов и информации людям в офисе с использованием множества методов пейджинга, в том числе традиционных систем служебного оповещения и многоадресной пейджинговой связи на телефонные аппараты на рабочих столах сотрудников. После этого мы углубились в приложение `ConfBridge()`, которое чрезвычайно гибко в настройке и имеет множество доступных функций. Это исследование различных методов реализации традиционных функций парковки, пейджинга и конференций современным способом, надеюсь покажет вам гибкость, которую может предложить Asterisk.

[1](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406491144-marker) Да, мы понимаем, что SIP INFO сообщение на самом деле является сообщением SIP и технически не является частью аудиоканала, но дело в том, что вы не можете использовать кнопку «передача» или «парковка» на своем телефоне SIP для доступа к этим функциям во время разговора. Вам нужно будет отправить DTMF.

[2](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406451032-marker) В синтаксисе есть некоторая гибкость (подробности можно посмотреть в файле примера), но в нашем примере используется стиль, который мы рекомендуем, поскольку он наиболее соответствует типичному синтаксису диалплана.

[3](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406440184-marker) Мы рассмотрим AGI в [Главе 18](glava-18.md), но вкратце скрипты AGI - это внешние программы, которые вы можете запускать из диалплана. Удобно? Очень!

[4](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406331512-marker) Мы надеемся вы понимаете, что фактический добавочный номер будет связан с названием канала, который запарковал вызов, и не будет `SIP_0004F2040808` (если Лейф не продаст вам телефон Polycom из своей лаборатории).

[5](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406290408-marker) Bogen UTI1 полезен тем, что он может обрабатывать все входящие и исходящие соединения, что практически гарантирует безболезненность подключения вашей телефонной системы к любому виду внешнего пейджингового оборудования, независимо от его возраста или неясности. Стоимость устройства может быть компенсирована за счет экономии времени благодаря специальному, полнофункциональному интерфейсу, напоминающему швейцарский армейский нож, с существующей системой громкой связи (или, в этом отношении, как часть новой системы оповещения).

[6](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406289064-marker) В этой книге мы предполагаем, что внешнее пейджинговое оборудование уже установлено и работает со старой телефонной системой, но ничто не мешает вам установить совершенно новую систему оповещения и подключить ее к вашей системе Asterisk. Возможно, вы чувствуете, что мы подключаем Bogen здесь очень быстро, но это просто потому, что они очень долго занимались телефонной связью. Мы используем их в течение почти 30 лет, но они делают это дольше, поэтому, пока вам удобно собирать все части, вы можете выполнить работу правильно с первого раза.

[7](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406286520-marker) Если вам это интересно, мы хотим предложить попробовать это в своей лаборатории. Это может оказаться очень полезным может сэкономить некоторые расходы на оборудование. Мы только что обнаружили, что аппаратное обеспечение дешевле, чем трудозатраты, поэтому предпочли бы потерять пару сотен долларов на заведомо исправном оборудовании, а не на том, чтобы какой-то плохой техник копался на месте в течение восьми часов, а расстроенный клиент требовал знать, когда возникшая проблема с пейджингом будет решена.

[8](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406263240-marker) Подсказка: локальный канал здесь будет вашим другом.

[9](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406256840-marker) Он даже имеет свое собственное пространство зарезервированных IP-адресов класса D, от 224.0.0.0 до 239.255.255.255 (но прочитайте про IP-multicast прежде чем просто взять один из них и назначить его). Часть этого адресного пространства являются частным, часть - общедоступной и некоторые предназначены для целей, отличных от тех, для которых вы желаете их использовать. Информацию о многоадресной адресации можно найти на [странице Википедии](https://ru.wikipedia.org/wiki/Мультивещание).

[10](https://learning.oreilly.com/library/view/asterisk-the-definitive/9781492031598/ch11.html%22%20/l%20%22idm46178406245224-marker) Очень громко, и нет возможности отрегулировать усиление.

[Глава 10. Погружение в диалплан](glava-10.md) | [Содержание](SUMMARY.md) | [Глава 12. Automatic Call Distribution Queues](glava-12.md)
