Mobilidade é uma palavra chave no atual cenário empresarial.
Ter acesso constante a seus documentos, sistemas e até mesmo ao seu ramal telefônico é um dos pilares da produtividade numa época em que passamos grande parte do dia conectados e disponíveis.
Essa “necessidade” traz junto alguns “desafios” , e um deles é o tema deste post.
Contextualizando
Vamos imaginar a seguinte situação: você está aguardando a ligação de alguns fornecedores para dar retorno urgente a seus clientes. Eles vão ligar para você hoje, diretamente para o seu ramal (1000, por exemplo) que está configurado no telefone IP de sua mesa, mas nem todos tem como lhe informar o horário em que farão as chamadas.
Porém hoje é o dia do workshop para os novos colaboradores, que já estava agendado há duas semanas, e você, como um dos responsáveis pelo setor, terá que ficar o dia inteiro na sala de treinamento, que fica em outro andar do prédio, ou seja, distante da sua mesa.
Felizmente a sala de treinamento possui um telefone IP (ramal 1050) e seu chefe autorizou que você interrompa o workshop para tratar desta situação urgente quando for necessário.
Para resolver este caso existem várias abordagens:
- A mais comum seria programar o desvio (siga-me) do seu ramal (1000) para o ramal da sala de treinamento (1050).
Essa abordagem, que é de simples implementação, permitiria que você recebesse as ligações para seu ramal no telefone da sala de treinamento. Aém disso, ela seria transparente para o fornecedor, que ligou diretamente para o seu ramal e nem tomaria conhecimento do desvio.
Essa abordagem, no entanto, não contempla as chamadas saintes e é aí que está a falha da mesma, pois:
- As ligações que fosse fizesse do telefone da sala de treinamento para os clientes seriam identificadas com o ramal da sala e não com o seu ramal.
- O ramal da sala de treinamento, por ser usado de forma geral pelos colaboradores, poderia não ter permissão de discar para números externos, fazendo chamadas só para outros ramais.
- A empresa pode ter um controle de saldo para os ramais, e apesar de seu ramal ter crédito de sobra, o ramal da sala de treinamento está sem saldo disponível.
Essas, é claro, são apenas algumas das possibilidades que podem tornar esta abordagem um problema.
- A outra opção seria praticamente uma “gambiarra”. Você configuraria o seu ramal em um softphone no notebook, e, para evitar que seu telefone fique também se registrando com o ramal, desligaria o mesmo.
Isso vai funcionar? Claro que vai, mas convenhamos que essa é uma prática lamentável, não é? 🙂
Certamente existem outras abordagens, mas que tal implementar uma maneira plenamente funcional e, porque não dizer, elegante para resolver esta questão.
Uma nova abordagem
A solução proposta é simples: você pode autenticar seu ramal em qualquer outro telefone IP ou softphone da rede, fazendo com que o mesmo passe a agir como se estivesse configurado com seu próprio ramal.
Mas o que isso muda em relação as abordagens anteriores?
Como esta abordagem o ramal temporário (no caso do exemplo, o ramal da sala de treinamento) passará a agir como o seu próprio ramal, recebendo e efetuando chamadas identificadas e garantindo que todas as políticas da empresa (permissões de discagem, saldo, etc…) funcionem como se você estivesse utilizando o telefone IP que está fisicamente disponível na sua mesa.
Mas como isso funciona no Asterisk?
O recurso faz uso do DB interno do Asterisk para controlar, através do plano de discagem, o recebimento e a realização de chamadas, consultando o banco sempre que for necessário efetuar alguma destas operações.
E como faço para implementar este recurso?
A implementação é relativamente simples, no entanto existe um item importante, não contemplado neste exemplo, que é a utilização de senha para autenticar o ramal antes de efetuar o “login”. Considere fazer uso da mesma antes de colocar em produção.
Vamos começar
Para iniciar é preciso criar o plano de discagem que irá logar e deslogar o ramal. Optei por fazer isso no meu contexto chamado [features].
Nos meus testes, como não possuía os respectivos áudios necessários, acabei utilizando o agi GoogleTTS para tal fim.
Para logar o ramal:
exten => *52*,1,Answer same => n,agi(googletts.agi,"Informe o ramal.","pt-BR") same => n,read(RAMAL,,4) same => n,agi(verifyclid.agi) same => n,GotoIf($["${LEN(${CLID})}" == "0"]?siperror:sipok) same => n(sipok),NoOp(Logando ramal ${RAMAL} no ramal ${CALLERID(num)}) same => n,Set(DB_KEY=desvioentrada${RAMAL}) same => n,Set(DB(${DB_KEY}/active)=1) same => n,Set(DB(${DB_KEY}/ramal)=${CALLERID(num)}) same => n,Set(DB_KEY=desviosaida${CALLERID(num)}) same => n,Set(DB(${DB_KEY}/active)=1) same => n,Set(DB(${DB_KEY}/ramal)=${RAMAL}) same => n,Set(DB(${DB_KEY}/clid)=${CLID}) same => n,agi(googletts.agi,"O ramal está logado.","pt-BR") same => n,Hangup same => n(siperror),agi(googletts.agi,"O ramal informado é inválido.","pt-BR") same => n,Hangup
Para deslogar o ramal:
exten => *53*,1,Answer same => n,agi(googletts.agi,"Informe o ramal.","pt-BR") same => n,read(RAMAL,,4) same => n,agi(verifyclid.agi) same => n,GotoIf($["${LEN(${CLID})}" == "0"]?siperror:sipok) same => n(sipok),NoOp(Deslogando ramal ${RAMAL} do ramal ${CALLERID(num)}) same => n,Set(DB_KEY=desvioentrada${RAMAL}) same => n,DBDeltree(${DB_KEY}) same => n,Set(DB_KEY=desviosaida${CALLERID(num)}) same => n,DBDeltree(${DB_KEY}) same => n,agi(googletts.agi,"O ramal está deslogado.","pt-BR") same => n,Hangup same => n(siperror),agi(googletts.agi,"O ramal informado é inválido.","pt-BR") same => n,Hangup
Você observará no plano de discagem que é feito uso de um script, que serve basicamente para verificar se o ramal indicado pelo usuário é válido e obter o CallerID.
O script, desenvolvido para conectar no DB Postgresql, pode ser baixado aqui.
É preciso também alterar os contextos de entrada de chamadas para os ramais e também os contextos de saída das ligações para considerar a programação dos desvios.
Exemplo de contexto de entrada da chamada para o ramal (no caso [sip]):
[sip] exten => _XXXX,1,NoOp(Verificando desvio de saída) same => n,Set(DB_KEY=desviosaida${CALLERID(num)}) same => n,GotoIf($[${DB(${DB_KEY}/active)}=1]?desviosaida:checkentrada) same => n(desviosaida),Set(CALLERID(all)=${DB(${DB_KEY}/clid)}) same => n,Set(CALLERID(ani)=${DB(${DB_KEY}/clid)}) same => n(checkentrada),NoOp(Verificando desvio de entrada) same => n,Set(DB_KEY=desvioentrada${EXTEN}) same => n,GotoIf($[${DB(${DB_KEY}/active)}=1]?desvioentrada:dial) same => n(desvioentrada),Goto(${DB(${DB_KEY}/ramal)},1) same => n(dial),DIAL(SIP/${EXTEN},30)
Exemplo de contexto de saída das ligações (no caso [saida]):
[saida] same => _X.,1,NoOp(Verificando desvio de saída) same => n,Set(DB_KEY=desviosaida${CALLERID(num)}) same => n,GotoIf($[${DB(${DB_KEY}/active)}=1]?desviosaida:saida) same => n(desviosaida),Set(CALLERID(all)=${DB(${DB_KEY}/clid)}) same => n,Set(CALLERID(ani)=${DB(${DB_KEY}/clid)}) same => n(saida),Dial(CHAN/${EXTEN},30)
Simples não? Agora basta você adaptar os exemplos acima para seu cenário.
Até a próxima.