Поиск по моему блогу

Asterisk и DTMF при callback

AsteriskImage via Wikipedia

Проблема

При организации функции callback на Asterisk`е, когда Asterisk перезванивает и ты пытаешься ввести тоном номер, то нажатые тобой цифры начинают задваиваться, а то и затраиваться.
Причем это могло происходить не всегда и не зависело от аппарата, на котором набирали тоном.
Так же после многочисленных тестов стало точно понятно, что когда идет звонок из «города» на Asterisk, то подобных проблем не возникает, только если сам Asterisk звонит в «город».
VoIP соединение идет так:
E1 <–> Cisco AS5350 (c5350-js-mz.124-15.T11.bin) <–> Asterisk (версия 1.4.29_2)
Попробую более менее внятно рассказать о процессе нашего разбора с этой проблемой и последовательности действий, а вдруг кому ещё пригодится кроме меня, если я захочу освежить память по этому вопросу через какое то время.

Начали разбор полетов

Для того что бы выявить проблему стало понятно, что нужно подебажить DTMF на самом Asterisk. Как это сделать ?
Пока опыт работы с Asterisk не такой большой как хотелось бы, посему прибегнули к помощи гугла, через минут пять выяснили:
Открываем файл  logger.conf и там ищем строчку:
console => notice,warning,error
В нее дописывем dtmf, получаем:
console => notice,warning,error,dtmf
Сохраняем файл, входим в консоль Asterisk`а:
asterisk -r
И в консоле даем команду:
asterisk*CLI> logger reload
После чего, в той же консоле, задаем уровень дебага, я делал так:
asterisk*CLI> core set debug 3
Далее, для того что бы потестить нажатие кнопок, я внес нехитрые изменения в dialplan:
[dtmf_test]
exten => s,1,Answer()
exten => s,n,Wait(1)
exten => s,n(collect),Read(digito,,11)
exten => s,n,SayDigits(${digito})
exten => s,n,GoTo(collect)
exten => s,n,Hangup
Т.е. поднимаем трубку, ждем ввода 11-ти цифр, а затем проговариваем все что набрали, собственно в этот контекст я перенаправил callback вызовы.

Подготовились, значит можно начинать.
Делаю callback на свою мобилку, начинаю давить цифири на мобиле, в консоле Астериска вижу:
[ДАТА] DTMF[5031]: channel.c:2351 __ast_read: DTMF begin '9' received on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2355 __ast_read: DTMF begin ignored '9' on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2283 __ast_read: DTMF end '9' received on SIP/gt-00000015, duration 352 ms
[ДАТА] DTMF[5031]: channel.c:2336 __ast_read: DTMF end passthrough '9' on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2351 __ast_read: DTMF begin '8' received on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2355 __ast_read: DTMF begin ignored '8' on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2283 __ast_read: DTMF end '8' received on SIP/gt-00000015, duration 376 ms
[ДАТА] DTMF[5031]: channel.c:2336 __ast_read: DTMF end passthrough '8' on SIP/gt-00000015
и т.д. Во, то что надо, дебаг нажатия кнопок есть.
На одно нажатие в дебаге 4-ре строки. Чем дальше я смотрел в дебаг тем больше понимал, что я нажимаю цифирь один раз, а в дебаге она могла появиться и 2 и 3 раза (т.к. после одного нажатия появлялось более 4-х строк).
Смотрим что вообще мы можем «потрогать» в Астериске на тему DTMF.
Открываем файл sip.conf:
relaxdtmf=yes ; Relax dtmf handling
dtmfmode = rfc2833 ; Set default dtmfmode for sending DTMF. Default: rfc2833
 ; Other options:
 ; info : SIP INFO messages
 ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
 ; auto : Use rfc2833 if offered, inband otherwise
Это глобальные настройки, кроме них так же можно указать dtmfmode и для конкретного пира в его контексте.
Меняли режимы, ситуация не изменялась. Как работало через раз, так и продолжало работать.
Раз так, то смотреть нужно с обоих сторон, т.е. в какой то момент привлекли и девайс Cisco.
Смотрим что же у нас указано в dial-peer:
dial-peer voice 23 voip
 description 4_outgoing_asterisk
 translation-profile incoming fake_aon
 answer-address 0010.....
 session protocol sipv2
 voice-class codec 20
 dtmf-relay rtp-nte  h245-signal h245-alphanumeric
 no vad
В voice-class перечислены кодеки:
voice class codec 20
 codec preference 1 g723r53
 codec preference 2 g723ar53
 codec preference 3 g723r63
 codec preference 4 g723ar63
 codec preference 5 g729r8
 codec preference 6 g729br8
 codec preference 7 gsmfr
 codec preference 8 g726r16
 codec preference 9 g726r24
 codec preference 10 g726r32
 codec preference 11 g711alaw
 codec preference 12 g711ulaw
Решили ужать выбор кодеков до alaw и ulaw, т.к. тот же режим inband работет только с этими кодеками.
Тоже самое сделали и на Asterisk, запретив использование всех кодеков кроме этих двух, для этого в sip.conf, в настройках peer`а, который смотрит на Cisco, указали:
disallow=all
allow = alaw
allow = ulaw
Снова стали менять режимы в sip.conf, пробовать звонить, пофиг, все как было так и осталось.
Полезли на Cisco.com -> Configuring SIP DTMF Features, в частности интересовали предлагаемый самой циской debug:
Verifying SIP DTMF Support
To verify SIP DTMF support, perform the following steps as appropriate (commands are listed in alphabetical order).
SUMMARY STEPS
1. show running-config
2. show sip-ua retry
3. show sip-ua statistics
4. show sip-ua status
5. show sip-ua timers
6. show voip rtp connections
7. show sip-ua calls
Благодаря команде show sip-ua calls видно какой режим DTMF выбран в данный момент:
Call 1
SIP Call ID                : 12abb76a79d610df282e2b237177bfe5@XX.XXX.XXX.XXX
   State of the call       : STATE_SENT_ALERTING (14)
   Substate of the call    : SUBSTATE_NONE (0)
   Calling Number          : 001000119
   Called Number           : 8916XXXXXXX
   Bit Flags               : 0xC0001C 0x100 0x404
   CC Call ID              : 22371
   Source IP Address (Sig ): XXX.XXX.XXX.XXX
   Destn SIP Req Addr:Port : XXX.XXX.XXX.XXX:5060
   Destn SIP Resp Addr:Port: XXX.XXX.XXX.XXX:5060
   Destination Name        : XXX.XXX.XXX.XXX
   Number of Media Streams : 1
   Number of Active Streams: 0
   RTP Fork Object         : 0x0
   Media Mode              : flow-through
   Media Stream 1
     State of the stream      : STREAM_ADDING
     Stream Call ID           : -1
     Stream Type              : voice+dtmf (1)
     Negotiated Codec         : g711alaw (160 bytes)
     Codec Payload Type       : 8
     Negotiated Dtmf-relay    : rtp-nte
     Dtmf-relay Payload Type  : 101
     Media Source IP Addr:Port: XXX.XXX.XXX.XXX:18936
     Media Dest IP Addr:Port  : XXX.XXX.XXX.XXX:14328
     Orig Media Dest IP Addr:Port : 0.0.0.0:0
Итак теперь видно что происходит с двух сторон и какой режим выбирается и снова пробовали разнообразные режимы.
В Инете (в частности на www.voip-info.org/wiki/view/Asterisk+DTMF) иногда народ советовал прям в dialplan указывать режим DTMF перед набором чего-либо, сделать это можно командой SIPdtmfmode:
SIPDtmfMode(inband|info|rfc2833)
Но это как то тоже не очень спасало. После многочасовых разборок решили глянуть, а что у Asterisk`а на тему vad есть.

Решение

В файле codecs.conf:
; voice activity detection [true / false]
; reduces bitrate when no voice detected, used only for CBR
; (implicit in VBR/ABR)
vad => true
Таксссс.. опять же народ в Инете, при разборках с DTMF, советует с первую очередь гасить vad к чертям, делаем это:
vad => false
Далее была обнаружена вот эта статья «Changing DTMF tone frequency in Asterisk«:
Changing the DTMF tones
The Asterisk module dsp.c contains the definitions for DTMF tones. Just look for a part of the source code that says:
static float dtmf_row[] =
{
    697.0,  770.0,  852.0,  941.0
};
static float dtmf_col[] =
{
    1209.0, 1336.0, 1477.0, 1633.0
};
And change that to:
static float dtmf_row[] =
{
        732.0,  809.0,  894.0, 988.0
        /* 697.0,  770.0,  852.0,  941.0 */
};
static float dtmf_col[] =
{
        1270.0, 1404.0, 1551.0, 1715.0
        /* 1209.0, 1336.0, 1477.0, 1633.0 */
};
This will raise all detected DTMF codes by some 40Hz, enough for Asterisk to become completely tone-blind to existing DTMF codes.
Once you made the change, you must recompile Asterisk by:
  • 1. Stopping Asterisk
  • 2. Go to your Asterisk source directory
  • 3. Enter make clean
  • 4. Enter make
  • 5. Enter make install
Note that you still can send Asterisk DTMF codes to transfer the call, start monitoring or what else – as long as you use the new DTMF tone matrix you just input. This is pretty easy to do with most industrial-grade call handling equipment.
«Ну что ж, не грех попробовать»  - сказали мы и выполнили как написано.
Диалпир на циске был приведен к виду:
dial-peer voice 23 voip
 description 4_outgoing_asterisk
 translation-profile incoming fake_aon
 answer-address 0010.....
 session protocol sipv2
 codec g711alaw
 dtmf-relay rtp-nte
 no vad
Наконец то оно заработало, заработало как надо. По крайней мере, после многочасовых тестов, ни одного сбоя в наборе тоном не было. Надеемся что и далее не будет проблем.
Я решил написать все это для того, что бы если кто-то тоже заморочится с этой темой и не будет знать как к этому подступиться, ну и если я вернусь к этому вопросу позднее, чтобы не вспоминать что уже было сделано :) .
Спасибо subnets.ru
Reblog this post [with Zemanta]

Реклама от BigBN