Upload
luiz-arthur
View
14.138
Download
4
Embed Size (px)
DESCRIPTION
Citation preview
Entendendo melhor o Dialplan
O dialplan é verdadeiramente o coração de qualquer sistema Asterisk, já que define como o Asterisk manipula os telefonemas que chegam e que são enviados. Em resumo, o dialplan consiste de uma lista de instruções ou passos que o Asterisk irá seguir. Estes passos são totalmente personalisaveis.
Sintaxe do dialpan
O dialplan do Asterisk é especificado no arquivo de configuração chamado de /etc/asterisk/extensions.conf.
O dialplan é composto de quatro partes principais: contextos, extensões, prioridades e aplicações .
Contextos
O dialplan é dividido em seções chamadas de contexto, tais contextos evitam que partes diferentes do dialplan interajam umas com as outras. Assim, uma extensão (as funções de um grupo) definida em um contexto é completamente isolada das extensões de outro contexto, a não ser que a interação seja especificamente permitida.
Os contexto são denotados pela colocação do nome de contexto dentro de colchetes [], por exemplo, [incoming]. Todas as instruções colocadas depois da definição de um contexto fazem parte do contexto até que seja definido outro contexto.
Um dos mais importantes usos de contextos é garantir a segurança. Pelo uso correto dos contextos, é possível permitir a determinadas pessoas acesso a algumas funções que não serão disponibilizadas a outras.
Extensões
Uma extensão é uma instrução que o Asterisk irá seguir e é incluída dentro de cada contexto. A extensão é acionada por uma chamada de entrada ou por dígitos sendo discados em um canal. Então as extensões especificam o que acontece às chamadas enquanto seguem seu caminho pelo dialplan.
A sintaxe para uma extensão é a palavra exten seguida por uma seta formada pelo sinal de igual e de maior que:
exten =>
Uma extensão completa é formada pelos seguintes componentes:
● O nome (ou número) da extensão;● A prioridade, na qual cada extensão pode incluir vários passos a ser executado na
chamada;● Aplicação (ou comando) que executa alguma ação na chamada.
Esses três componentes são separados por vírgulas, da seguinte forma:
exten => nome,prioridade,aplicação()
Um simples exemplo:
exten => 123,1,Answer()
Neste exemplo, o nome da extensão é 123, a prioridade é 1 e a aplicação é Answer().
O nome da extensão. Quando lidamos com sistemas telefônicos, temos a tendência de usar números que devemos digitar para fazer outro telefone tocar, mas no Asterisk é possível fazer muito mais, tal como colocar nomes .
Prioridades
Cada extensão pode ter vários passos , chamados de prioridades. Cada prioridade é numerada seqüencialmente e cada prioridade executa uma aplicação específica. Por exemplo, a seguinte extensão pode responder a uma chamada (na prioridade 1) e então desligar (na prioridade 2):
exten => 123,1,Answer()exten => 123,2,Hangup()
Atenção as prioridades devem iniciar em 1 e são numeradas consecutivamente. Caso uma prioridade fique fora de ordem numérica o Asterisk não continua depois dela .
As versões mais recentes do Asterisk, a partir da 1.2, é possível usar um truque para enumerar as prioridades, como por exemplo usar o “n” que indica a próxima , ou seja, cada vez que o Asterisk achar um “n” ele pega o número da prioridade anterior e acrescenta mais 1. Por exemplo:
exten => 123,1,Answer()exten => 123,n,faça alguma coisaexten => 123,n,faça outra coisaexten => 123,n,Hangup()
É possível ainda acrescentar textos as prioridades, por exemplo:
exten => 123,n(texto),faça algo.
Aplicações
As aplicações são os cavalos de batalha do dialplan. Cada aplicação executa uma ação específica no canal em questão, tal como emitir um som, aceitar uma entrada toquetom ou desligar a chamada. Algumas aplicações precisam de argumentos a serem passados juntos com as aplicações para determinar como devem executar suas ações. Para passar argumentos às aplicações, coloqueos entre os parênteses que se seguem ao nome da aplicação, separados por vírgulas.
Um simples exemplo de dialplan
Vamos criar um dialplan simples para entender como este funciona. Em nosso exemplo iremos criar um diaplan para que quando a chamada chegar, o Asterisk irá responder à chamada, tocar um arquivo de som e então desligar a chamada.
Antes de iniciar o dialplan, nós devemos explicar sobre uma extensão especial chamada de extensão “s”, quando as chamadas entram num contexto sem uma extensão específ ica de destino (por exemplo, uma linha FXO chamado), elas são automaticamente manipuladas pela extensão “s”. O “s” indica início (start).
Nosso dialplan irá iniciar com a extensão “s” e executaremos três ações: responder, tocar um arquivo de som e desligar:
[incoming]
exten => s,1,Answer()exten => s,2,Playback(hello-world)exten => s,3,Hangup()
A aplicação Answer() é utilizada para responder a um canal que está chamando, isso faz a configuração inicial do canal que recebe a chamada que está entrando, Answer() não tem argumentos.
A aplicação Playback() é utilizada para tocar um arquivo de som previamente gravado sobre um canal. Ao utilizar a aplicação Playback() a entrada do usuário é simplesmente ignorada. Para utilizar o Playback(), especifique um nome de arquivo sem extensão como argumento, por exemplo, Playback(musica) que fará tocar musica.gsm. O Asterisk vem com muitos arquivos de som profissionalmente gravados, que podem ser encontrados no diretório de som usualmente /var/lib/asterisk/sounds.
A aplicação Hangup() desliga o canal ativo e quem está chamando recebe uma indicação que a chamada foi desligada, devese utilizar essa aplicação ao final do contexto quando quiser terminar a atual ligação para assegurar que o dialplan não continuará sendo utilizado. Essa aplicação não tem argumento.
O dialplan até agora não tem muita utilidade é mais para entender a teoria e testes, caso os canais estejam configurados é possível testálo. Vamos tornar o dialplan mais dinâmico.
Aplicações Background() e Goto()
Uma chave importante para montar sistemas Asterisk interativos é aplicação Background(), que funciona da mesma forma que a Playback(), mas na Background() quando o chamador pressionar uma tecla, ou uma série de teclas, em seu telefone, ela interrompe a música (ou um som qualquer, exemplo um menu de voz) e vai para a extensão que corresponder ao(s) dígito(s) pressionado(s). Se o chamador pressiona o 5, por exemplo, o Asterisk irá para de tocar o arquivo de som e enviar o controle da chamada para a primeira prioridade de extensão 5.
exten =>123,1,Background(hello-world)
O uso mais comum da aplicação Background() é criar menus de vozes , freqüentemente chamados de autoatendentes). Muitas empresas criam menus de vozes para dirigir as chamadas para os ramais adequados, aliviando, assim seus recepcionistas a cada chamada.
Outra aplicação útil é Goto(), que é usada para enviar a chamada para outro contexto, extensão e prioridade . A aplicação Goto() torna fácil se mover programaticamente uma chamada entre duas partes diferentes do dialplan. A sintaxe para a aplicação Goto() nos pede que passemos os argumentos do contexto, da extensão e da prioridade para a aplicação, da seguinte forma:
exten => 123,1,Goto(contexto,extensão,prioridade)
Neste próximo exemplo, iremos tocar o arquivo de amostra de som chamado de vm-enter-num-to-call.gsm. E depois adicionar duas extensões que serão acionadas pelo chamador ao inserir 1 ou 2 no telefone.
[incoming]exten => s,1,Answer()exten => s,2,Background(vm-enter-num-to-call)exten => 1,1,Playback(digits/1)exten => 1,2,Goto(incoming,s,1)exten => 2,1,Playback(digits/2)exten => 2,2,Goto(incoming,s,1)
Então quando os usuários chamam nosso dialplan, eles vão ouvir uma saudação, e devem inserir um digito, se eles pressionarem 1, irão ouvir o número 1 e, se pressionarem o número 2, irão ouvir o número 2. E o Goto() irá fazer tudo ser repetido.
Manipulando entradas inválidas e tempos decorridos
Bem com os exemplos anteriores temos um menu de voz, mas é preciso controlar algumas anomalias, a primeira é a entrada inválida de um usuário, tal função é feita pela extensão “i”.
Outra situação é quando o usuário não digita uma entrada a tempo (o tempo provisório é de 10 segundos), estas chamadas devem ser tratadas pela extensão “t” se o chamador demorar a pressionar um digito depois que Background() tiver terminado de tocar o arquivo de som.
[incoming]exten => s,1,Answer()exten => s,2,Background(vm-enter-num-to-call)exten => 1,1,Playback(digits/1)exten => 1,2,Goto(incoming,s,1)exten => 2,1,Playback(digits/2)exten => 2,2,Goto(incoming,s,1)exten => i,1,Playback(pbx-invalid)exten => i,2,Goto(incoming,s,1)exten => t,1,Playback(vm-goodbye)exten => t,2,Hangup()
Uso da aplicação Dial()
Uma das mais importantes características do Asterisk é sua habilidade para conectar diferentes chamadores , uns com os outros. Isso é especialmente útil se os chamadores aplicarem diferentes métodos de comunicação (SIP, H.323, PSTN, etc).
A sintaxe da aplicação Dial() é um pouco mais complexa que as das outras aplicações, já que utiliza 4 argumentos .
O primeiro argumento é o destino que está tentando chamar, que é feito de uma tecnologia por meio do qual será feita a chamada, uma barra normal e o recurso remoto (normalmente um nome ou número de canal). Exemplo:
exten => 123,1,Dial(Zap/1)
Neste exemplo assumimos que queremos chamar um canal ZAP chamando ZAP/1, que é um canal FXS com um fone analógico conectado. A tecnologia é “Zap” e o recurso é “1”, e o 123 indica que o Asterisk deve chamar o canal Zap/1 quando forem digitados 123.
Também é possível chamar vários canais ao mesmo tempo:
exten => 123,1,Dial(Zap/1&Zap/2&Zap/3)
A aplicação Dial() irá ligar a chamada a aquele que atender primeiro.
O segundo argumento da aplicação Dial() é o tempo decorrido , especificado em segundos. Se não for especificado um tempo, o telefone irá continuar tocando até alguém atender ou que a pessoa chamando desista.
exten => 123,1,Dial(Zap/1,10)
Se a chamada for atendida antes do tempo decorrido, os canais são ligados e o dialplan será concluído. Se o destino simplesmente não responder, Dial() vai para a próxima prioridade na extensão. Se, entretanto, o canal de destino estiver ocupado, Dial() irá para a prioridade n+101 , se a prioridade existir (onde n é a prioridade onde a aplicação Dial() foi chamada). Isso nos permite manipular chamadas não respondidas de maneira diferente das chamadas cujos destinos estavam ocupados.
exten => 123,1,Dial(Zap/1,10)exten => 123,2,Playback(vm-nobodavail)exten => 123,3,Hangup()exten => 123,102,Playback(tt-allbusy)exten => 123,103,hangup()
O terceiro argumento de Dial() é uma seqüência opcional , que pode conter um ou mais caracteres que modificam o comportamento da aplicação Dial(), esta lista é muito grande, então iremos ver apenas a letra “r” que é a mais usada, esta opção indica que a pessoa que fez a chamada irá ouvir um tom de chamada enquanto o canal de destino estiver sendo
notif icado que está sendo chamado, mas nem sempre isto é necessário, pois o Asterisk pode automaticamente fazer tal tom.
exten => 123,1,Dial(Zap/1,10,r)
Vamos fazer agora um DialPlan que permita que falemos com John e Jane.
[incoming]exten => s,1,Answer()exten => s,2,Background(enter-ext-of-person)exten => 101,1,Dial(Zap/1,10)exten => 101,2,Playback(vm-nobodyavail)exten => 101.3,Hangup()exten => 101,102,Playback(tt-allbusy)exten => 102,1,Dial(SIP/Jane,10)exten => 102,2,Playback(vm-nobodyavail)exten => 102,3,Hangup()exten => 102,102,Playback(tt-allbusy)exten => 102,103,Hangup()exten => i,1,Playback(pbx-invalid)exten => i,2,Goto(incoming,s,1)exten => t,1,Playback(vm-goodbye)exten => t,2,Hangup()
O quarto e último argumento da aplicação Dial() é um URL, assim, se o canal de destino tem a capacidade de receber um URL no momento da chamada, a URL especificada será enviada, este argumento é raramente utilizado.
Qualquer um desses argumento de Dial() podem ser deixados em branco.
exten => 123,1,Dial(Zap/1,,r)
Contexto para tratar as chamadas internas
Bem depois de entender como funciona basicamente o dialplan vamos entender como criar mais de um contexto e fazer estes interagirem , lembre que é essa uma das funções do dialplan.
Então vamos criar um contexto chamado (ramais) internos e configurar a capacidade desses dois ramais ligar um para o outro, este novo contexto vai se chamar [internal].
Nós iremos deduzir que já esteja configurado um canal FXS Zap (Zap/1) e um canal FXO (Zap/4) que utilizam o canal [incoming] e um ou mais canal SIP (SIP/jane), que está configurado no contexto [internal]
Nosso dialplan vai ser parecer da seguinte forma:
[incoming]exten => s,1,Answer()exten => s,2,Background(enter-ext-of-person)exten => 101,1,Dial(Zap/1,10)
exten => 101,2,Playback(vm-nobodyavail)exten => 101,3,Hangup()exten => 101,102,Playback(tt-allbusy)exten => 101,103,Hangup()exten => 102,1,Dial(SIP/jane,10)exten => 102,2,Playback(vm-nobodyavail)exten => 102,3,Hangup()exten => 102,102,Playback(tt-allbusy)exten => 102,103,Hangup()exten => i,1,Playback(pbx-invalid)exten => i,2,Goto(incoming,s,1)exten => t,1,Playback(vm-goodbye)exten => t,2,Hangup()
[internal]exten => 101,1,Dial(Zap/1,,r)exten => 102,1,Dial(SIP/jane,,r)
Neste exemplo, foi adicionado duas novas extensões ao contexto [internal]. Dessa forma, a pessoa que estiver utilizando o canal Zap/1 pode pegar o fone e chamar a pessoa que está no canal SIP/Jane discando 102. Pela mesma razão, o telefone registrado como SIP/Jane pode chamar Zap/1 discando 101.
Até agora só foi usado três dígitos, mas é possível utilizar até 80 caracteres, ou seja, também é possível usar letras, é claro que o terminal vai ter de suportar caracteres.
[internal]exten => 101,1,Dial(Zap/1,,r)exten => john,1,Dial(Zap/1,,r)exten => 102,1,Dial(SIP/jane,,r)exten => jane,1,Dial(SIP/jane,,r)
Uso de variáveis
As variáveis podem ser utilizadas em um dialplan do Asterisk para ajudar a reduzir a digitação, melhorar a clareza ou acrescentar lógica ao dialplan.
No Asterisk existem duas formas de referenciar uma variável. Para referenciar o nome da variável, é necessário digitar simplesmente o nome da variável, tal como JOHN. Se, por outro lado for necessário acessar o valor da variável, devese digitar um símbolo de dólar, abrir uma chave, o nome da variável e fechar a chave. Exemplo ${JOHN}.
JOHN=Zap/1exten => 555,1,Dial(${JOHN},,r)
que é igual á:
exten => 555,1,Dial(Zap/1,,r)
Existem três tipos de variáveis no Asterisk: globais, de canal e de ambiente.
Variáveis globais: Se aplicam a todas as extensões em todos os contextos, assim, é possível utilizar as variáveis globais em qualquer lugar do dialplan.
As variáveis globais podem ser declaradas no contexto [globals] no início do arquivo extensions.conf. Ou podem ser definidas programaticamente, usandose a aplicação SetGlobalVar().
[globals]JOHN=ZAP/1
ou
[internal]exten => 123,1,SetGlobalVar(JOHN=Zap/1)
Variáveis de Canal: É uma variável que é somente associada a uma chamada em particular, ou seja, são definidas somente na duração da chamada atual e estão disponíveis somente para o canal que está participando dessa chamada.
As variáveis de canal são definidas por meio da aplicação Set()
exten => 123,1,Set(MAGICNUNBER=42)
Existem variáveis de canal predefinidas em README.variables, mas veremos estas depois.
Variáveis de Ambiente: são uma forma de acesso as variáveis do ambiente UNIX de dentro do Asterisk. E são referenciadas na forma de ${ENV(variável)}, onde variável é o nome da variável UNIX.
Adaptação de modelos
Será impossível acrescentar cada possível extensão ao dialplan , especialmente o caso das chamadas para fora. Imagine um dialplan com uma extensão para todos os números que se pode discar? Impossível não é!
Felizmente, o Asterisk tem uma forma para solucionar isso: adaptação de modelos, que permite que se utilize uma seção de código para muitos ramais diferentes.
Sintaxe da adaptação de modelos
Ao utilizar a adaptação de modelos, é necessário utilizar letras e símbolos para representar os possíveis dígitos que queremos adaptar. Os modelos sempre começam com um sublinhado (_). Isso diz ao Asterisk que estamos adaptando sobre um modelo, e não um nome de extensão.
Depois do sublinhado, devese utilizar um ou mais dos seguintes caracteres:
X Adapta qualquer dígito de 0 a 9.Z Adapta qualquer dígito de 1 a 9.N Adapta qualquer dígito de 2 a 9.
[17] Adapta qualquer dígito na faixa indicada. No caso do 1 ao 7.
Para utilizar a adaptação de modelos no dialplan, simplesmente é necessário colocar no lugar do nome ou número da extensão a adaptação:
exten => _NXX,1,Playback(auth-thankyou)
Neste exemplo, o modelo deve adaptar quaisquer ramais de 3 dígitos de 200 a 999 (lembrese o N adapta qualquer dígito entre 2 e 9, e cada X entre 0 e 9. Isto que dizer que se um chamador digitou qualquer ramal de 3 dígitos entre 200 a 999 nesse contexto, ele deverá ouvir o arquivo de som atuth-tahkyou.gsm.
Se tiver mais do que um modelo que se adapte a chamada (ao ramal discado) o Asterisk utilizará o mais específico. Digamos que tenhase digitado 5551212:
exten => _555XXXX,1,Playback(digits/1)exten => _55512,1,Playback(digits/2)
Neste caso, o chamador ouvirá o digito 2
Uso de variável de canal $(EXTEN)
Bem e se tivermos que saber quais números foram discados em uma adaptação de contexto? Bem neste caso o Asterisk define a variável de canal ${EXTEN} para os dígitos que foram discados. Nós podemos usar uma aplicação chamada SayDigits() para testar esta funcionalidade.
exten => _XXX,1,SayDigits(${EXTEN})
Freqüentemente, é útil se manipular o ${EXTEN} removendo um certo número de dígitos da frente da extensão. Isto é feito usandose a sintaxe ${EXTEN:x}, onde x ;e o número de dígitos que quer se remover.
Por exemplo, se o valor de EXTEN é 95551212, então ${EXTEN:1} é 5551212.
exten => _XXX,1,SayDigits(${EXTEN:1})
Se o x for negativo será obtido os últimos dígitos x do ramal discado.
exten => _XXX,1,SayDigits(${EXTEN:-1})
Habilitações de discagem de ligações externas
Agora que já foi apresentado a adaptação de modelos, podemos fazer ligações externas.
Então podemos acrescentar uma variável ao contexto [globals] para definir quais canais serão utilizados para fazer ligações externas:
[globals]JOHN=Zap/1
JANE=SIP/janeOUTBOUNDTRUNK=Zap/4
Vamos criar um contexto para ligações externas, isto é necessário para colocar um pouco de segurança, regular e controlar as ligações externas (quem pode fazer ligações externas).
Então vamos criar um contexto chamado [outbound-local]. Vamos usar o número 9 no início, de forma que os usuários deveram usar o 9 para chamar um número externo.
[outbound-local]exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})exten => _9NXXXXXX,2,Congestion()exten => _9NXXXXXX,102,Congestion()
Então neste contexto anterior, nós acrescentamos uma variável global chamada OUTBOUNDTRUNK, que irá controlar qual ramal será utilizado para fazer ligações externas.
Nós também adicionamos um contexto para ligações externas locais. Na prioridade 1, nós pegamos o ramal discado, eliminando o 9 com a sintaxe ${EXTEN:1} e então tentamos discar aquele número no canal significando pela variável OUTBOUNDTRUNK.
Se a chamada funcionar, o chamador é ligado ao canal de saída. Se a chamada falhar, por que o canal está ocupado, ou porque o número não pode ser discado por qualquer razão, a aplicação Congestion() é chamada e toca um “sinal de ocupado”, para permitir que o chamador saiba que sua chamada falhou.
Ao discar o 9 não será fornecido realmente uma linha externa como em um sistema PBX tradicional, mas sim aparecerá um silêncio, caso queirase um tom de discagem adicione ao contexto:
ignorepat => 9
Que diz ao Asterisk para continuar a tocar o tom de discagem mesmo depois de o chamador discar o 9.
É sempre interessante permitir que o dialplan possa discar para números de emergência:
[outbound-local]exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})exten => _9NXXXXXX,2,Congestion()exten => _9NXXXXXX,102,Congestion()
exten => 190,1,Dial(${OUTBOUNDTRUNK}/190)
Inclusos
O Asterisk permite que utilizemos um contexto dentro de outro contexto por meio da diretiva include. Assim o include é utilizado para fornecer acesso a diferentes seções do dialplan. Nós utilizaremos a funcionalidade include para permitir que usuários do contexto [internal]
(da rede local) tenham a capacidade de fazer chamadas para telefones externos (rede PSTN, no nosso caso).
Estrutura do include
A definição de include toma a seguinte forma, em que context é o nome do contexto remoto que gostaríamos de incluir no contexto atual:
include => context
Quando existirem contextos dentro do contexto atual, é necessário observar a ordem em que estamos incluindo os contextos, já que o Asterisk irá primeiro tentar corresponder a extensão do contexto atual, se este falhar o Asterisk chamará o primeiro que aparecer e se der errado o próximo e assim por diante, na ordem que forem incluídos.
Vamos ao último exemplo usando os inclusos:
[globals]JOHN=Zap/1JANE=SIP/janeOUTBOUNDTRUNK=Zap/4
[incoming]exten => s,1,Answer()exten => s,2,Background(enter-ext-of-person)exten => 101,1,Dial(Zap/1,10)exten => 101,2,Playback(vm-nobodyavail)exten => 101,3,Hangup()exten => 101,102,Playback(tt-allbusy)exten => 101,103,Hangup()exten => 102,1,Dial(SIP/jane,10)exten => 102,2,Playback(vm-nobodyavail)exten => 102,3,Hangup()exten => 102,102,Playback(tt-allbusy)exten => 102,103,Hangup()exten => i,1,Playback(pbx-invalid)exten => i,2,Goto(incoming,s,1)exten => t,1,Playback(vm-goodbye)exten => t,2,Hangup()
[internal]include => outbound-localexten => 101,1,Dial(Zap/1,,r)exten => 102,1,Dial(SIP/jane,,r) [outbound-local]exten => _9NXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})exten => _9NXXXXXX,2,Congestion()exten => _9NXXXXXX,102,Congestion()
exten => 190,1,Dial(${OUTBOUNDTRUNK}/190)
O include possibilita que chamadores do contexto [internal] façam chamadas externas.
Nós só abordamos funcionalidades básicas, existem muitas funcionalidades mais avançadas que podem ser estudadas, mas os conceitos vistos aqui são conceitos básicos para qualquer dialplan e através desses é possível implementar muitos sistemas Asterisk.