Asterisk 16: работаем с AstDB, используем встроенную базу данных

Итак, Asterisk имеет простую встроенную базу данных AstDB, которая позволяет хранить данные в формате "Группа => ключ => значение". Используя встроенную БД можно реализовать настройку переадресации звонка пользователем, создание черного списка, привязки абонента к конкретному оператору и т.п. Для доступа к этой базе данных мы будем использовать следующие функции:

  • DB: Получить или установить значение во встроенной базе данных AstDB.
  • DB_DELETE: Удаление ключа из внутренней базы данных Asterisk.
  • DB_EXISTS: Проверка существования ключа во внутренней базе данных Asterisk.
Напишем простой контекст, который позволит пользователю включить постоянный безусловный перевод со своего IP телефона на мобильный или внутренний номер, а также включить нежелательный номер в черный список.
;Контекст для включения и отключения безусловного перевода звонка по *21/22, и черный список
[call-forward]
;Включить безусловный перевод для использования в cfim-forward
exten => _*21XXX,1,NoOp(Активирован безусловный перевод звонка c ${CALLERID(num)} на внутренний номер ${EXTEN:3})
same => n,SET(DB(CFIM/${CALLERID(NUM)})=${EXTEN:3})
same => n,Hangup
;Отключить безусловный перевод
exten => #21,1,NoOp(Отмена перевода звонка с ${CALLERID(num)} на внутренний номер: ${DB_DELETE(CFIM/${CALLERID(NUM)})
same => n,Hangup
;Перевод звонка при недоступности на сотовый номер 8ХХХХХХХХХХ для cftc-forward
exten => _*23X.,1,NoOp(Активирован безусловный перевод звонка с ${CALLERID(num)} на сотовый номер ${EXTEN:3})
same => n,SET(DB(CFTC/${CALLERID(num)})=${EXTEN:3})
same => n,Hangup
;Отмена перевода звонка на сотовый номер
exten => #23,1,NoOp(Отмена перевода звонка с ${CALLERID(num)} на сотовый номер: ${DB_DELETE(CFTC/${CALLERID(NUM))})
same => n,Hangup
;Внести номер в черный список
exten => _*27X.,1,NoOp(Вносим номер ${EXTEN:3} в черный список ${CALLERID(num)})
same => n,SET(DB(BLIST/${CALLERID(num)}/${EXTEN:3})=${EXTEN:3})
same => n,Hangup
;Удалить номер из черного списока
exten => _#27X.,1,NoOp(Удаляем номер ${DB_DELETE(BLIST/${CALLERID(num)}/${EXTEN:3})} из черного списка ${CALLERID(num)})
same => n,Hangup
Далее мы создадим 3 контекста для проверки наличия номера в нужных списках:
;Контекст проверки номера по черному списку
[check-blist]
exten => s,1,NoOp(Проверяем номер по черному списку)
same => n,SET(result=${DB(BLIST/${ARG1}/${ARG2})})
same => n,GotoIf($["${result}"=""]?done)
same => n,NoOp(Номер в черном списке)
same => n,Hangup
same => n,Return
same => n(done),NoOp(Номер не в черном списке)
same => n,Return ;возвращаемся в контекст откуда вызвали

;Контекст проверки безусловного перевода звонка на сотовый номер
[cftc-forward]
exten => s,1,SET(CFTC=${DB(CFTC/${ARG1})})
same => n,GotoIf($["${CFTC}" = ""]?done)
same => n,Playback(msg404);Ваш звонок переведен на мобильный телефон сотрудника
same => n,Dial(SIP/zadarma/7${CFTC:1},40,g)
same => n,Hangup
same => n,Return
same => n(done),NoOp(Безусловный перевод на сотовый телефон не включен)
same => n,Return ;возвращаемся в контекст откуда вызвали

;Контекст проверки безусловного перевода на внутренний номер
[cfim-forward]
exten => s,1,SET(CFIM=${DB(CFIM/${ARG1})})
same => n,GotoIf($["${CFIM}" = ""]?done)
same => n,Dial(SIP/${CFIM},40,t)
same => n,Hangup
same => n(done),NoOp(Безусловный перевод на внутренний номера не включен)
same => n,Return ;возвращаемся в контекст откуда вызвали
Теперь находим контекст, где совершается вызов и перед Dial прописываем перенаправления в контексты для проверок:
[call-in]
; ${ARG1} - Extension
; ${ARG2} - CallerID Number
exten => s,1,NoOp(Звонок с ${ARG2} на ${ARG1})
same => n,GoSub(check-blist,s,1(${ARG1},${ARG2}));проверяем по черному списку
same => n,GoSub(cfim-forward,s,1(${ARG1}));проверяем, включен ли безусловный перевод на внутренний номер
same => n,GoSub(cftc-forward,s,1(${ARG1}));проверяем, включен ли безусловный перевод на сотовый телефон
same => n,Dial(SIP/${ARG1},60,Ttg) ;звоним на номер
same => n,Hangup
Теперь в основном диалплане вместо Dial можем использовать обращение в контексту call-in. Например так:
exten => _XXX,1,GoSub(call-in,s,1(${EXTEN},${CALLERID(num)}))
Для пользователя работать правила будут следующим образом:
*21ХХХ - Включить безусловный перевод звонка на внутренний номер ХХХ
#21 - Отмена безусловного перевода звонка
*238ХХХХХХХХХХ - Включить безусловный перевод звонка на сотовый номер 8ХХХХХХХХХХ
#23 - Отмена безусловного перевода звонка на сотовый номер
*27XXX. - Внести внутренний номер XXX с черный список
#27XXX. - Убрать номер XXX из черного списка

2 комментария:

  1. Добрый день. Сделал по вашей инструкции, все классно, работает, но понадобилось сделать условную переадресацию. Если вставить строку с дозвоном на внутренний номер, то возвращается экстеншен s. (например, SIP/s,10,t). Я сделал глобальную переменную, в которую пишется экстеншен на который пришел звонок. И тогда все работает как надо, но. Я не уверен, что использование глобальной переменной это правильно. Не получит ли результат этой переменной другой экстеншен

    ОтветитьУдалить
    Ответы
    1. Мне кажется, в данном случае можно ограничиться наследуемой канальной переменной (с префиксом __)
      exten = 1234,1,Set(__FOO=bar)

      Удалить