[API, Asterisk] Asterisk. И снова AMI Originate

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
17-Май-2021 20:32

Ранее я уже писал "AMI. Разносторонний Originate. Применение в CTI приложении". На тот момент мне казалось, что тема раскрыта, исчерпана. Но оказалось, есть куда стремиться. Классический Originate
Action: Originate
Channel: PJSIP/201
Context: all-peers
Exten: 203
Priority: 1
Callerid: 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: Originate
Channel: Local/201@internal-orig
Context: all-peers
Exten: 203
Priority: 1
Callerid: 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-00000012
2021-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: Originate
Channel: Local/201@internal-orig
Context: all-peers
Exten: 203
Priority: 1
Callerid: 201
Variable: 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: Originate
Channel: Local/201@internal-orig
Context: all-peers
Exten: 203
Priority: 1
Callerid: 201
Variable: 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
===========

Похожие новости: Теги для поиска: #_api, #_asterisk, #_mikopbx, #_asterisk, #_pbx, #_ami, #_api, #_asterisk
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 13:11
Часовой пояс: UTC + 5