Первоначально идея была написать о hint, все так и было, но потом Остапа понесло…
1. SIP NOTIFY
2. hints
3. DEVICE_STATE
4. EXTENSION_STATE
5. BLF на примере DND
Hint позволяет узнать состояние устройства еще до того как мы что то пытаемся с ним сделать:)
Кому интересно милости прошу
SIP SUBSCRIBE/NOTIFY механизм – Что это и как это работает:)
Протокол SIP позволяет любому SIP клиент мониторить состояние другого, детальнее читаем тут RFC 3265.
Работает это приблизительно так:
Если устройство А хочет знать о состоянии устройства Б, посылает SUBSCRIBE запрос или прямо устройству Б или серверу который в курсе состояния устройства Б. Если SUBSCRIBE запрос был успешен, то после о каждом изменении состояния устройства Б, устройство А узнает об этом с помощью SIP NOTIFY! так работает Busy Lamp Field(BLF). Термин любезно позаимствован со старых телефонных станций, когда с помощью лампочки можно было посмотреть занятость линии.
NOTIFY сообщение отсылается при первой регистрации телефона, и в дальнейшем отсылаются при изменении в номере сообщений или в статусе хранимых сообщений.
Asterisk всегда в курсе состояния многих вещей: телефонов, очередей, голосовой почты. поэтому астериск должен бы принимать SUBSCRIBE запросы и сообщать о изменениях в устройствах которые мониторятся. Однако, SIP протоколы и стандарты не могут описать все возможные названия устройств или статусы – но протоколы предоставляют общий фреймворк для информирования о событиях без определения точного события или имени устройства. Для максимальной гибкости, Астериск позволяет задать имена устройств в диалплане(extensions.conf). Для этого и используются Hintы. Hints это простое,настраиваемое, сопоставление между произвольной именной меткой и определенным телефоном или приложением, о каком знает Астериск.
Когда Астериск получает SIP SUBSCRIBE запрос он проверяет хинты в диалплане, какие должны совпадать с именем устройств которые мониторятся. Хинты сообщают Астериску, какому устройству они соответствуют. Хинты связывают номера с физическими или виртуальными(конференции, парковки) устройствами
Примеры:
exten => 1234,hint,SIP/phoneA&SIP/phoneB&SIP/phoneC exten => 1234,1,Dial(SIP/phoneA&SIP/phoneB&SIP/phoneC) exten => 5555,hint,DAHDI/1 exten => 5555,1,Dial(DAHDI/1) exten => 31337,hint,MeetMe:31337 exten => 31337,1,MeetMe(31337,dM)
Проверить состояние через CLI:
CLI>core show hints
Также можно добавить наблюдателя(watcher) тот кто подписан на обновления(см начало статьи)
В версии 1.6 появилась специальная функция DEVICE_STATE() – Получение или установка состояния устройства.
Синтаксис:
DEVICE_STATE(device)
Описание:
Функция DEVICE_STATE может использоваться для получения состояния устройства с любого из тех, которые могут предоставлять эту информацию.
Также функция может использоваться для установки некоторых особенных состояний устройства из плана набора. В этом случае для указания имени состояния должен использоваться префикс “Custom:”.
!!! Если у Вас SIP постоянно отвечает NOT_INUSE, то нужно добавить в [general] раздел sip.conf
callcounter=yes
Вы можете подписаться на отслеживание изменения этого “особенного” состояния устройства, используя hint приоритет в плане набора:
exten => 1234,hint,Custom:lamp1
Возможные значения для обоих случаев применения данной функции следующие:
UNKNOWN
NOT_INUSE
INUSE
BUSY
INVALID
UNAVAILABLE
RINGING
RINGINUSE
ONHOLD
Пример получение статуса устройства:
NoOp(SIP/mypeer has state ${DEVICE_STATE(SIP/mypeer)})
NoOp(Conference number 1234 has state ${DEVICE_STATE(MeetMe:1234)})
Пример установки статуса устройства:
Set(DEVICE_STATE(Custom:lamp1)=BUSY)
Set(DEVICE_STATE(Custom:lamp2)=NOT_INUSE)
[use_ctx] include => parkedcalls-tenant exten => 999,1,NoOp(Show parked call hint state) exten => 999,n,NoOp(DEVICE_STATE(park:701@use_ctx)=${DEVICE_STATE(park:701@use_ctx)}) exten => 999,n,NoOp(DEVICE_STATE(park:701@parkedcalls-tenant)=${DEVICE_STATE(park:701@parkedcalls-tenant)}) exten => 999,n,NoOp(EXTENSION_STATE(701@use_ctx)=${EXTENSION_STATE(701@use_ctx)}) exten => 999,n,NoOp(EXTENSION_STATE(701@parkedcalls-tenant)=${EXTENSION_STATE(701@parkedcalls-tenant)})
Также есть функция EXTENSION_STATE(), работает подобно DEVICE_STATE, но для экстеншенов
exten => 7013,1,Answer() same => n,Verbose(3,The state of 7001@phones is ${EXTENSION_STATE(7001@phones)}) same => n,Hangup()
Возможные значения:
• UNKNOWN
• NOT_INUSE
• INUSE
• BUSY
• UNAVAILABLE
• RINGING
• RINGINUSE
• HOLDINUSE
• ONHOLD
BLF (МИГАЮЩА ЛАМПАЧГА)
Для нормальной работы нам понадобятся такие опции:
callcounter=yes если не указать, SIP устройство всегда будет NOT_INUSE
busylevel=N задает к-во звонков, при котором считается, что телефон занят. Можно указывать индивидуально для каждого профиля в файле sip.conf.
call-limit устаревшая функция использовалась как callcounter и для установки ограничения к-ва звонков, теперь нужно использовать функции GROUP() и GROUP_COUNT().
allowsubscribe=no и система не будет отслеживать подписки на BLF от этого абонента.
subscribecontext=context устанавливает особый контекст на подписки.
notifyringing=yes Отсылать или нет уведомление о том что устройство звонит, по умолчанию да. Используется dialog-info. Опция устанавливается в разделе [general] в sip.conf.
notifyhold=yes Позволяет chan_sip устанавливать состояние SIP устройств в ONHOLD, по умолчанию да. Опция устанавливается в разделе [general] в sip.conf.
notifycid=yes вкл возможность передачи инфо о CID c dialog-info+xml сообщениями (snom телефоны). По умолчанию No. Эта функция будет корректно работать только при входящем звонке использующим то же контекст и номер, которые используются как hint для вызываемого номера. не будет работать если используется subscribecontext!=context также огр для пользователя, если экстеншен звонит(несколько входящих) только один будет использоваться как источник CID. Укажите ‘ignore-context’ для игнора вызываемого контекста при просмотре канала звонящего. отображение CID может быть полезным когда агент решает перехватывать вызов или нет.
Пример реализации DND(“do not disturb”)
; Создаем хинт, чтобы телефон мог использовать BLF для сигнализации состояния DND ; exten => DND_7015,hint,Custom:DND_7015 ; ; Создаем номер, который привяжем к определенной кнопке на телефоне, которая и будет переключать состояние DND. ; exten => DND_7015,1,Answer() same => n,GotoIf($["${DEVICE_STATE(Custom:DND_7015)}"="BUSY"]?turn_off:turn_on) same => n(turn_off),Set(DEVICE_STATE(Custom:DND_7015)=NOT_INUSE) same => n,Hangup() same => n(turn_on),Set(DEVICE_STATE(Custom:DND_7015)=BUSY) same => n,Hangup() ; ; Пример использования состояния DND. ; exten => 7015,1,GotoIf($["${DEVICE_STATE(Custom:DND_7015)}"="BUSY"]?busy:available) same => n(available),Verbose(3,DND is currently off for 7015.) same => n,Dial(SIP/exampledevice) same => n,Hangup() same => n(busy),Verbose(3,DND is on for 7015.) same => n,Playback(vm-theperson) same => n,Playback(digits/7&digits/0&digits/1&digits/5) same => n,Playback(vm-isunavail) same => n,Playback(vm-goodbye) same => n,Hangup()
Еще есть прикольное применение, подсмотрел у сименсовских АТСок, Перехват вызова.
Есть у нас парочка телефонов разнесенных по зданию. И вот решил коллега зайти к Вам в гости, по служебным вопросам), НО мы хотим сделать возможным перехват вызова,с его трубу, как будто он ответил со своего места.
В руки ко мне попал аппарат китайских мастеров телефонного дела Grandstream GXP-2000
1. В вебморде аппарата на закладке BASIC SETTINGS находим поле Multi Purpose Key 1 Выставляем Key Mode: BLF, выбираем аккаунт(у этого телефона 4 линии) Name пишем произвольное, а вот UserID точно такое как номер и привязанный к нему hint(например 7107)
2. Создаем перехватывалку))
или отдельным контекстом или..
exten => _**71XX,1,Pickup(${EXTEN:2}) exten => _**71XX,2,Hangup
3. Создаем хинты устройств. Если разбить хинты по разным контекстам, то мы разделим группы пользователей для перехвата, для примера добавил 2 группы.
exten => 7107,hint,SIP/7107 [BLF_Group_1] exten => 501,hint,SIP/501 exten => 502,hint,SIP/502 exten => 503,hint,SIP/503 [BLF_Group_2] exten => 504,hint,SIP/504 exten => 505,hint,SIP/505 exten => 506,hint,SIP/506 exten => 507,hint,SIP/507
4. в Sip.conf добавляем контекст подписчика)
[504] type=friend username=504 secret=mypassword context=localcontext host=dynamic nat=yes canreinvite=no mailbox=504 subscribecontext=BLF_Group_2
Теперь пояснения по индикации
Горит зеленая лампочка – линия свободна, нажав на нее мы наберем данного абонента.
Мигает красная лампочка – кто-то звонит, нажав на нее, мы перехватываем звонок GXP-2000 отправит SIP INVITE на номер “**7107” Астериску.
Горит красная лампочка – кто-то говорит по линии(вх или исх звонок)
Связка Шеф-Секретарь с помощью BLF.
Дано:
Секретарь(359)
Шеф(350)
По умолчанию все звонки приходят на секретаря, и она уже может соединить с шефом.
У каждого на телефоне есть кнопка(цеплял на 4ю линию) при нажатии которой можно изменить состояние связки.
Если секретарь уходит, или шеф хочет лично принимать звонки, это можно сделать нажатием кнопки.
В диалплане создаем вот такую штуку:
Кто хочет может приаккуратить диалплан милости прошу)
exten => DND350,hint,Custom:DND350 exten => DND350,1,Answer() same => n,GotoIf($["${DEVICE_STATE(Custom:DND350)}"="BUSY"]?turn_off:turn_on) same => n(turn_off),Set(DEVICE_STATE(Custom:DND350)=NOT_INUSE) same => n,Hangup() same => n(turn_on),Set(DEVICE_STATE(Custom:DND350)=BUSY) same => n,Hangup() exten => 350,1,NoOp(Start) same => n, GotoIf($[${CALLERID(num)}=359]?busy:normal) same => n(normal), GotoIf($["${DEVICE_STATE(Custom:DND350)}"="BUSY"]?busy:available) same => n(available),Verbose(3,DND is currently off for 350.) same => n,Dial(SIP/359) same => n,Hangup() same => n(busy),Verbose(3,DND is on for 350.) same => n,Dial(SIP/${EXTEN}) same => n,Hangup()
В качестве конечных устройств Шефа и секретаря я использую Cisco SPA504G
Как прошить обновить и пр, есть у меня в бложеге )
В телефоне настраиваем кнопку, или скриптами, или как в данном случае через вебморду.
Заходим в настройки телефона, Admin->Advanced->Voice->Phone
Выбираем линию, например 4…выставляем:
Extension: Disabled Share Call Appearance: private Extended Function: fnc=blf+sd;sub=DND350@$PROXY;ext=DND350@$PROXY Short Name: Какое пожелаете)
Естественно, это нужно проделать на двух телефонах)