quinta-feira, 22 de setembro de 2016

Asterisk® SCF™ Extension States e HINT/BLF em ARA (Realtime)

Extension States

Os estados de extensão são outro conceito importante no Asterisk® SCF™. Os estados de extensão (Extension States) são o que os dispositivos (Endpoints/Devices) SIP assinam para obter informações de presença (a presença SIP é discutida em mais detalhes em um post futuro chamado Presença SIP). O estado de uma extensão é determinado verificando o estado de um ou mais dispositivos. A lista de dispositivos que mapeiam para estados de extensão é definida no Dialplan do Asterisk® SCF™, /etc/asterisk/extensions.conf (ou extensions.lua em LUA, ou ainda extensions.ael em AEL), usando uma diretiva de HINT especial. A próxima figura, é sobre o Mapeamentos de Estados de Extensão, que mostra o mapeamento entre dispositivos, estados de dispositivos (Extension States), e estados de extensão (Device States), além é claro dos próprios Devices..
 

Hints

Para definir um HINTs de estado de extensão no Dialplan do Asterisk® SCF™, o HINT é utilizado como uma palavra chave (keyword), no lugar da prioridade. Aqui está um exemplo simples do Dialplan relacionado à figura acima mostrada, sobre Mapeamentos de Estado de Extensão.

[default]
exten => 1234,hint,SIP/phoneA&SIP/phoneB&SIP/phoneC
exten => 5555,hint,DAHDI/1
exten => 31337,hint,MeetMe:31337

Normalmente, os HINTs são simplesmente definidas junto com o restante da extensão. Este próximo exemplo adiciona entradas de extensão simples para o que aconteceria se cada uma dessas extensões fosse chamada:

[default]
exten => 1234,hint,SIP/phoneA&SIP/phoneB&SIP/phoneC
exten => 1234,1,Dial(SIP/phoneA&SIP/phoneB&SIP/phoneC)

exten => 5555,hint,DAHDI/1
exten => 5555,1,Dial(DAHDI/1)

exten => 31337,hint,MeetMe:31337
exten => 31337,1,MeetMe(31337,dM)

Em nosso exemplo, fizemos uma correlação direta entre o número do ramal do HINT e o número do ramal que está sendo destinado a chamada, embora não seja necessário que esse seja o caso.

Verificando Extension States

A maneira mais fácil de verificar o estado atual em uma extensão é na *CLI> do Asterisk® SCF™. O comando core show hints mostrará todos os HINTs atualmente configurado. Considere a seguinte definição de HINT.

[phones]
exten => 7001,hint,SIP/0004F2060EB4

Quando o core show hints é executado no *CLI> do Asterisk® SCF™, a seguinte saída é apresentada quando o dispositivo (Device/Endpoint) está em uso:

*CLI> core show hints
    -= Registered Asterisk Dial Plan Hints =-
           7001@phones   : SIP/0004F2060EB4    State:InUse    Watchers  0
----------------
- 1 hints registered


Além de mostrar o estado da extensão, a saída do core show hints, também fornece uma contagem de observadores. Um observador é algo no  Asterisk® SCF™ que se inscreveu para receber atualizações sobre o estado desta extensão. Se um telefone SIP assinar o estado de um ramal, a contagem de observadores será aumentada.

O estado da extensão também pode ser recuperada com uma função do Dialplan, EXTENSION_STATE( ). Essa função opera de maneira semelhante à função DEVICE_STATE( ), iremos também em um post futuro descrever sobre essa função. O exemplo a seguir mostra uma extensão que imprimirá o estado atual de outra extensão no *CLI> do Asterisk® SCF™:

exten => 7013,1,Answer()
 same => n,Verbose(3,The state of 7001@phones is ${EXTENSION_STATE(7001@phones)})
 same => n,Hangup()


Quando esta extensão é chamada, esta é a mensagem detalhada que aparece no *CLI> do Asterisk® SCF™:

 -- The state of 7001@phones is INUSE

A lista a seguir inclui os valores possíveis que podem ser retornados da função EXTENSION_STATE( ):
  • UNKNOWN;
  • NOT_INUSE;
  • INUSE;
  • BUSY;
  • UNAVAILABLE;
  • RINGING;
  • RINGINUSE;
  • HOLDINUSE;
  • ONHOLD. 

Device States

Existem dois tipos de dispositivo aos quais os estados do dispositivo se referem: dispositivos reais e dispositivos virtuais. Dispositivos reais são terminais de telefonia que podem fazer ou receber chamadas, como Telefones SIP. Dispositivos virtuais incluem coisas que estão dentro do Asterisk® SCF™, mas fornecem informações úteis de estado. A tabela a seguir, Dispositivos virtuais no Asterisk lista os dispositivos virtuais disponíveis no Asterisk.
 
 
Virtual deviceDescription
MeetMe:<conference bridge>O estado de uma ponte de conferência MeetMe( ). O estado refletirá se a ponte de conferência tem ou não participantes chamados no momento. Mais informações sobre o uso de MeetMe( ) para chamadas de conferência podem ser encontradas na seção chamada “Conferencing with MeetMe( )”.
SLA:<shared line>Informações de estado de Aparência de LInha compartilhada. Este estado é manipulado pelos aplicativos SLATrunk( ) e SLAStation( ). Mais detalhes podem ser encontrados na seção chamada “Shared Line Appearances”.
Custom:<custom name>Estados de dispositivos personalizados. Esses estados têm nomes persolaizados e são modificados usando a função DEVICE_STATE( ). O uso de exemplo pode ser encontrado na seção chamada “Using Custom Device States”.
Park:<exten@context>O estado de uma vaga em um estacionamento de chamadas. As informações de estado refletirão se um chamador está ou não estacionado naquele ramal. Mas informações sobre estacionamento de chamdas no Asterisk® SCF™ podem ser encontradas na seção chamada “Parking Lots”.
Calendar:<calendar name>Estado do calendário. O Asterisk® SCF™ usará o conteúdo do calendário nomeado para definir o estado como disponível (available) ou ocupado (busy). Mais informações sobre integração de calendário no Asterisk podem ser encontradas no capítulo 18 do Livro Asterisk The definitive Guide 3ª Edição, chamada de External Services.


Um estado de dispositivo é um mapeamento simples de um para um para um dispositivo. A figura a seguir, mostra esse maepamento de estado do dispositivo:

 

Verificando os estados do dispositivo

A função do Dialplan DEVICE_STATE( ) pode ser usada para ler o estado atual de um dispositivo. Aqui está um exemplo bem simples de uno no Dialplan:
  
exten => 7012,1,Answer()

; *** This line should not have any line breaks
    same => n,Verbose(3,The state of SIP/0004F2060EB4 is
${DEVICE_STATE(SIP/0004F2060EB4)})
    same => n,Hangup()
 
Se chamarmos o ramal 7012 do mesmo dispositivo do qual estamos verificando o estado, a seguinte mensagem detalhada aparecerá no console do Asterisk® SCF™:
 
-- The state of SIP/0004F2060EB4 is INUSE
 
É importante resaltar que no livro acima citado, no capítulo 20, Asterisk Manager Interface (AMI). A ação do gerenciador GetVar pode ser usada para recuperar valores de estado do dispositivo em um programa externo. Você pode usá-lo para obter o valor de uma variável normal ou de uma função do Dialplan, como o DEVICE_STATE( ).
 
A lista a seguir inclui os valores prossíveis que retornarão da função DEVICE_STATE( ):
  • UNKNOWN
  • NOT_INUSE
  • INUSE
  • BUSY
  • INVALID
  • UNAVAILBLE
  • RINGING
  • RINGINUSE
  • ONHOLD
 

Conclusão

Então após está explicação, eu estava trabalhando em um método para deixar o HINTs/BLF em ARA (Asterisk Realtime Architecture), após alguns dias de pesquisa intensa, encontrei uma solução parcial para o meu desafio, aqui vai algumas dicas, na expectativa de mais alguém ter está necessidade e quem sabe vir a ajudar a melhorar esta funcionalidade ou recurso. 

Mudanças necessárias para o sip.conf: 
  • notifyringing deve ser definido como "yes"; 
  • tanto rtcachefriends e rtupdate definido como "yes"; 
  • limitonpeers deve ser definido como "yes". 
Alterações na tabela SIP TABLE, inserir as seguintes colunas: 
  • "call-limit" do tipo "int";
  • "subscribecontext" do tipo "varchar(80)"
o "subscribecontext" tem de ter o mesmo nome do contexto em que o comandos estão, eu uso "[blf_pbx]". A minha necessidade é de fazer uma "Terminal Inteligente" Virtual.  

Eu já disponibilizei aqui uma maneira de fazer o HINT/BLF funcionar em um aparelho da Khomp o "IPS 212". Claro que esta solução é toda desenvolvida no "extensions.conf" ou no "extensions.ael" de maneira manual ou seja para cada extensão telefônica adicionada no seu PBX IP você tem obrigatoriamente que incluir no "subscribecontext".  Mas se você (como eu) estiver usando "ARA" (Asterisk Realtime Architecture) isto acaba sendo uma inconveniente. 

Este ponto de vista de fazer o HINTs/BFL dinâmico é na verdade um Shell Script que fica sendo executado no CRON. Caso você venha a alterar o Shell Script de maneira que fique melhor agradeceria em compartilhar aqui no post. 

Caso queira mudar o nome do contexto, pode fazê-lo no Shell Script na linha que escrevemos o "switch => realtime/@".  

Em seguida ele escrevera o necessário nos arquivos extensions.conf ou extensios.ael, ou seja, de maneira dinâmica. 
"exten => ,hint,SIP/".


appenddynamic()
{
  mysql -u dbusername -pdbpassword -h dbhostname dbname -se "select distinct(context) from extensions" | grep -v '^context$' | while read context; do
    echo "[$context]" >> $ASTCONF
    echo "switch => Realtime/@" >> $ASTCONF
    if [ $context = "target_context" ]
    then
        echo "exten => 100,hint,SIP/100"
        echo "exten => 101,hint,SIP/101"
    fi
    echo "" >> $ASTCONF
  done
}

Eu realmente espero que faça algum sentido para alguém.

Ishfaq Malik
Software Developer
PackNet Ltd

Fonte: Lista de Discussão Asterisk Developer.

quarta-feira, 21 de setembro de 2016

Usando reSIProcate para conectar Asterisk com WebRTC.

Post Por Daniel Pocock.
Como em um mundo tradicional, "não-WebRTC", o proxy SIP simplesmente facilita chamar entre todos os clientes que ele conhece. Na prática, as implantações geralmente deseja adicionar funcionalidade adicional na forma de um PBX com filas, correio de voz, menus e conferência.

O Asterisk 11,12 e 13 inclui "suporte para WebRTC" embora ainda está evoluindo e eu atualmente não recomendo ligar Asterisk diretamente à Internet pública. Em particular, o Asterisk não suporta recursos como autenticação mútua de TLS com o transporte (WebSocket seguro) WSS. Aqui, nós olhamos como "Repro" pode aceitar conexões de usuários de Internet/Web e retransmiti-las para um servidor Asterisk interno. Aqui está um diagrama da arquitetura:



Observe que as mensagens SIP são aceitos sobre o transporte "WebSocket do Repro" e retransmitida para Asterisk ao longo de um transporte regular SIP TCP. Isso significa que nós nos beneficiamos de suporte "TLS de Repro" também, para que o cliente WebSocket tem uma chance muito maior de escapar do seu firewall do lado do cliente, se a porta 443 é usada (fazer o Repro ser um servidor HTTPS) e os clientes podem ser autenticados com certificados em sua navegador.

Aqui estão os passos para fazê-lo funcionar:


Servidor com Repro e reTurn

Configurar Repro para rodar em um servidor Debian. Verifique se os clientes podem falar com Repro. A pergunta que surge cada vez mais nos dias de hoje: qual é a maneira mais rápida para rodar o "WebRTC" e vê-lo trabalhar? Como pode um desenvolvedor web começar a experimentar WebRTC no seu blog ou demonstração site?
Boa notícia: não é mais necessário copilar ele - e muitos dos componentes estão disponíveis em sistemas baseados em Debian Server (incluindo Ubuntu Server) ou soluções baseadas em RPM, como o Fedora e CentOS.
Vamos a uma rápida verificação de como é fácil, explico abaixo:
# apt-get update
# apt-get install -t experimental repro resiprocate-turn-server
# apt-get install -t unstable chromium sipml5-web-phone
# cd /var/www && mkdir jssip && cd jssip
# wget -r -nH http://tryit.jssip.net
# vim /etc/repro/repro.config
# vim /etc/reTurnServer.config
# vim /var/www/jssip/js/custom.REMOVE_THIS.js

e, em seguida, tentar navegar para "/jssip" ou "/sipml5-web-phone".

Comece com um SIP Proxy

Como explicado no guia "RTC Quick Start" para RTC regular, um proxy SIP é um componente limpo e simples para começar. O mesmo é realmente necessário para WebRTC: iniciar com um proxy. Há dois Vou enfatizar aqui:
  • Repro da reSIProcate é rápido e fácil de configurar e tem suporte embutido TLS. A versão 1.9 alpha com o apoio WebSocket para WebRTC acaba de ser carregado para o "Debian" e está pronto para ser usado em produçãoe. Usuários RPM só precisa baixar o "arquivo tar" e usar rpm build para obter pacotes a partir dele.
  • Kamailio fornece suporte muito bom WebRTC também. Os pacotes estão disponíveis, mas devido a problemas de licença GPL devem ser recompilados com TLS, consulte o arquivo "README" do Kamailio para mais detalhes. Também fiquem a vontade para usar o repositório de "pacotes binários que incluem TLS".

Obter um servidor TURN

servidores TURN, ajudam o fluxo da mídia atravessar NAT. Eles são muito fáceis de configurar, mas devem ter endereços IP reais.

Colocar o JavaScript no servidor Web

Adicionando WebRTC a um Web site pode ser tão simples como cortar e colar um código JavaScript no HTML.
Três amostras de trabalho para começar com:
  • Use o pacote de telefone web "SIPml5" no Debian e adicione a um host virtual, procure "/sipml5-web-phone"
  • Use wget para buscar uma cópia do "JsSIP". Você vai ter uma página de amostra tipo está "tryit.jssip.net". Então edite os arquivos "custom.js" fornecido e altere o endereço do SIP Proxy.
  • QoffeeSIP é outra alternativa.

Browser

Os usuários precisam de um navegador recente. Os últimos Browsers como Google Chrome, Firefox, Opera, IE9 devem funcionar muito bem.

Instalando e configurando Asterisk

Digium, os criadores do Asterisk, atualmente não estão mais apoiando pacotes para Debian e seus forks (Ubuntu), mas eles não fornecem pacotes RPM em seus repositórios de pacotes do "Asterisk".
No entanto, os pacotes binários pré-compilados para Asterisk 11.4 não incluem suporte SRTP. SRTP é uma parte obrigatória do WebRTC. Portanto, tomamos o RPM Fonte (SRPM) e vamos construí-lo manualmente.
Em primeiro lugar, é recomendado que você comece com um servidor CentOSX completamente limpo ou RHELX. Eu construí uma máquina virtual no meu ambiente.  Depois de instalar e configurar uma senha de root, configurar o yum para acessar "EPELX" (eu usei o CentOS6, logo vou usar o EPEL6).
Certifique-se de SELinux e firewall estão desativados de fato (que muitas vezes são ativadas por padrão). Uma maneira rápida de fazer isso:
# sed -i s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config
# reboot
...

# iptables -I INPUT -j ACCEPT

Em seguida, você pode fazer "YUM" sobre o repositório Digium e instalar todas as dependências necessárias para a construção de Asterisk:
# rpm -Uvh http://packages.asterisk.org/centos/6/current/x86_64/RPMS/asterisknow-version-3.0.0-1_centos6.noarch.rpm
# yum update
# yum install rpm-build libsrtp-devel

Em seu diretório pessoal, configurar uma árvore de trabalho para "rpm build":
$ mkdir ~/rpmbuild
$ cd ~/rpmbuild
$ mkdir BUILD BUILDROOT RPMS SOURCES SPECS SRPMS
$ cd SPECS
$ wget http://danielpocock.com/sites/danielpocock.com/files/asterisk.spec
$ cd ../SRPMS
$ wget http://packages.asterisk.org/centos/6/asterisk-11/SRPMS/asterisk-11.4.0-1_centos6.src.rpm
$ rpmbuild --rebuild asterisk-11.4.0-1_centos6.src.rpm

Nesta fase, você vai ter alguns erros, mas veja que foi extraído com sucesso o arquivo no diretório de SOURCES:
$ ls -l ../SOURCES
-rw-r--r--   1 daniel daniel 11573400 May 20 23:07 asterisk-sources-11.4.0.tar.gz
$

Ele também irá reclamar dependências que estão faltando, você vai instalar fazendo uso do YUM:
yum install make gcc gcc-c++ ...

Observe que você tenha baixado uma versão ligeiramente modificada do arquivo asterisk.spec, as razões para isso são explicados nesta lista de discussão . O que se segue agora deve desencadear uma compilação bem-sucedida:
$ rpmbuild -bb \
  --without tds \
    --without misdn \
    --without odbc \
   ~/rpmbuild/SOURCES/asterisk.spec

Felizmente, Digium adicionou o suporte SRTP nas versões 12 e 13 não sendo necessário fazer a compilação que estamos fazendo aqui para o Asterisk 11.4.1.

Configuração do Asterisk: aplicação demo

Aqui só temos de instalar os RPMs e fazer uma alteração rápida da configuração:
$ cd ~/rpmbuild/RPMS/x86_64
$ su -
# rpm -i asterisk*rpm
# yum install asterisk-sounds-core-en-ulaw asterisk-sounds-extra-en-ulaw --enablerepo=asterisk-11
# ln -s /usr/share/asterisk/sounds/demo-* /var/lib/asterisk/sounds/en/

Para habilitar conexões do proxy, precisamos definir algumas configurações não padrão. É essencial para usar o transporte TCP. Como as mensagens SIP de clientes WebSocket são geralmente muito grande para pacotes UDP.  Também é necessária permitir SRTP e AVPF, uma vez que estes são obrigatórios em WebRTC. Aqui uma comparação no arquivo padrão do "/etc/asterisk/sip.conf":

--- /etc/asterisk.orig/sip.conf 2013-06-04 10:57:49.428617785 +0200
+++ /etc/asterisk/sip.conf 2013-06-04 11:18:17.825604261 +0200
@@ -207,7 +207,7 @@
 ; subject to change in any release.  If they are changed, the changes will
 ; be reflected in this sample configuration file, as well as in the UPGRADE.txt file.
 ;
tcpenable=no                    ; Enable server for incoming TCP connections (default is no)
tcpenable=yes                    ; Enable server for incoming TCP connections (default is no)
tcpbindaddr=0.0.0.0             ; IP address for TCP server to bind to (0.0.0.0 binds to all interfaces)
                                 ; Optionally add a port number, 192.168.1.1:5062 (default is port 5060)
 
@@ -1371,6 +1371,13 @@
 ; ...
 ;
 
[1001](public-phone,ulaw-phone)
avpf = yes
encryption = yes
context = public
icesupport = yes


 ; Standard configurations not using templates look like this:
 ;
 ;[grandstream1]

Isso pressupõe que o ID de usuário SIP do seu utilizador WebSocket é 1001. Agora você pode executar o Asterisk:
# service asterisk start

Configurando o SIP Proxy Repro para enviar chamadas para Asterisk

Isto é uma demonstração relativamente simples. O objetivo é enviar chamadas para o número 1000 para o aplicativo de demonstração em Asterisk
Na interface web do Repro, clique em Adicionar rota no menu. Utilize os seguintes parâmetros e deixar todas as outras opções em branco:
  • URI: ^sip:([0-9]+)@
  • Destination: sip:$1@pbx.example.org?transport=tcp
Nota: substituir pbx.example.org com o nome ou o endereço IP do Asterisk para o trunk. Vá para o link do menu ADD USER e adicionar um usuário chamado 1001. O ID de usuário e senha devem ser colocadas no arquivo custom.js para JsSIP.

Testando a partir JsSIP

Presumo JsSIP foi criado seguindo as instruções anterior. Asterisk não suporta o CODEC vídeo de um cliente WebRTC. Para contornar isso, no arquivo "custom.js" para JsSIP, certifique-se de vídeo está desativado por padrão.
No cliente WebRTC, disque 1000. Você deve ouvir a demo saudação do Asterisk.

Solução de possiveis problemas

  • Verifique o registo de JavaScript no navegador;
  • Verifique os logs no SIP Proxy Repro e aumente a verbosidade dos logs, se necessário. Se o nível estiver definido como STACK, você vai ver cópias completas de cada mensagem SIP enviados e recebidos.
  • Conectar ao console Asterisk (comandos UNIX: rasterisco -vvvvgci) e permitir a exibição de mensagem SIP: 
    • *CLI> sip set debug on

terça-feira, 20 de setembro de 2016

Formas de Tarifação em Telefonia IP

Material disponibilizado por Renan Manso (Asterisk Framework Developer), bom proveito!

Sobre o tempo de tarifa:"s"

Exemplo: você determinou que custa 1.00 real a tarifa em tempo "s", então ele vai tarifar por segundo até completar o 1 real, portanto se nessa rota a pessoa falou 30 segundos então sua chamada custara 30 centavos em modo "s".

Sobre o tempo de tarifa:"c"

Em modo "c" a tarifa sera cobrada por chamada pro exemplo a pessoa ligou e ficou 30 segundos, então sera cobrado o valor do minuto inteiro. Por outro lado ela pode ficar o tempo que quiser que vai só custar 1.00 real.

Sobre o tempo de tarifa:"m"

Em modo "m" sera cobrado 1.00 a cada minuto, se você permanecer por 5 minutos sera cobrado o valor de 5 reais. E se forem 5 minutos e 10 segundos? Então sera cobrado 6.00 reais, pois foram cobrados os minutos inteiros.

Sobre o tempo de tarifa:"1m+s"

Em modo "1m+s" o primeiro minuto sera cobrado integral já no primeiro segundo, após o primeiro minuto a tarifa sera dividida por segundo. Por exemplo se você falou 1 minuto e 10 segundos sera cobrado 1,10 reais.

Sobre o tempo de tarifa:"30s+s"

Em"30s+s"sera cobrado metade do valor antes dos 30 segundos, após isso sera cobrado o segundo. Por exemplo a pessoa ficou 12 segundos sera cobrado 0.50 centavos, a pessoa ficou 32 segundos sera cobrado 0.53 centavos.

Sobre o tempo de tarifa:"30s+6s"

Em"30s+6s" sera cobrado metade do valor antes dos 30 segundos após isso sera cobrado o segundo exemplo 12 segundos na chamada.. sera cobrado 0.50 centavos, 32 segundos sera cobrado 0.60 centavos, ele sempre arredonda.

Fonte: Perfil do Renan Linkedin

quinta-feira, 15 de setembro de 2016

Respondendo Detecção de máquina com AMD() e WaitForSilence( ).



Descrição do Algoritmo:
O algoritmo depende da duração da saudação e do silêncio ou falta del que se segue à saudação. Por exemplo, uma pessoa normalmente atender o telefone com um simples Aló?, seguido por um período de silêncio. Essas pessoas também podem ter uma saudação um pouco mais longa, como Aló! Delphini, pois não?, seguida por um período de silêncio. As secretárias eletrônicas normalmente têm saudações muito mais longas, sem longos períodos de silêncio, como Olá! Você ligou para a residência do Delphini, deixe uma mensagem após o bipe

Usando uma função de energia de curto tempo, o algoritmo determina quando uma pessoa está falando e quando ela fez transição para o silêncio e determina se a pessoa chamada é uma pessoa viva ou uma secretária eletrônica.

A taxa de passagem zero de curto tempo é usada para determinar se a energia detectada é fala ou um tom sinusoidal (Um senoide ou sinusoide - também chamado de onda seno, onda senoidal, ou onda sinusoidal - é uma curva matemática que descreve uma oscilação repetitiva suave, sendo esta uma onda contínua. É nomeada após a função seno, leia mais sobre isso aqui. Ou um par de tons, tal como DTMF). O algoritmo AMD rejeitará tons e não os confundirá com possível fala. Isso é necessário porque algumas secretárias eletrônicas podem iniciar sua mensagem com um tom. Além disso, os produtos do tipo Telezapper agora são frequentemente usados para tentar enganar discadores preditivos, reproduzindo um ou uma série de tons (tom de reordenar) antes que a secretária eletrônica ou a pessoa atendam. Este algoritmo precisa rejeitar esses tons e ouvir apenas a fala.

Devido à natureza do processo de detecção descrito aqui, deve-se observar que a taxa de detecção não é e nunca poderá ser 100%. As mensagens da secretária eletrônica podem ser muito diversas, podem incluir música ou outro ruído, etc., todas afetando o algoritmo e seu processo de tomada de decisão. Outro fato importante é que o AMD( ) e WaitForSilence( ) existentes em Open Source Telephony Systems (Asterisk SCF, OpenSER, Kamailio, OpenSIPs e FreeSWITCH),  foram projetados para PSTN (ISDN e POTS), e não para ITSP (SIP), logo é importante ter isso em mente. Outro ponto é que se de fato usa uma ITSP, o CODEC G729a vai derrubar fatores importantes do algoritmo. Mas tenha em mente que como não temos uma rede 100% VoIP, sempre seremos atendido por uma CPA. 

Chaves de registro do discador CPA que afetam o comportamento do AMD:

Valor recomendado da chave de registro (unidades) e Definição do valor padrão (unidades):
  • CPAMinSilencePeriod 375 (ms) e 608 (ms), quantidade de tempo que o sinal deve ser silencioso após a detecção de fala para declarar uma voz ao vivo.
  • CPAAnalysisPeriod 2500 (ms) 1592 (ms), quantidade de tempo (a partir do momento em que o sistema detecta a fala pela primeira vez) em que a análise será realizada no áudio de entrada.
  • CPAMaxTimeAnalysis 3000 (ms) 8000 (ms), o período em que CPAAnalysisPeriod deve iniciar e parar ou a voz será declarada. Este temporizador começa off-hook (fora do gancho).
  • CPAMaxTermToneAnalysis 12000 (ms) 30000 (ms), está é a quantidade de tempo que o algoritmo irá procurar por um bipe de finalização, uma vez que o algoritmo detectou uma secretária eletrônica.
Outras chaves de registro do discador CPA:

Valor recomendado da chave de registro (unidades) e Definição do valor padrão (unidades):
  • CPANoiseThresholdPeriod 100 (ms) 32 (ms), quantidade de tempo que o algoritmo CPA usa para calcular o nível do ruído (Noise Floor).
  • CPAMinimumValidSpeechTime 112 (ms) 112 (ms), quantidade de tempo que essa energia deve estar ativa antes do discurso declarado. Qualquer coisa menos é considerada uma falha.
  • CPAMaxNoiseFloor 10000 10000, limite do limiar de ruído. Não permitido exceder 10000.
  • CPAMinNoiseFloor 1000 1000, Limite do limiar de ruído. Não pode ser inferior a 1000.
  • CPAJitterBufferDelay 150 (ms) 100 (ms), Jitter Buffer Delay.
  • CPAActiveThreshold 32 (dB) 32 (dB), o sinal deve exceder CPAActiveThreshold * CPANoiseThresholdPeriod para ser considerado ativo. Por exemplo, 32 é 10 * log (32) = 15 dB.
Exemplos:
Observação:
  • CPAMaxTimeAnalysis começa na detecção de off-hook (fora do gancho);
  • Assim que o algoritmo AMD( ) declara voz ativa, um possível humano, a chamada é transferida para o ponto de rota;
  • CPAMaxTimeAnalysis é discutível uma vez que a voz é detectada.
Observação:

  • O algoritmo declara secretária eletrônica porque após a detecção de voz, não houve períodos de silêncio de pelo menos CPAMinSilencePeriod de comprimento.
  • Se nenhum bipe for detectado durante o período de CPAMaxTermToneAnalysis, a chamada será transferida no final do período.
  • O algoritmo declarará a secretária eletrônica e começará a procurar o bipe assim que CPAAnalysisPeriod expirar.
  • CPAMaxTimeAnalysis é discutível uma vez que a voz é detectada.
Como podemos ver, isso já não era e agora mais ainda não é uma ciência exata, logo o que você deve fazer, calcular todos esses parâmetros de cada operadora que deseja detectar a secretária eletrônica, agora chamadas de caixa postal, continuarei chamando de secretária eletrônica. O que você deve saber para que os parâmetros do AMD() estejam corretos? Veja a descrição:

AMD([initialSilence,[greeting,[afterGreetingSilence,[totalAnalysis Time,[miniumWordLength,[betweenWordSilence,[maximumNumberOfWords,[silenceThreshold,[maximumWordLength]]]]]]]]])

Argumentos:
  • initialSilence - É duração máxima silêncio inicial antes de saudação. Se esse número for excedido definida como MACHINE;
  • greeting - é o comprimento máximo de uma saudação. Se esse número for excedido definida como MACHINE;
  • afterGreetingSilence - é o silêncio após a detecção de uma saudação. Se esse número for excedido definido como HUMANO;
  • totalAnalysis Time - é o tempo máximo permitido para o algoritmo para decidir se é HUMAN ou MACHINE;
  • miniumWordLength - é a duração mínima de Voz considerada uma palavra;
  • betweenWordSilence - é a duração mínima de silêncio depois de uma palavra para considerar o áudio a seguir para ser uma nova palavra;
  • maximumNumberOfWords - é o número máximo de palavras em uma saudação Se esse número for excedido definida como MACHINE;
  • silenceThreshold - Quanto tempo nós consideramos o silêncio;
  • maximumWordLength - é a duração máxima de uma palavra de aceitar. Se ultrapassado definida como MACHINE.
Agora de detemos essas informações, o que temos que fazer, é pegar os parâmetros para que o algoritmo funcione corretamente, então você vai ter que ter essas informações de cada operadora móvel, e da telefonia fixa, a seguir vamos pensar que temos essas informações.

Descrição Answering Machine Detect - AMD:

Esta aplicação "tenta" detectar atendedores de chamadas no início de uma chamadas de saída. Basta encaminhar para esse aplicativo (Application_AMD) após a chamada ser atendida (somente chamadas originadas, é claro).

Quando carregado, AMD lê "amd.conf" e usa os parâmetros especificados como valores padrão. Esses valores padrão é substituído quando o aplicativo AMD() é chamando com parâmetros.

Esta aplicação define as seguintes variáveis ​​de canal:

  • ${AMDSTATUS} - Este é o estado de detecção do atendedor de chamadas.
    • MACHINE - MÁQUINA;
    • HUMAN - HUMANO;
    • NOTSURE - NÃO TENHO CERTEZA;
    • HANGUP - DESLIGOU.
  • ${AMDCAUSE} - Indica a causa que levou à conclusão de TOOLONG - Tempo Total;
    • INITIALSILENCE - Duração do Silêncio - initialSilence;
    • HUMAN - Duração do Silêncio - afterGreetingSilence;
    • LONGGREETING - Duração da Voz Humana - Greeting;
    • MAXWORDLENGTH - número máximo de palavras - Word Count.

Descrição WaitForSilence - WFS:

Aguarda até que o silêncio necessário seja alcançado (milissegundos), nos tempos de iterações. Um tempo limite opcional especifica o número de segundos para retornar depois, mesmo se não recebermos a quantidade especificada de silêncio.

Use o tempo limite com cuidado, pois isso pode anular o objetivo deste aplicativo, que é esperar indefinidamente até que o silêncio seja detectado na linha. 

Isso é particularmente útil para aplicativos de transmissão de chamada do tipo reverso 911, nos quais é necessário aguardar que uma secretária eletrônica complete sua fala antes de reproduzir uma mensagem. Normalmente, você deseja incluir duas ou mais para que o WaitForSilence saiba como lidar com uma secretária eletrônica; primeiro esperando o áudio terminar, depois esperando o sinal sonoro (bipe), etc. 

Exemplos: 
  • WaitForSilence(500,2), aguardará 1/2 segundo de silêncio, duas vezes;
  • WaitForSilence(1000), aguardará 1 segundo de silêncio, uma vez;
  • WaitForSilence(300,3,10), aguardará 300ms de silêncio, 3 vezes, e retornará após 10 segundos, mesmo que o silêncio não seja detectado. 
Com esses parâmetros o algoritmo vai definir a variável de canal WAITSTATUS para um destes valores: 
  • SILENCE - se encerrado com o silêncio detectado; 
  • TIMEOUT - se encerrado sem que o silêncio seja detectado após o tempo limite. 
Quando utilizando a aplicação WaitForSilence(), há três parâmetros.
  • SILENCEREQUIRED é a duração, em milissegundos, de silêncio que vamos esperar.
  • ITERATIONS é o número de ocorrências do silêncio com duração em milissegundos. 
  • TIMEOUT é o tempo total para a aplicação esperar após o tempo limite para liberar o controle de volta para o Dialplan (em AEL e LUA é mais rápido).
[amd-and-wfs-detect]
exten => s,1,Verbose(AMD and WFS Detect)
 same =>   n,Answer( )
 same =>   n,Set(WFS-SILENCEREQUIRED=2500) 
 same =>   n,Set(WFS-ITERATIONS=1)
 same =>   n,Set(WFS-TIMEOUT="")
 same =>   n,Set(AMD-PARAMETER= 2250|1500|1250|5000|100|50|3|8|256)
 same =>   n,Background(silence/1)
 same =>   n,AMD(${AMD-PARAMETER})
 same =>   n,Verbose("AMD STATUS: ${AMDSTATUS} - ${AMDCAUSE})
 same =>   n,GotoIf($["${AMDSTATUS}" = "MACHINE"]?machine)
 same =>   n,Set(TIMEOUT(response)=5)
 same =>   n,Background(custom/${HUMANMSG})
 same =>   n,Read(ack,,1)
 same =>   n,GotoIf($["${ack}" = "1"]?confirmed)
 same =>   n,HangUp( )
 same =>   n(confirmed), UserEvent(CALLSTATUS,UNIQUEID:${UNIQUEID},V:OK)
 same =>   n,Wait(1)
 same =>   n(machine),UserEvent(CALLSTATUS,UNIQUEID:${UNIQUEID},V:AMD)
 same =>   n,WaitForSilence(${WFS-SILENCEREQUIRED},${WFS-ITERATIONS},${WFS-TIMEOUT})
 same =>   n,Background(custom/${MACHINEMSG}) 
 same =>   n,UserEvent(CALLSTATUS,UNIQUEID:${UNIQUEID},V:AMDALL) 
 same =>   n,Wait(1)
 same =>   n,HangUp( )
Associar ao arquivo chamada.call.
# Este é um exemplo de arquivo que podem ser despejados em /var/spool/asterisk/outgoing
# para gerar um chamada.call 
Channel: SIP/0313939200@inphonex.com.br 
Context: amd-and-wfs-detect 
Callerid: Serviço de Mensagem <(031)39392001>
Extension: s Priority: 1 
#

Este exemplo está configurado para testar uma variedade de atendedores de chamadas. Nós usamos o aplicativo "Set( )" para fornecer acesso fácil para alterar os parâmetros para "WaitForSilence( )".

O "WaitForSilence( ) é usado imediatamente após a "Answer( )" e o Dialplan. Vai esperar "1" segundo para uma ocorrência de silêncio com duração do "2500" milissegundos antes de retornar controle para o Dialplan.

No *CLI> a saída, nos fornece a seguinte observação -- "-- Waiting 1 time(s) for 2500ms silence'. and the next line"-- ou seja que está aguardando "2500ms" de silêncio para executar a próxima linha. Com isto o Dialplan fica aguardando a mensagem da secretária eletrônica para completar, e parar de gravar a voz ou mensagem de entrada. Observe, que cada secretária eletrônica tem o seu próprio tempo limitador para fazer o "TimeOut" antes de desligar a chamada quando não "há áudio/voz detectada".

As configurações acima não foi para detectar um humano e sim detectar o mais rápido possível se a chamada foi atendida por uma secretaria eletrônica. 

Para usar isso, o arquivo da chamada é movido para o "/var/spool/asterisk/outgoing". Asterisk faz a leitura quase que imediato deste arquivo (chamada.call) e processa a chamada.

Esta aplicação define a variável de canal chamado "${WAITSTATUS}" a qualquer "SILENCE" (silencio encontrado) ou "TimeOut" (tempo limite atingido). Neste exemplo, nós estamos somente imprimindo Verbose("${WAITSTATUS}")  mas não estamos agindo sobre ela.


Veja também: AMD( ) , WaitForRing( ).