Posts Tagged ‘agi’

CDR no Asterisk, nada bom :(

Thursday, August 20th, 2009

O Call Detail Record no Asterisk PBX é feito por um modulo homônimo que aceita diversos backends para persistencia dos dados em SGDB’s, csv, odbc, etc. Sua força está na sua simplicidade quanto ao uso, já vem por padrão no Asterisk e funciona muito bem para a maioria dos casos. Mas nem tudo são flores, dentre seus problemas mais graves estão: inconsistencia na gravação do status da ligação em transferencias cegas, ligações que deveriam ser ANSWER estão NOANSWER. Nenhuma confiabilidade nos dados de transferencia assistida. O campo ‘uniqueidNÃO É UNICO.

Asterisk sobre Você

Asterisk sobre Você

Ainda há o fato da tabela do banco de dados ter uma estrutura travada e não mapeavel, o que faz com que a customização da mesma seja um processo doloroso e até mesmo inviável.

O que fazer? Fazer um só pra você horas. Todo bom nerd que se prese acha sabe que pode fazer melhor. Então vamos ver como poderemos criar nosso próprio cdr com ajudinha de alguns AGI’s.

Um script AGI que você executa após cada tentativa de Dial() e que grava automaticamente informações como DIALSTATUS, BILLSEC, DUURATION se mostra mais eficiente já que pode-se adaptar a gravação do log conforme a sua estrutura de controle de ligações.

Até ai tudo bem, podemos fazer o controle de ligações simples com as informações que eu bem entender, mas ainda nos resta as ligações que passam por filas de atendimento e ligações que são transferidas.

Filas: Aqui temos um problema, a forma nativa de executar um AGI dentro da app_queue não é satisfatória já que ela executa o script somente quando a ligação é atendida pelo membro da fila. Assim perdemos o status das primeiras ligações caso elas tenham sido recusadas e as informações são as mesmas que colcoar o agi para executar depois da execução do Queue() no dialplan.

Podemos nesse caso, implementar uma Queue via AGI ou Monitorar o Queue log em busca dessas informações.

A solução mais elegante ao meu ver é modificar a aplicação do Queue para que ao invés de implementar o dial diretamente seja possível direcionar para um contexto, assim é possível monitorar todo o comportamento da ligação e da fila em geral. (entra na TODO list)

Transferencias: As transferencias é um problema simples de resolver, ao setar a variavel global TRANSFER_CONTEXT para um contexto qualquer você consegue executar seu AGI lá dentro e resolver esse problema, com um pouco de esforço ainda se pode gerar uma estrutura complexa e bonita com árvore de chamada para não perder os dados da ligação geral e ainda ter o status da ligação primária.

Sempre há a possibilidade de se esperar pela próxima versão, não testei a versão 1.6 do asterisk ainda. Mas até onde fui informado ela teria solucionado esses bugs. Mas ainda sobra a rigidez estrutural.

update: encontrei uma boa discussão sobre o assunto e sobre esses problemas em uma lista de discussão da Digium: http://lists.digium.com/pipermail/asterisk-dev/2008-November/035305.html

update2: nessa discussão tem uma documentação que resume algumas coisas e explana outras, vale a leitura: http://svn.digium.com/svn/asterisk/team/murf/RFCs/

Capturas por grupo no Asterisk

Saturday, July 11th, 2009

AsteriskUm dos problemas que enfrentamos em sistemas com Asterisk é a captura por grupo. Elas não funcionam quando se tem tecnologias diferentes em ramais e/ou se usa driver de canais de terceiros. Administrar isso se torna uma tarefa monstruosa e épica caso seu sistema seja muito grande, já que apesar de macros e modelos nos arquivos de configuração de tecnologias você precisa administrar vários deles, tarefa esta que se torna especialmente dolorosa em sistemas integrados com ramais espelhados em banco de dados.

Uma solução que eu implementei com sucesso até agora é a implementação manual de um sistema de capturas usando um script AGI e a app Pickup presente por padrão no Asterisk.

A aplicação Pickup efetua capturas de ligações recebendo como parâmetro uma extensão em um contexto. Esse tipo de captura não me ajuda em nada na maioria das vezes mas a app Pickup tem uma boa carta na manga: o contexto PICKUPMARK.

Quando o contexto passado como parâmetro para a aplicação é PICKUPMARK a aplicação vai procurar ligações que contenham a variável de canal definida como o conteúdo do exten.  Ex: Pickup(desenvolvimento@PICKUPMARK) irá procurar ligações que contenham a variável PICKUPMARK definida como ‘desenvolvimento’.

Para marcar e  capturar é necessário encontrar o real realizador da chamada e resolver seu grupo, para isso eu uso um script AGI que faz a identificação do grupo de captura baseado no callerid do originador da chamada.

;Configuração para extensão de captura
exten => _*8,1,AGI(resolv_pickup_group.php,${CALLERID(num)})
exten => _*8,n,Pickup(${PICKUPGROUP}@PICKUPMARK)
exten => _*8,n,Hangup

O funcionamento desse AGI é muito simples, o que ele faz é uma consulta no banco de dados onde estão configurados meus ramais e retornar o grupo de captura referente ao ramal passado como parâmetro.

Usa-se o mesmo script para definir o grupo da ligação quando uma ligação é efetuada para o ramal, não esqueça de executar isso antes de cada dial para o ramal que se deseja ter essa feature ativa.

;Configuração para extensão de captura
exten => _X.,1,AGI(resolv_pickup_group.php,${CALLERID(num)})
exten => _X.,n,Set(__PICKUPMARK=${PICKUPGROUP})
exten => _X.,n,Dial(${EXTEN},60,twk)
exten => _X.,n,Hangup

Perceba o pulo do gato: ao atribuir a variável eu estou usando dois _ (underlines) antes do nome da variável para determinar herença infinita na variável. Assim não é necessário defini-la como variável global e sem isso a captura não funciona quando se tem ligações concorrentes.