Как получить Отвеченный номер/отвеченный CLID при одновременной переадресации звонков в Астериске?

У меня проблема, уже 20 часов по теме, а решить не могу. Дело в том, что я не могу выставить счет за звонок, потому что не могу получить точный CLID отвеченного номера при одновременной переадресации в Asterisk. ${CDR(src)}, ${CDR(dst)} здесь не помогают.

Я звоню с PSTN +79000000000 на DID +78120000000 и звонок поступает на нашу Астериск. На астериске через тот же транк звонок переадресовывается на другую ТфОП +74950000000 и там отвечает. По завершению вызова в CDR мы видим:

src: 79000000000
dst: 78120000000

и нет информации о последнем звонке 78120000000 -> 74950000000

Я могу использовать переменную CDR для хранения 74950000000 перед вызовом приложения Dial:

Set(CDR(fwd)=74950000000);
Dial(SIP/78120000000/74950000000);

то в CDR при завершении вызова мы можем увидеть:

src: 79000000000
dst: 78120000000
fwd: 74950000000

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

sip.conf

[78120000000]
name=78120000000
type=peer
host=sip.provider.com

extensions.ael

context sequential {
   _.=> {
       Set(CDR(fwd)=74950000000);
       Dial(SIP/78120000000/74950000000);
       Hangup();
    }
    h => {
       Set(BILL_THE_CALL=${ODBC_BILL_THE_CALL()});
       // billing is easily executed thanks to logged fwd in CDR
    }
  }

Но при одновременной переадресации это невозможно:

  context simultaneous {
   _.=> {
       // can't set fwd before call completion, because don't know 
       // if my_cell_phone or softphone will answer
       // my_cell_phone costs 5 cents/min, softfone is free of charge
       Dial(SIP/78120000000/74950000000&SIP/softphone);
       Hangup();
   }
   h => {
       Set(BILL_THE_CALL=${ODBC_BILL_THE_CALL()});
       // billing is impossible because fwd is not logged to CDR
   }
 }

При завершении вызова в CDR мы видим то же самое, что и для последовательного случая, без fwd:

src: 79000000000
dst: 78120000000

и нет информации о последнем 78120000000 -> 74950000000 или на софтфон

Итак, знаете ли вы какой-либо способ получить это имя пользователя, на который был дан ответ, номер, на который был дан ответ, CLID или что-то еще, чтобы иметь возможность выставить счет за звонок?

http://www.voip-info.org/wiki/view/Asterisk+variables

http://www.voip-info.org/wiki/view/Asterisk+func+channel

и т.д. ссылки не содержат ничего полезного для меня.

По звонку также могу подать заявку

sip show channel faf7767642

и увидеть имя пользователя канала, исходный uri и т. д., которые содержат мой номер переадресации, но я не могу получить их оттуда с помощью диалплана. Но когда я звоню:

NoOp(${CHANNEL(username)});

просто ничего не показывает. Есть идеи? Не могу поверить, что я пропустил что-то очевидное. Спасибо!


person Alexey Che    schedule 23.12.2013    source источник
comment
Трудно что-то сказать по предоставленной вами информации, очень вероятно, что у вас есть ограничение на количество подключений к БД. Я рекомендую вам включить отладку звездочки и проверить журнал. Или наймите внешнего консультанта с более высоким навыком звездочки для наблюдения за вашим диалпланом.   -  person arheops    schedule 23.12.2013
comment
Почему вы решили, что это проблема соединения с базой данных, в то время как вся проблема связана с переменными звездочки? БД в полном порядке. Дело в одновременной переадресации. Например, Dial(SIP/client1&IAX/client2); - как узнать, кто ответил на звонок: клиент1 или клиент2? Потому что в CDR такой информации нет. В этом проблема.   -  person Alexey Che    schedule 31.12.2013
comment
Потому что у астериска нет никаких ограничений на количество соединений, и на самом деле не так просто создать ограничение, даже если вы пытаетесь это сделать.   -  person arheops    schedule 31.12.2013
comment
Для набора номера (SIP/client1&IAX/client2); вы можете использовать Dial (Local/client1@internal/n&local/client2@internal/n) и создать расширение client1 во внутреннем контексте, таким образом, у вас будет 3 cdrs и вы увидите. Другое решение использует макрос on-answer в наборе и отметке cdr. В любом случае, делать сложную систему на астериске - плохая идея, если вы не являетесь экспертом и никогда не читали книги/код других систем, таких как freepbx.org.   -  person arheops    schedule 31.12.2013
comment
Спасибо за указание на макрос во время дозвона! Dial(SIP/client1&IAX2/client2,,M(giveme-answered-clid)); и макросы context macro-giveme-answered-clid { _. => { Set(CDR(fwd)=${CHANNEL(peername)}); } на самом деле устанавливают CDR(fwd) на допустимое имя пользователя, на который был дан ответ (т.е. на client1 или client2 - в зависимости от имени пользователя, на которое ответила сторона! Но переменная CDR(fwd) не передается обратно в контекст, где был вызван Dial, и это не работает. .Может стоит использовать глобальную переменную Set(CDR(fwd)=${CHANNEL(peername)},g); - и она будет доступна через любой контекст в любое время?   -  person Alexey Che    schedule 31.12.2013


Ответы (1)


Да, это сработало благодаря выполнению M(x) во время команды Dial() с Set(GLOBAL(var)=${CHANNEL(peername)}) внутри контекста macro-x.

context macro-give-me-answered-clid {
    _. => {
        Set(GLOBAL(simultaneous_call_answered_peer)=${CHANNEL(peername)});
    }
}

context simultaneous {
   _.=> {
     // can't set fwd before call completion, because don't know 
     // if my_cell_phone or softphone will answer
     // my_cell_phone costs 5 cents/min, softfone is free of charge
     Dial(SIP/78120000000/74950000000&SIP/softphone,,M(give-me-answered-clid));
     Hangup();
   }

   h => {
     Set(CDR(fwd)=${simultaneous_call_answered_peer})
     Set(BILL_THE_CALL=${ODBC_BILL_THE_CALL()});
     // billing is ok because fwd is now logged to CDR
   }
} 

Может быть, не красиво, может быть, все же глупо, но работает, и я доволен этим на данный момент. Большое спасибо за помощь, артеопс!

Что касается разработки сложных решений без экспертных навыков, то это идеальный ответ Гая Ричи:

Единственный способ стать умнее — играть с более умным противником.

(c) Револьвер, 2005. Это ЕДИНСТВЕННЫЙ способ стать экспертом.

person Alexey Che    schedule 31.12.2013