Manual

do

Maker

.

com

Configurar PBX Asterisk no Raspberry Pi

Configurar PBX Asterisk no Raspberry Pi

Há um bom tempo eu mostrei como configurar um PBX Asterisk no notebook/desktop com Linux, para controlar um LED RGB conectado a um Arduino através de uma URA (Unidade de Resposta Audível). Dessa vez, vamos dispensar qualquer microcontrolador, configurando tudo do Asterisk no Raspberry Pi e vamos configurar um ramal para um softphone.

Aplicação

E para quê ter um PBX em casa? Bom, uma das razões pode ser justamente controlar GPIO através de uma URA. Vamos começar pelo básico, depois do artigo eu publico um video no canal DobitAoByteBrasil e discorro mais a respeito.

Primeiro passo - Instalando pacotes

O Asterisk é bastante modular. Nessa instalação haverão coisas que não serão utilizadas agora, mas esse artigo será referência para outros, por isso sugiro que instale tudo conforme recomendado. Mas antes, temos que burlar um problema. Faça o seguinte:

cd /tmp
wget -c wget -c https://raw.githubusercontent.com/asterisk/third-party/master/pjproject/2.6/pjproject-2.6.tar.bz2
md5sum pjproject-2.6.tar.bz2 >pjproject-2.6.md5

Só mostro meus sorrisos, as lágrimas não estão dispostas nos artigos. Esse processo aparentemente "estranho" vai resolver um problemão.

Pegue a versão mais atual do Asterisk ou a versão que condiga com sua distribuição Linux.

sudo su
apt-get update
apt-get -y install subversion libspeexdsp-dev unixodbc-dev \
libmariadbclient-dev-compat libnewt-dev libncurses5-dev uuid-dev \
libxml2-dev libsqlite3-dev libssl-dev --allow-unauthenticated

apt-get -y install make gcc g++ libxml2 libxml2-dev ssh libncurses5 \
libncursesw5 libncurses5-dev libncursesw5-dev linux-libc-dev sqlite \
libnewt-dev libusb-dev zlib1g-dev default-libmysqlclient-dev libsqlite0 \
libsqlite0-dev bison openssl libssl-dev libeditline0 libeditline-dev \
libedit-dev mc sox libedit2 libedit-dev curl apache2 \
libapache2-mod-php7.0 php-pear openssh-server build-essential \
openssh-client zlib1g zlib1g-dev libtiff5 libtiff5-dev \
libnet-telnet-perl mime-construct libipc-signal-perl libmime-types-perl \
libproc-waitstat-perl mpg123 libiksemel-dev libjansson-dev libjansson4
 --allow-unauthenticated

cd /usr/src

wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz

tar zxvf asterisk-13-current.tar.gz 

cd asterisk-13.18.3/

./configure --with-pjproject-bundled NOISY_BUILD=yes

Se você chegar na tela seguinte, parabéns, primeiro passo concluído. Se não chegou, supra as dependências. Eu levei praticamente um dia inteiro pra acertar a configuração até aqui. Seja perseverante.

asterisk-first_step-300x248.webp

Segundo passo - configurar add-ons

Agora no menu vamos selecionar alguns ítens. à direita, selecione os ítens marcados com asterisco.

asterisk-menuconfig.webp

Com Tab, alterne para Save & Exit. Agora 2 comandos extremamente demorados. Vá almoçar, jantar, dormir, tomar café da manhã, fazer uma hora de esteira, jogar um video-game, pintar um quadro e volte para ver se deu certo.

make -j4

O parâmetro -j4 é para utilizar os 4 núcleos, senão ele vai compilar tudo em 1 só, e aí meu amigo, case hoje e volte nas bodas de prata.

Após a compilação...

asterisk-compiled-300x103.webp

Se a compilação ocorreu sem erros, parabéns, agora já podemos instalar o asterisk. Vamos fazer o que está descrito ao final da mensagem:

make install

asterisk-make_installed-239x300.webp

Dá pra ser mais rápido?

Claro que dá, mas como eu estava com preguiça, fiz desse jeito mesmo, "ao vivo". Só que poderia ter sido feito a partir de uma imagem no computador, de modo a aproveitar o processamento de uma plataforma x86. Se desejar, siga esse tutorial para preparar a imagem.

Terceiro passo - Configurar o Asterisk no Raspberry

Agora as configurações envolvem conceitos, os quais você poderá adquirir depois. Vamos focar em fazer funcionar primeiramente.

Configurar um ramal

Vamos configurar um ramal. Os ramais são configurados no arquivo /etc/asterisk/sip.conf. No final do arquivo, adicionei um ramal para utilizar nesse artigo:

[general]
transport=udp

[friends_internal](!)
type=friend
host=dynamic
context=arduino
disallow=all
allow=ulaw

[djames](friends_internal)
secret=1234

[12345](friends_internal)
callerid=DobitAoByte
secret=1234
host=dynamic
type=friend
context=casa

Configurar um contexto

Um contexto é o processo que deverá ocorrer em resposta a uma situação, no sentido literal. O número a ser discado será 8888. Quando o ramal discar para 8888, o contexto correspondente será o arduino. O número que segue a discagem é o primeiro passo> Supondo que a discagem fosse encaminhada para o contexto arduino e depois tivesse um segundo passo, ele retornaria para dar sequência. Mas não é o caso.

Estou replicando primeiramente o exemplo do Arduino citado ao início desse, justamente para testar a funcionalidade. Se estiver funcionando da mesma forma, podemos avançar com tutoriais. Mas invés de conectar um Arduino, agora vou abrir um socket UDP em meu desktop e apenas imprimir os valores advindos da rede. Ainda assim vou manter o nome do contexto para realmente replicar a configuração e provar o conceito.

Vamos agora criar o contexto editando o arquivo /etc/asterisk/extensions.conf:

[arduino]

exten => 8888,1,Goto(arduino,s,1)

exten => s,1,Answer()
exten => s,2,NoOp(Ligação entrou na URA)
exten => s,3,Background(dobitaobyte)
exten => s,4,NoOp(Digite a opção...)
exten => s,5,WaitExten(10)

exten => 1,1,AGI(udp.py,"Opcao_UM")
exten => 1,2,GoTo(arduino,s,4)

exten => 2,1,AGI(udp.py,"Opcao_DOIS")
exten => 2,2,GoTo(arduino,s,4)

exten => 3,1,AGI(udp.py,"Opcao_TRES")
exten => 3,2,GoTo(arduino,s,4)

exten => 4,1,AGI(udp.py,"Saindo-QUATRO")
exten => 4,2,Hangup()

exten => 1234,1,Background(dobitaobyte)
exten => 1234,2,Hangup()

As primeiras 5 linhas estão relacionadas ao tratamento da ligação. Em seguida, os passos 1,11,2se referem à escolha feita na URA. Do mesmo modo, a opção 23, que também possuem dois passos cada. Ou seja, ao entrar no contexto, ele executa um script AGI com o parâmetro numérico que o segue, então volta para o contexto de s no passo 4, que é onde se seleciona uma opção. Apenas na escolha do passo 3 a ligação é encerrada. Não estranhe a extension global dentro do contexto.

O parãmetro Background(dobitaobyte) toca um áudio antes da interação com a URA. O áudio deverá estar em /var/lib/asterisk/sounds.

É um processo diferente, mas não é complicado, certo?

As últimas duas linhas são para outro número dentro do mesmo contexto. Se esse usuário discar 1234, tocará o áudio e fará hangup em seguida. O áudio pode ser qualquer um, desde que siga o padrão descrito mais adiante.

Criar o script AGI

O script Python para o envio de dados via socket UDP deve ficar em /var/lib/asterisk/agi-bin. Seu conteúdo deverá ser o seguinte:

#!/usr/bin/env python
import socket
import sys

UDP_IP="192.168.1.7"
UDP_PORT=8888
MESSAGE = sys.argv[1]

try:
  if not sys.argv[1]:
    print "Passe o r,g,b como parametro"
    print ""
except:
  print "Passe o R,G,B como parametro no formato decimal separado por virgula"
  print ""

#print "UDP target IP:", UDP_IP
#print "UDP target port:", UDP_PORT
#print "message:", MESSAGE

sock = socket.socket( socket.AF_INET, # Internet
socket.SOCK_DGRAM ) # UDP
for i in range(3):
  sock.sendto( MESSAGE, (UDP_IP, UDP_PORT) )

Qualquer porta acima de 1024 é permitida, fica a seu critério. O IP deve corresponder ao IP do host que receberá a mensagem.

O UDP não garante a entrega de pacotes, não tem CRC, não entrega ordenadamente. Por isso preferi fazer um loop e enviar 3 vezes a mesma mensagem, apenas para garantir sua transmissão. Se sua rede estiver ruim a ponto de não conseguir entregar o pacote em 3 tentativas, talvez esteja na hora de uma manutenção por aí.

Criar o arquivo de áudio

Tem algumas maneiras de fazer isso, escolha a sua.

Google Translator

Não gosto de trapaça, mas acho que não tem nada que nos impeça de utilizar o Google Translator para gerar a voz. Se desejar fazê-lo, o procedimento é o seguinte:

1 - Remova todos os arquivos de midia do cache do Google Chrome:

rm -f "~/.cache/google-chrome/Default/Media Cache/*"

Depois acesse o site translator.google.com e digite o texto em português, então clique em Falar (ícone do canto esquerdo). Após, o arquivo estará lá no cache de mídias do browser:

voice-google_translator.webp

Nuance Vocalizer Expressive

Se quiser um ótimo resultado, pode pegar uma demonstração do Loquendo. Entre com o texto, selecione o idioma e a voz de quem vai falar e o arquivo será automaticamente baixado. Porém esse vocalizador expressivo da Nuance não é gratuito e os áudios gerados por ele não podem ser utilizados comercialmente sem uma licença, ok? Baixe o arquivo, brinque, faça uso pessoal e considere comprar uma licença caso deseje criar um produto.

Na época da criação desse artigo, Loquendo era o que tinha de melhor. Hoje temos opções incrivelmente boas que podem ser contratadas como serviço ou compra única, como o Re-voicer, baseado em aprendizado de máquina.

Linux TTS

Tem soluções gratuitas para Linux, inclusive sendo possível gerar a voz diretamente no asterisk usando text-to-speech. Se não me engano, o padrão do Asterisk é o Festival. Uma lista extensa das possiblidades podem ser vistas nesse link.

Se quiser fazer TTS on-the-fly no Google Translator, pode usar esse script perl.

Converter o áudio para GSM

Para o Asterisk tocar o áudio adequadamente, é necessário que alguns parâmetros sejam definidos; 8KHz, mono e GSM. Para converter um arquivo comum como um desses supracitados, utilize o seguinte comando:

sox dobitaobyte.wav -r 8000 -c1 dobitaobyte.gsm

Sei que não é necessário dizer que o nome do arquivo corresponde ao que foi especificado no arquivo extensions.conf, certo?

Executar o asterisk

Para executar, simplesmente digite asterisk, que rodará o serviço em segundo plano. Se não houver nenhum erro na configuração ou nas dependências, você conseguirá acessar o console com alguns diferentes parâmetros. O mais básico:

asterisk -r

Para ver o plano de discagem configurado conforme os passos anteriores, digite:

dialplan show arduino

Isso deve retornar a configuração do plano de discagem que criamos no arquivo extensions.conf.

asterisk-dialplan_show_arduino.webp

Para ter maior verbosidade, inclua um monte de 'vvvvv' antes de iniciar o prompt do Asterisk:

asterisk -rvvvvvvvv

Para saber se a porta SIP está disponível no sistema, digite:

netstat -naut|grep 5060

Que deve retornar algo como:

asterisk-sip_port.webp

Agora precisamos configurar um softphone.

Softphone

O softphone lhe permitirá estabelecer uma conexão SIP com o PBX Asterisk. Instale-o e siga o Wizard.

sudo apt-get install linphone 
linphone

Apenas configure usuário, senha e sip server. Depois, disque para 8888.

asterisk-calling_dobitaobyte.webp

O video está disponível no canal DobitAoByteBrasil no Youtube, não deixe de dar seu like e se inscrever no canal, valeu?

Conclusão

A conclusão é que não tem nada concluído. Isso foi só um exemplo de URA, mas tem uma quantidade enorme de configurações ainda, inclusive várias que não dá pra fazer no Raspberry. Mas com isso, já podemos interagir com os GPIO do Raspberry de uma maneira diferente. O contexto arduino está configurado para executar o mesmo AGI com diferentes parâmetros, mas podemos executar diferentes AGIs para diferentes mensagens, basta gravar uma introdução e depois, uma mensagem para cada ítem. Utilizando o festival para fazer text-to-speech é possível obter informações do sistema através desses scripts e por fim, criar muitas outras coisa!

Para discar de ramal para ramal é necessário uma configuração um pouco diferente, vou tentar escrever mais a respeito.

Inscreva-se no nosso canal Manual do Maker no YouTube.

Também estamos no Instagram.

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.