Русский
Русский
English
Статистика
Реклама

Asterisk. И снова AMI Originate

Ранее я уже писал "AMI. Разносторонний Originate. Применение в CTI приложении". На тот момент мне казалось, что тема раскрыта, исчерпана. Но оказалось, есть куда стремиться.

Классический Originate

Action: OriginateChannel: PJSIP/201Context: all-peersExten: 203Priority: 1Callerid: 201

Пример контекста all-peers

[all-peers]exten => _X!,1,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})},30,Tt)same => n,Hangup()
  • 201 совершит вызов на 203

  • callerid у 201 отобразиться как 201 (значение параметра "Callerid" в команде Originate)

  • callerid у 203 отобращиться как 201 - все красиво

В истории звонков отобразится

2021-05-17 16:34:17|2021-05-17 16:34:20|2021-05-17 16:34:32|201|PJSIP/201-0000000a|203|PJSIP/203-0000000b

В истории все хорошо.

Чего не хватает:

  • 201 видит не корректный номер телефона, в идеале, отобразить номер, с кем планируем разговаривать

  • Не учитывается случай множественной регистрации, для 201 будет звонить последний зарегистрированный contact. Необходимо, чтобы звонили все зарегистрированные на 201 устройства одновременно


Учитываем множественную регистрацию

Опишем дополнительный контекст в extensions.conf

[internal-orig]exten => _X!,1,Set(DST_CONTACT=${PJSIP_DIAL_CONTACTS(${EXTEN})})  same => n,ExecIf($["${DST_CONTACT}x" != "x"]?Dial(${DST_CONTACT},30,Tt))

Теперь Originate примет вид:

Action: OriginateChannel: Local/201@internal-origContext: all-peersExten: 203Priority: 1Callerid: 201

Проблема множественной регистрации решена, звонят все телефоны одновременно. Но, в CDR теперь каша:

2021-05-17 17:01:09|2021-05-17 17:01:12|2021-05-17 17:01:17|203|Local/201@internal-orig-00000006;2|201|PJSIP/201-000000122021-05-17 17:01:09|2021-05-17 17:01:12|2021-05-17 17:01:17|201|Local/201@internal-orig-00000006;1|203|PJSIP/203-00000013
  • Теперь две записи

  • Появились Local каналы

Это все решается, но перейдем к этому вопросу позже.

Корректный CallerID для звонящего

Добавим в AMI команду дополнительную переменную origCid=203:

Action: OriginateChannel: Local/201@internal-origContext: all-peersExten: 203Priority: 1Callerid: 201Variable: origCid=203

Значение переменной будет совпадать с параметром "Exten" нашего запроса AMI.

Теперь дополним dialplan:

[internal-orig]exten => _X!,1,Set(D_CONT=${PJSIP_DIAL_CONTACTS(${EXTEN})})  same => n,Set(CALLERID(num)=${origCid})  same => n,ExecIf($["${D_CONT}x" != "x"]?Dial(${D_CONT},${ringlength},Tt))

Теперь на каждый увидит корректный callerid.

Исправляем информацию в CDR

Эта задача оказалась наиболее сложной и интересной. К сожалению в интернет на эту тему информации крайне мало.

Основная идея по порядку:

  • Как можно раньше убить Local каналы (hangup)

  • Local каналы НЕ должны создавать CDR записи

  • Необходимо перехватить канал звонящего при создании и направить его в контекст назначения

Теперь на примерах.

Для определения вновь созданного "реального канала" (НЕ Local) следует использовать опцию U(orig-answer-channel) в приложении Dial

Дополнительный контекст orig-answer-channel примет вид:

[orig-answer-channel]exten => s,1,Set(MASTER_CHANNEL(O_SRC_CHAN)=${CHANNEL})  same => n,return

Основная его задача - получить имя реального канала.

Дополним контекст назначения. В нем мы завершим все Local каналы и "Реальный канал" в контекст назначения:

[all-peers]exten => _X!,1,ExecIf($[ "${O_SRC_CHAN}x" != "x" ]?ChannelRedirect(${O_SRC_CHAN},${CONTEXT},${EXTEN},1))  same => n,ExecIf($[ "${O_SRC_CHAN}x" != "x" ]?Hangup())  same => n,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})},30,Tt)  same => n,Hangup()

В "all-peers" первым попадет Local канал. Это хорошо видно в verbose логе:

Executing [203@all-peers:1] ExecIf("Local/201@internal-orig-00000009;1", "1?NoCDR()")Executing [203@all-peers:2] ExecIf("Local/201@internal-orig-00000009;1", "1?ChannelRedirect(PJSIP/201-00000016,all-peers,203,1)")Executing [203@all-peers:3] ExecIf("Local/201@internal-orig-00000009;1", "1?Hangup()")

Было использовано приложение "ChannelRedirect" реальный канал будет переадресован в контекст назначения, а Local каналы будут завершены.

Executing [203@all-peers:1] ExecIf("PJSIP/201-00000016", "0?NoCDR()")Executing [203@all-peers:2] ExecIf("PJSIP/201-00000016", "0?ChannelRedirect(,all-peers,203,1)")Executing [203@all-peers:3] ExecIf("PJSIP/201-00000016", "0?Hangup()")Executing [203@all-peers:4] Dial("PJSIP/201-00000016", "PJSIP/203/sip:203@172.16.156.1:59442;ob,30,Tt")

В качестве "all-peers" лучше всего использовать контекст, определенный для конкретного sip пира, тогда звонок через Originate будет соответствовать аналогичному звонку напрямую с телефона.

Осталось только добавить NoCDR, чтобы убрать cdr записи Local каналов.

Итоговый вариант

Команда AMI примет вид:

Action: OriginateChannel: Local/201@internal-origContext: all-peersExten: 203Priority: 1Callerid: 201Variable: origCid=203

Итоговый dialplan, обратите в нем внимание на два вызова NoCDR:

[internal-orig]exten => _X!,1,NoCDR()same => n,Set(MASTER_CHANNEL(O_DST_CHAN)=${origCid})same => n,Set(CALLERID(num)=${origCid})same => n,Set(DST_CONTACT=${PJSIP_DIAL_CONTACTS(${EXTEN})})same => n,ExecIf($["${DST_CONTACT}x" != "x"]?Dial(${DST_CONTACT},${ringlength},TtU(orig-answer-channel),s,1)))[orig-answer-channel]exten => s,1,Set(MASTER_CHANNEL(O_SRC_CHAN)=${CHANNEL})  same => n,return[all-peers]exten => _X!,1,ExecIf($[ "${O_SRC_CHAN}x" != "x" ]?NoCDR())same => n,ExecIf($[ "${O_SRC_CHAN}x" != "x" ]?ChannelRedirect(${O_SRC_CHAN},${CONTEXT},${O_DST_CHAN},1))same => n,ExecIf($[ "${O_SRC_CHAN}x" != "x" ]?Hangup())same => n,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})},30,Tt)same => n,Hangup()

В CDR будет сохранена одна запись

2021-05-17 17:29:07|2021-05-17 17:29:10|2021-05-17 17:29:14|201|PJSIP/201-00000018|203|PJSIP/203-00000019

То, что надо! :)

Итоги

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

Описанный прием мы успешно применили в нашей бесплатной АТС с открытым исходным кодом MikoPBX.

Полезный ресурсы

Источник: habr.com
К списку статей
Опубликовано: 17.05.2021 18:06:47
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Api

Asterisk

Mikopbx

Pbx

Ami

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru