Asterisk: режим DND на BLF клавише

    В рамках адаптации Asterisk к нуждам начальников и их секретарей озадачился я индикацией режима DND («Do Not Disturb» — «Не беспокоить») на клавишах BLF (Busy Lamp Field). На Хабре нашёлся соответствующий пост (а в комментарии ещё и полезная ссылка на альтернатитвный способ).

    «DnD достаточно востребованная функция, но обычно режим включается на самом телефоне, не уведомляя об этом Asterisk, отчего тот будет обращаться к телефону пользователя, думая, что тот на месте и готов ответить на звонок. Как нам включить режим DnD на самом Asterisk и чтобы кнопка включения при активированном DnD моргала красным цветом?» © xtelekom

    Однако, просто так взять и начать пользоваться DND на BLF не получилось.

    1. Первый способ на первый взгляд выглядит сложно. Без подробного объяснения использовать код в учёбе сложно, а в продакшене страшно. Как показали дальнейшие изыскания, можно обойтись меньшим количеством кода.
    2. Красная лампочка должна не моргать (абоненту звонят, он не берёт трубку, может, надо перехватить звонок?), а постоянно гореть (абонент занят).
    3. Во втором способе проверка текущего состояния DND всегда возвращала true. Естественно, способ не работал.
    4. Проблема индикации DND у самого абонента. Хорошо, если в телефоне есть возможность набирать номер при снятии/установке DND. В моём китаефоне такой возможности нет, да и сама кнопка DND выполнена на удивление неудобно — это тумблер на задней поверхности телефона. Конечно, нет проблем повесить DND (набор, скажем, *76) на многофункциональную клавишу, а hint на свой номер на соседнюю МФ-клавишу. Но логично, если весь функционал DND (и переключение, и индикация) будет находиться на одной клавише. Я пришёл к выводу, что для включения DND абонент будет набирать свой номер, тогда наблюдаемый и набираемый номера будут совпадать, что и нужно.

    В процессе допилинга методика эволюционировала весьма существенно, так что я решил поделиться результатами работы. Результаты постарался сделать наиболее понятными и, по возможности, оснастить комментариями.

    Итак, имеем Asterisk 1.8.18.0, абоненты уже есть и пользуются функцией BLF.

    Первым делом воспользуемся наработками коллег и в слегка модифицированном виде реализуем DND по набору *76. Добавляем в наш диалплан такой контекст:
    [dnd-on-off]
    exten => *76,1,Answer
    ; включён ли уже режим DND?
    exten => *76,n,GotoIf($["${DB(DND/${CALLERID(number)})}" = ""]?activate:deactivate)
    ; если DND выключен — ВКЛЮЧАЕМ
    exten => *76,n(activate),Set(STATE=BUSY)
    ; устанавливаем статус "занят" (чтобы сработал hint)
    exten => *76,n,Set(DEVICE_STATE(Custom:DND${CALLERID(number)})=${STATE})
    ; делаем запись в БД о включении DND
    exten => *76,n,Set(DB(DND/${CALLERID(number)})=1)
    exten => *76,n,Hangup
    ;;; а если DND включён — ВЫКЛЮЧАЕМ
    exten => *76,n(deactivate),Set(STATE=NOT_INUSE)
    ; устанавливаем статус "доступен" (чтобы сработал hint)
    exten => *76,n,Set(DEVICE_STATE(Custom:DND${CALLERID(number)})=${STATE})
    ; делаем запись в БД о выключении DND
    exten => *76,n,Set(DB(DND/${CALLERID(number)})=)
    exten => *76,n,Hangup
    

    Теперь добавим контекст, который будет включать DND по набору своего номера.
    [dnd-on-off-2]
    ; абонент звонит себе или кому-то другому?
    exten => _7XXX,1,GotoIf($["${CALLERID(number)}" = "${EXTEN}"]?godnd:gonext)
    ; если себе - отправляемся включать DND
    exten => _7XXX,n(godnd),Goto(dnd-on-off,*76,1)
    ; если другому - продолжаем набирать номер как обычно (у меня это исторически переход к приоритету 10)
    exten => _7XXX,n(gonext),Goto(10)
    

    Теперь научим Asterisk проверять состояние вызываемого абонента, и при выявлении режима DND вешать трубку. Для этого добавляем строку прямо перед вызовом абонента.
    ; Добавляем проверку, не находится ли вызываемый абонент в режиме DND
    exten => _7XXX,n,GotoIf($["${DB(DND/${EXTEN})}" = "1"]?gooff)
    exten => _7XXX,n,Dial(SIP/${EXTEN},20,Tt)
    exten => _7XXX,n(gooff),Hangup()
    

    Осталось воспользоваться новыми контекстами там, где нужно:
    ; это контекст, в который попадает любой звонок с SIP-телефона
    [outcoming-sip]
    ;;; Добавляем: включить/выключить DND по набору своего номера
    include => dnd-on-off-2
    ;;; следующий контекст содержит только "exten => _X.,1,Goto(10)"
    include => goto10
    ;;; Добавляем: включить/выключить DND по набору *76
    include => dnd-on-off
    ;;; звоним на SIP-телефоны (этот контекст начинается с приоритета 10)
    include => sip-phones
    

    Сохраняем и делаем asterisk -rx "dialplan reload".

    После этого на телефоне понравившуюся многофункциональную клавишу переводим в режим BLF и назначаем ей hint самого абонента. Pickup code не указываем, он не нужен. Хотя, конечно, тут всё зависит от телефона (у меня Flying Voice IP-622).

    Теперь после нажатия клавиши «Не беспокоить» звонки абоненту прекращают поступать, сама клавиша загорается красным, а у секретарши загорается красным клавиша «Шеф», миссия выполнена.

    P.S. Особую благодарность хочу выразить телефону Flying Voice IP622, который, хотя и вёл себя слегка неадекватно на старой прошивке и немного окирпичился во время обновления, сейчас показывает себя молодцом. Функционал богат, поддержка трудолюбива, а интерфейс прошивок v1.4 и v3 практически идентичен. Для своей цены просто шикарен.
    • +13
    • 20k
    • 8
    Поделиться публикацией

    Комментарии 8

      0
      Подарок от Деда Мороза. В избранное! Спасибо!
        0
        Спасибо, приятно знать, что это кому-то нужно =)
        0
        3. Во втором способе проверка текущего состояния DND всегда возвращала true. Естественно, способ не работал.

        это мой способ не работает? или нет? потому как у меня все-таки работает

        Пару вопросов от себя :)
        астериск голый без всяких настроек? или какой то веб все таки есть?
        ну и на какой оси все крутится?

          0
          > это мой способ не работает?
          Да, у меня не работает. Возможно, дело в версии или в настройках, но я, честно говоря, не вижу в вашем диалплане записи в AstDB, чтобы потом проверять ${DB(DND/${CALLERID(number)})}. Видимо, запись в БД подразумевается при Set(DEVICE_STATE ...), но у меня не пишется или пишется не туда.

          > астериск голый без всяких настроек? или какой то веб все таки есть?
          Debian 6, Asterisk 1.8 без веба, реально обслуживает десяток пользователей.
            0
            exten => _[12]0[1-2],hint,Custom:DND${EXTEN}&SIP/${EXTEN}

            я хинтом проверяю. и он же отслеживает состояние. Может не работать так как я на фре поднимал. а что там разработчики намутили — хз :)
              0
              Чего-то я не понимаю, или спать уже пора.
              Вот эта строчка:
              exten => *76,n,GotoIf($["${DB(DND/${CALLERID(number)})}" = ""]?activate:deactivate)
              напрямую взята из вашего жж. И в ней явно проверяется ключ из AstDB.
              Какая строка вашего диалплана меняет этот ключ? Должен же он меняться. Это точно тот же самый код, что вы на самом деле используете?..
                0
                я дико извиняюсь :) писал по памяти и пропустил строчку с удалением из базы

                даю правильный контент:

                [dnd_on-off]
                exten => *76,1,Answer
                exten => *76,n,GotoIf($["${DB(DND/${CALLERID(number)})}" = ""]?activate:deactivate)
                exten => *76,n(activate),Set(STATE=RINGING)
                exten => *76,n,Set(DEVICE_STATE(Custom:DND${CALLERID(number)})=${STATE})
                exten => *76,n,Hangup
                exten => *76,n(deactivate),dbDel(DND/${CALLERID(number)})
                exten => *76,n,Set(STATE=NOT_INUSE)
                exten => *76,n,Set(DEVICE_STATE(Custom:DND${CALLERID(number)})=${STATE})
                exten => *76,n,Hangup
                  0
                  Всё, теперь картинка сложилась :)

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое