UNIVERSIDADE REGIONAL DE BLUMENAU CENTRO DE CIÊNCIAS EXATAS E NATURAIS CURSO DE CIÊNCIA DA COMPUTAÇÃO – BACHARELADO PROTÓTIPO DE INTERFONE SEM FIO COM ÁUDIO E VÍDEO ANDRÉ VINICIUS BAMPI BLUMENAU 2018 ANDRÉ VINICIUS BAMPI PROTÓTIPO DE INTERFONE SEM FIO COM ÁUDIO E VÍDEO Trabalho de Conclusão de Curso apresentado ao curso de graduação em Ciência da Computação do Centro de Ciências Exatas e Naturais da Universidade Regional de Blumenau como requisito parcial para a obtenção do grau de Bacharel em Ciência da Computação. Prof. Miguel Alexandre Wisintainer, Mestre - Orientador BLUMENAU 2018 Dedico este trabalho aos meus pais que sempre me apoiaram em todas as situações e que me forneceram toda a estrutura necessária para que eu pudesse fazer essa graduação. AGRADECIMENTOS A Deus pela minha vida, saúde e pelos dons que me possibilitaram chegar até aqui. Aos meus pais Aderlei Baggio Bampi e Amarildo Bampi pelo apoio incondicional em todas as situações e por sempre me incentivarem nos estudos, fornecendo todas as condições necessárias para que eu pudesse concluir essa graduação. Ao meu irmão Alexandre Mateus Bampi por sempre me ajudar em todas as vezes que eu precisei. Ao meu orientador Miguel Alexandre Wisintainer por seu apoio, suporte e por continuar acreditando na minha capacidade de desenvolver este trabalho, apesar dos tropeços em semestres anteriores. Aos meus amigos Eli Tonny de Souza, Gustavo Sabel, Maicon Machado Gerardi da Silva, Reinoldo Krause Junior, Vivian de Lima Panzenhagen e William Leander Seefeld por toda ajuda e conhecimento adquirido nos trabalhos em grupo e pelos momentos que tornaram o período da graduação mais bem agradável. Aos meus professores por todo o conhecimento e valores adquiridos durante a graduação. Além disso, irmãos, tudo o que é verdadeiro, tudo o que é nobre, tudo o que é justo, tudo o que é puro, tudo o que é amável, tudo o que é de boa fama, tudo o que é virtuoso e louvável, eis o que deve ocupar vossos pensamentos. Filipenses 4: 8 RESUMO Este trabalho apresenta o desenvolvimento de um protótipo de interfone sem fio com vídeo. O objetivo é a implementação de uma solução de automação residencial utilizando um minicomputador de propósito geral e softwares livres. O protótipo consiste em um hardware baseado no minicomputador Raspberry Pi e periféricos para as funcionalidades de interfone, um hardware baseado no mesmo minicomputador para o controle de equipamentos externos como portões eletrônicos e um conjunto de softwares que implementa essas funcionalidades. Algumas das funcionalidades implementadas são: chamadas com ou sem vídeo entre os interfones, encaminhamento de chamadas não atendidas para telefones comuns, controle de equipamentos externos durante as chamadas, histórico de chamadas e bloqueio de interfones. Para a implementação dessas funcionalidades, foram desenvolvidas três aplicações: a aplicação de administração, que serve para os cadastros, configurações e consultas, a aplicação de interfone e a aplicação de controle de ações, que serve para fazer o controle de equipamentos externos. O sistema de interfones utiliza o modelo cliente-servidor, efetuando as chamadas entre os interfones por intermédio de um servidor que utiliza tecnologias de Voice Over IP (VoIP). Por fim, os resultados obtidos através dos testes realizados mostraram que o trabalho desenvolvido atingiu os seus objetivos. Palavras-chave: Automação residencial. Domótica. Raspberry Pi. Interfone. Segurança condominial. Software livre. VoIP. Asterisk. Linux. ABSTRACT This work shows the development of a prototype of a wireless video intercom. The goal is to implement a home automation solution using a general-purpose minicomputer and free software. The prototype consists of hardware based on the Raspberry Pi mini-computer and peripherals for the intercom functions, a hardware based on the same minicomputer for the control of external equipment as electronic gates and a set of software that implements these functionalities. Some of the functionalities implemented are: video calls with or without video between the intercoms, routing of unanswered calls to ordinary telephones, control of external equipment during calls, call history and intercom blocking. For the implementation of these functionalities, three applications were developed: the administration application, which is used for the registers, configurations and queries, the application of intercom and the application of control of actions, which are to control external equipment. The intercom system uses the client-server model, making calls between the intercoms through a server that uses Voice Over IP (VoIP) technologies. Finally, the results obtained through the tests performed showed that the work developed has achieved its objectives. Key-words: Home automation. Domotics. Raspberry Pi. Intercom. Condominial safety. Free software. VoIP. Asterisk. Linux. LISTA DE FIGURAS Figura 1 - Aplicações de automação residencial ...................................................................... 18 Figura 2 - Rede VoIP ................................................................................................................ 19 Figura 3 - Raspberrys Pi modelos 2 B e 3B+ ........................................................................... 21 Figura 4 - Raspbian 9 Stretch ................................................................................................... 22 Figura 5 - Elastix 2.5 executando numa máquina virtual ......................................................... 24 Figura 6 - Arquitetura do Linphone .......................................................................................... 25 Figura 7 - Diagrama de distribuição ......................................................................................... 31 Figura 8 - Diagrama de casos de uso do interfone ................................................................... 33 Figura 9 - Diagrama de casos de uso da aplicação de administração ....................................... 34 Figura 10 - Diagrama de casos de uso do controle de ações .................................................... 35 Figura 11 - Diagrama de atividades do interfone – Inicialização/encerramento ...................... 37 Figura 12 - Diagrama de atividades do interfone – thread de status de chamada .................... 39 Figura 13 - Diagrama de atividades do interfone – chamada entre interfones ......................... 41 Figura 14 - Diagrama de atividades do controlador de ações................................................... 43 Figura 15 - MER ....................................................................................................................... 44 Figura 16 - Diagrama de pacotes .............................................................................................. 45 Figura 17 - Diagrama de classes resumido ............................................................................... 47 Figura 18 - Diagrama do hardware do interfone ...................................................................... 49 Figura 19 - Equipamentos dispostos no interfone .................................................................... 50 Figura 20 - Interfone montado .................................................................................................. 50 Figura 21 - Diagrama do hardware do controlador de ações .................................................... 51 Figura 22 - Controlador de ações montado .............................................................................. 52 Figura 23 - Placa com LEDs..................................................................................................... 53 Figura 24 - Adaptadores de rede do servidor ........................................................................... 55 Figura 25 - Servidor Elastix em execução ................................................................................ 55 Figura 26 - Habilitando suporte a chamadas com vídeo do Asterisk ....................................... 56 Figura 27 - Configurando tronco SIP ....................................................................................... 57 Figura 28 - Configurando rota de saída .................................................................................... 58 Figura 29 - Cadastro de ramal .................................................................................................. 59 Figura 30 - Criação do banco de dados .................................................................................... 60 Figura 31 - Configurações do Linphone ................................................................................... 61 Figura 32 - Arquivo de chamada da aplicação de interfone ..................................................... 62 Figura 33 - Arquivo de inicialização do LXDE ....................................................................... 62 Figura 34 - Arquivo de inicialização do Raspbian ................................................................... 63 Figura 35 - Construção do formulário da aplicação de interfone ............................................. 64 Figura 36 - Janelas exibidas durante uma chamada ................................................................. 71 Figura 37 - Servidor iniciado e conectado ................................................................................ 83 Figura 38 - Cadastrar ramais no Asterisk ................................................................................. 83 Figura 39 - Dados de um ramal ................................................................................................ 84 Figura 40 - Efetuar login na aplicação de administração ......................................................... 84 Figura 41 - Aplicação de administração ................................................................................... 85 Figura 42 - Parâmetros do sistema de interfones ...................................................................... 85 Figura 43 - Cadastro de dispositivo .......................................................................................... 86 Figura 44 - Cadastro de apartamento ........................................................................................ 86 Figura 45 - Cadastro de usuário ................................................................................................ 87 Figura 46 - Controlador de ações inicializado .......................................................................... 87 Figura 47 - Efetuar login na aplicação de interfone ................................................................. 88 Figura 48 - Aplicação de interfone inicializada........................................................................ 88 Figura 49 - Bloqueio de usuários .............................................................................................. 89 Figura 50 - Apartamento bloqueado ......................................................................................... 89 Figura 51 - Apartamento desbloqueado.................................................................................... 90 Figura 52 - Efetuando uma chamada ........................................................................................ 90 Figura 53 - Recebendo uma chamada ...................................................................................... 91 Figura 54 - Chamada de vídeo atendida ................................................................................... 91 Figura 55 - Efetuando ação ....................................................................................................... 92 Figura 56 - Ação processada .................................................................................................... 93 Figura 57 - Vídeo oculto ........................................................................................................... 94 Figura 58 - Vídeo oculto no usuário de origem ........................................................................ 95 Figura 59 - Consulta de ligações .............................................................................................. 95 Figura 60 - Consulta de ações .................................................................................................. 96 LISTA DE QUADROS Quadro 1 - Representação de um componente visual............................................................... 64 Quadro 2 - Exemplo de programa em Python utilizando GTK ................................................ 65 Quadro 3 - Classe de conexão ao banco de dados .................................................................... 66 Quadro 4 - Classe de manipulação de dados da tabela de apartamentos .................................. 67 Quadro 5 - Função de salvamento de apartamento com validações ......................................... 68 Quadro 6 – Funções de inicialização e encerramento do Linphone ......................................... 69 Quadro 7 - Funções de chamada............................................................................................... 70 Quadro 8 - Função de status de chamada do Linphone ............................................................ 71 Quadro 9 - Controles de tamanho e posição da janela de vídeo ............................................... 72 Quadro 10 - Funções de login e logout da classe MainController ........................................... 73 Quadro 11 - Implementação do Singleton na classe ParametersController ............................. 74 Quadro 12 - Funções de login e logout .................................................................................... 75 Quadro 13 - Função de efetuar chamada .................................................................................. 75 Quadro 14 - Função de status de chamada ............................................................................... 76 Quadro 15 - Funções de registro de chamada........................................................................... 77 Quadro 16 - Função de efetuar ação ......................................................................................... 77 Quadro 17 - Função que mantém a janela do software de interfone em primeiro plano.......... 77 Quadro 18 - Função de bloqueio e desbloqueio de usuário ...................................................... 78 Quadro 19 - Função de processamento de ações da classe ProcessActionsMainController .... 78 Quadro 20 - Função de processamento de ações da classe ActionCallController.................... 79 Quadro 21 - Função de salvar dados do usuário ....................................................................... 80 Quadro 22 - Função de bloqueio emergencial de chamadas da AdminMainController .......... 80 Quadro 23 - Função de bloqueio emergencial de chamadas da ActionsDao ........................... 81 Quadro 24 - Função de inicialização de thread no GTK .......................................................... 81 Quadro 25 - Trecho de código da função da thread de status do interfone .............................. 82 Quadro 26 - Erro de compilação da biblioteca Liblinphone .................................................... 97 Quadro 27 - Comparativo deste trabalho com os correlatos .................................................. 100 LISTA DE ABREVIATURAS E SIGLAS API – Application Programming Interface ARM – Advanced RISC Machine DSP – Digital Signal Processor GB – Gigabyte GHz – Giga-hertz GPIO – General Purpose Input/Output GPP – General Purpose Processor GTK – GIMP Toolkit HDMI – Definition Multimedia Interface IETF – Internet Engineering Task Force IP – Internet Protocol LCD – Liquid-crystal Display LED – Light-emitting Diodes LSS – Linux Suport Services LXDE – Lightweight X11 Desktop Environment MER – Modelo Entidade Relacionamento MHz – Mega-hertz PABX – Private Automatic Branch Exchange QCIF – Quarter Common Intermediate Format RAM – Random Access Memory RF – Requisito Funcional RNF – Requisito Não Funcional RTP – Real-time Transport Protocol SGBD – Sistema de Gerenciamento de Banco de Dados SIP – Session Initiation Protocol TCP/IP – Transmission Control Protocol/Internet Protocol USB – Universal Serial Bus VoIP – Voice Over IP SUMÁRIO 1 INTRODUÇÃO .................................................................................................................. 15 1.1 OBJETIVOS ...................................................................................................................... 15 1.2 ESTRUTURA.................................................................................................................... 16 2 FUNDAMENTAÇÃO TEÓRICA .................................................................................... 17 2.1 AUTOMAÇÃO RESIDENCIAL ...................................................................................... 17 2.2 VOIP .................................................................................................................................. 18 2.2.1 Protocolos VoIP .............................................................................................................. 19 2.3 RASPBERRY PI ............................................................................................................... 20 2.3.1 Raspbian .......................................................................................................................... 21 2.4 SOFTWARES LIVRES UTILIZADOS NO TRABALHO .............................................. 22 2.4.1 Asterisk ........................................................................................................................... 22 2.4.2 Elastix.............................................................................................................................. 23 2.4.3 Linphone ......................................................................................................................... 24 2.5 TRABALHOS CORRELATOS ........................................................................................ 25 2.5.1 Plataforma de comunicação multimedia para dispositivos de baixo custo com o uso de protocolos seguros ........................................................................................................... 25 2.5.2 Uma Arquitetura de Hardware e Software Livres para um Telefone VoIP .................... 26 2.5.3 Servidor VoIP com sistema de segurança doméstica integrada de baixo custo.............. 27 3 DESENVOLVIMENTO DO PROTÓTIPO .................................................................... 29 3.1 REQUISITOS .................................................................................................................... 29 3.2 ESPECIFICAÇÃO ............................................................................................................ 30 3.2.1 Diagrama de distribuição ................................................................................................ 30 3.2.2 Diagramas de casos de uso.............................................................................................. 31 3.2.3 Diagramas de atividades ................................................................................................. 35 3.2.4 MER ................................................................................................................................ 44 3.2.5 Diagrama de pacotes ....................................................................................................... 45 3.2.6 Diagrama de classes resumido ........................................................................................ 45 3.3 IMPLEMENTAÇÃO ........................................................................................................ 47 3.3.1 Hardware do protótipo .................................................................................................... 48 3.3.2 Técnicas e ferramentas utilizadas.................................................................................... 53 3.3.3 Instalação e configuração de softwares e redes do sistema............................................. 54 3.3.4 Código-fonte ................................................................................................................... 63 3.3.5 Operacionalidade da implementação .............................................................................. 82 3.4 ANÁLISE DOS RESULTADOS ...................................................................................... 96 3.4.1 Soluções descartadas e suas substitutas .......................................................................... 96 3.4.2 Principais problemas e suas soluções .............................................................................. 98 3.4.3 Comparação com os trabalhos correlatos ........................................................................ 99 4 CONCLUSÕES ................................................................................................................ 101 4.1 EXTENSÕES .................................................................................................................. 101 REFERÊNCIAS ................................................................................................................... 103 15 1 INTRODUÇÃO No cenário mundial, a automação residencial é uma das tendências de destaque, conquistando grande relevância no setor da construção civil. Segundo José Roberto Muratori, diretor executivo da Associação das Empresas de Automação Residencial e Predial (Aureside), a automação residencial é um processo pelo qual são utilizados diferentes sistemas para automatizar as tarefas de uma residência e otimizar sua utilização (AURESIDE, 2015). Os brasileiros estão absorvendo rapidamente novas tecnologias para o seu dia-a-dia. No Brasil, há um grande interesse pela automação residencial na construção civil. O interesse por parte dos consumidores brasileiros, que é de 78%, é maior que a média mundial, que é de 66%. Existe potencial para fornecer equipamentos para 1,8 milhões de residências, mas apenas 300 mil possuem esses equipamentos (AURESIDE, 2015). Para a construção civil, há várias tendências em destaque para os sistemas de automação residencial, entre eles a sustentabilidade, a integração de sistemas, internet das coisas, ambientes compactos, segurança, entre outras. Soluções com o uso de internet das coisas permitem a integração com demais objetos inteligentes, além de simplificar a instalação dos sistemas (AURESIDE, 2015). Diante do exposto, propõe-se nesse trabalho o desenvolvimento de uma solução de automação residencial que utilize os principais conceitos aqui descritos, como internet das coisas e capacidade de integração com outros sistemas. Esta solução é um interfone sem fio com áudio e vídeo e com encaminhamento de chamadas utilizando VoIP. 1.1 OBJETIVOS O objetivo deste trabalho é desenvolver um protótipo de um interfone sem fio com áudio e vídeo utilizando o minicomputador Raspberry Pi. Os objetivos específicos do trabalho são: a) construir um hardware a partir do minicomputador Raspberry Pi e periféricos que possa ser utilizado como um interfone; b) construir um hardware a partir do minicomputador Raspberry Pi e periféricos que possa ser utilizado como uma central de comunicação entre o sistema de interfones e equipamentos externos, como portões eletrônicos; c) desenvolver um conjunto de softwares que formam um sistema de interfones com áudio e vídeo e com comunicação com equipamentos externos. 16 1.2 ESTRUTURA Este trabalho está dividido em quatro capítulos. O primeiro capítulo apresenta a introdução e os objetivos do trabalho. O segundo capítulo trata da fundamentação teórica, explicando os principais conceitos e técnicas utilizados no trabalho. O terceiro capítulo contempla o desenvolvimento do protótipo, onde são descritos a arquitetura do trabalho através de diagramas, detalhamento da implementação e os resultados obtidos. Por fim, o quarto capítulo apresenta as conclusões, assim como sugestões para trabalhos futuros. 17 2 FUNDAMENTAÇÃO TEÓRICA Este capítulo está organizado em 5 seções. A seção 2.1 complementa o conceito de automação residencial. A seção 2.2 define o conceito de VoIP e alguns de seus protocolos. A seção 2.3 apresenta o minicomputador Raspberry Pi. A seção 2.4 apresenta os principais softwares livres utilizados no trabalho. Por fim, a seção 2.5 apresenta os trabalhos correlatos. 2.1 AUTOMAÇÃO RESIDENCIAL O conceito de automação residencial tem suas primeiras tecnologias desenvolvidas no final da década de 1970, nos Estados Unidos, utilizando soluções simples, praticamente não integradas e pontuais. A automação residencial passou a ter um forte apelo com as diversas tecnologias que se popularizaram a partir daí, como os computadores pessoais, a internet, a telefonia móvel, entre outras (MURATORI; DAL BÓ, 2011). O propósito da automação residencial é tornar o dia-a-dia das pessoas em suas residências mais simples, executando suas tarefas domésticas frequentes de forma automática. “Conforto, segurança e economia: a automação residencial aplica tecnologias no ambiente doméstico para atender basicamente a essas três necessidades.” (ROSARIO, 2009, p. 430). Outro termo utilizado para definir automação residencial, mais utilizado na Europa, é "Domótica" (MURATORI; DAL BÓ, 2011). Esse termo vem da junção da palavra latina "Domus" (casa) com Robótica (LINS; MOURA, 2010). A domótica é o conjunto de tecnologias aplicadas ao controle e à automação inteligente das residências. Ela ajuda a melhorar a qualidade de vida do usuário facilitando a economia de energia, promovendo a acessibilidade, proporcionando segurança, tornando as residências mais confortáveis e garantindo a comunicação mediante o controle e supervisão remota da residência (CEDOM, 2018). Em um sistema de automação residencial podem ser desenvolvidas muitas aplicações. Como exemplo de aplicações podem ser citados: controle de eletrodomésticos, acendimento de lâmpadas, controle de temperatura de ar condicionado, alimentação de animais domésticos, entre outros (MIGUEL; HENNING; TURATTI, 2017, p. 1). O protótipo desenvolvido neste trabalho implementa essas aplicações: a) telefonia Private Automatic Branch Exchange (PABX); b) vídeo porteiro; c) controle de portão eletrônico. A Figura 1 apresenta alguns exemplos de aplicações de automação residencial. 18 Figura 1 - Aplicações de automação residencial Fonte: Gessinger (2016). 2.2 VOIP VoIP é um conjunto de tecnologias de comunicação por voz que utiliza redes Internet Protocol (IP) locais ou a internet. Essas tecnologias utilizam o conjunto de protocolos das redes IP para a transmissão de sinais de voz em tempo real na forma de pacotes de dados, substituindo ou complementando os sistemas de telefonia convencionais (ROSS, 2007, p. 11). Segundo Gross (2011, p.21), “(…) VoIP vem da sigla em inglês Voice over Internet Protocol, em português: Voz sobre o Protocolo de Internet (IP), ou seja, estabelecer uma chamada de voz entre dois pontos utilizando como meio a rede de dados.” O primeiro software comercial de VoIP foi lançado em 1993. Em 1998, os primeiros sistemas a integrar a telefonia convencional com VoIP surgiram. Nesse mesmo ano, os primeiros padrões relacionados a VoIP surgiram, criados pela Internet Engineering Task Force (IETF) e a International Telecommunication Union (ITU). Hoje o VoIP está difundido no mercado, sendo utilizado para fazer ligações entre computadores, entre computadores e telefones e entre telefones (BORDIM, 2010, p. 12). Entre as vantagens de utilizar VoIP, o uso da mesma rede para chamadas telefônicas e para outros tipos de informação, sem utilizar a rede de telefonia pública comutada, diminui os custos (ROSS, 2007, p. 10). Outras vantagens são a portabilidade e funcionalidades acrescidas (BORDIM, 2010, p. 13). Pode-se destacar também algumas desvantagens, como limitações da rede, o alto custo inicial para redes totalmente IP, escassez de mão de obra especializada, entre outras (BORDIM, 2010, p. 14). Segundo Bordim (2010, p. 17), existem três formas de comunicação via VoIP: a) via softphone: um computador pode ser utilizado para comunicação via VoIP através de um software adequado; 19 b) via Adaptador de Telefone Analógico (ATA): um telefone analógico comum pode ser utilizado através desse tipo de adaptador; c) via telefones IP: são telefones que se comunicam através de redes IP. Eles possuem a mesma aparência de um telefone comum. A Figura 2 apresenta um exemplo de rede VoIP interligando a matriz e a filial de uma empresa através da internet. No exemplo, são utilizados softphones em diversos dispositivos, telefones convencionais e telefones IP. Figura 2 - Rede VoIP Fonte: Dmesg (2016). 2.2.1 Protocolos VoIP A comunicação é feita via protocolos utilizados para telefonia VoIP. Um deles, utilizado para controle de sessões multimídia, é o Session Initiation Protocol (SIP). Ele é um protocolo da camada de aplicação do modelo de referência Transmission Control Protocol/Internet Protocol (TCP/IP), que é usado para estabelecer, modificar e terminar sessões de multimídia, como a telefonia VoIP. Ele é de código aberto e é um padrão da IETF (ROSENBERG et al., 2002). A arquitetura SIP é constituída por um agente de usuário, um servidor de registro, e um servidor de reencaminhamento. O agente de usuário é quem inicia e recebe as sessões SIP e as comunicações multimídia. O servidor de registro é o responsável por registrar o usuário em um domínio que depois permita o uso dos serviços disponibilizados por esse servidor. É ele quem cria a sessão entre os usuários. O servidor de reencaminhamento serve para obter o endereço do usuário que está sendo contatado (ROSENBERG et al., 2002). 20 Para a transferência de dados é utilizado o protocolo Real-time Transport Protocol (RTP), que é um protocolo da camada de transporte do modelo de referência TCP/IP. Ele fornece funções fim-a-fim de transporte de rede adequadas para aplicações de transmissão de dados em tempo real, como áudio, vídeo, e outros, mais serviços de rede multicast ou unicast. Assim como o SIP, o protocolo RTP também é um padrão da IETF (SCHULZRINNE et al, 1996). As aplicações com RTP executam esse protocolo sobre o User Datagram Protocol (UDP) para fazer uso dos serviços de multiplexagem e checksum, mas também podem usar outros protocolos como o Transmission Control Protocol (TCP). Ele pode trabalhar com diversos protocolos de início de sessão, como o SIP, o Jingle, o H.225, o H.245, entre outros (SCHULZRINNE et al, 1996). 2.3 RASPBERRY PI Uma definição sobre o que é o Raspberry Pi, de acordo com a Raspberry Pi Foundation: O Raspberry Pi é um computador de baixo custo do tamanho de um cartão de crédito que se conecta a um monitor de computador ou TV, e usa um teclado e mouse padrão. É um pequeno dispositivo que permite às pessoas de todas as idades explorar a computação e aprender a programar em linguagens como Scratch e Python. É capaz de fazer tudo que você esperaria que um computador Desktop fizesse, desde navegar na internet e reproduzir vídeos em alta definição até fazer planilhas, processamento de texto e jogar jogos. (RASPBERRY PI FOUNDATION, 2018c, p. 1, tradução nossa). Atualmente está em sua terceira geração, tendo disponíveis quatro modelos: o Zero W, o 3 A+, o 3 B e o 3 B+. O modelo 3 B+, utilizado no trabalho, possui um processador Advanced RISC Machine (ARM) Cortex-A53 64 bits de quatro núcleos e clock de 1,4 Gigahertz (GHz), 1 Gigabyte de memória Random Access Memory (RAM), vídeo 3D videoCore IV de 400 Mega-hertz (MHz) e interfaces Wi-fi e Bluetooth integradasss (RASPBERRY PI FOUNDATION, 2018b). Outro modelo utilizado no trabalho é o 2 B, de segunda geração. Este modelo possui um processador ARM Cortex-A7 de quatro núcleos e clock de 900 MHz, 1 GB de memória RAM e processador de vídeo 3D VideoCore IV de 250 MHz, sem módulos Wi-fi e Bluetooth (RASPBERRY PI FOUNDATION, 2018a). Os dois modelos utilizados no trabalho, 2 B e 3 B+, possuem 4 portas Universal Serial Bus (USB), uma porta ethernet, uma interface para câmera e uma para display, saída HighDefinition Multimedia Interface (HDMI), saída de áudio estéreo e vídeo composto, porta para cartão Micro SD e 40 pinos de General Purpose Input/Output (GPIO) (Figura 3). 21 Figura 3 - Raspberrys Pi modelos 2 B e 3B+ Fonte: elaborado pelo autor. Além do Raspberry Pi, existem outros minicomputadores com o mesmo propósito. Como exemplo, podem ser citados: Banana Pi (BANANA PI, 2018), CubieBoard (CUBIEBOARD DOCS, 2014), BeagleBone (BEAGLEBOARD, 2018), entre outros. Como o Raspberry Pi utiliza um processador da arquitetura ARM, ele pode utilizar diversos sistemas operacionais. Alguns exemplos de sistemas operacionais suportados: Raspbian (RASPBIAN, 2018), Snappy Ubuntu Core (UBUNTU DEVELOPER, 2018), Windows 10 IoT (MICROSOFT, 2018), entre outros. O sistema operacional utilizado no trabalho é o Raspbian. 2.3.1 Raspbian O Raspbian é um sistema operacional livre, baseado na distribuição Linux Debian. Ele é otimizado para funcionar no Rasperry Pi e vem com um conjunto básico de programas e utilitários para essa plataforma (RASPBIAN, 2018). Desenvolvido a partir da versão estável mais recente do Debian, o Raspbian atual é baseado na versão 9, de codinome Stretch (RASPBIAN, 2018) (Figura 4). 22 Figura 4 - Raspbian 9 Stretch Fonte: elaborado pelo autor. O projeto Raspbian, apesar de seu sistema operacional ter sido adotado pela Raspberry Pi Foundation não é afiliado à essa fundação. O Raspbian foi criado por uma equipe pequena de desenvolvedores que são fãs do hardware do Raspberry Pi, dos objetivos educacionais da Raspberry Pi Foundation e do Projeto Debian (RASPBIAN, 2018). 2.4 SOFTWARES LIVRES UTILIZADOS NO TRABALHO O protótipo desenvolvido neste trabalho é totalmente baseado em softwares livres. Nesta seção, serão apresentados alguns deles, que desempenham as seguintes funções no trabalho: gerenciar a comunicação VoIP no servidor (Asterisk), sistema operacional do servidor (Elastix) e efetuar as chamadas nos interfones (Linphone). 2.4.1 Asterisk De acordo com o site oficial do Asterisk: O Asterisk é um framework de código aberto para a criação de aplicações de comunicação. O Asterisk transforma um computador comum em um servidor de comunicações. O Asterisk é plataforma para sistemas de PABX IP, gateways de VoIP, servidores de conferência e outras soluções personalizadas. É usado por pequenas empresas, grandes empresas, call centers, transportadoras e agências governamentais em todo o mundo. O Asterisk é livre e de código aberto. O Asterisk é patrocinado pela Digium (ASTERISK, 2018, p.1, tradução nossa). O Asterisk foi criado em 1999 por Mark Spencer para atender a necessidade de sua empresa, a Linux Suport Services (LSS), por um sistema telefônico “real” que pudesse distribuir chamadas uniformemente pela equipe de suporte. Ele decidiu criar seu próprio sistema telefônico após fazer orçamento com vários fornecedores locais desse tipo de sistema e descobrir que os custos seriam muito maiores que os que a LSS poderia pagar. Após alguns meses de desenvolvimento, ele publicou o código fonte original do Asterisk na internet sob a 23 licença GNU General Public License (GPL). A ideia do PABX de código aberto pegou, e centenas (agora milhares) de desenvolvedores em todo o mundo começaram a enviar novos recursos e funções. Em 2001, a LSS mudou seu nome para Digium (ASTERISK, 2016). O Asterisk serve para implementar as funções de um PABX utilizando tecnologia VoIP, com chamada de voz, conferência, resposta de voz interativa (menus do telefone), e distribuição automática de chamadas. O Asterisk suporta vários protocolos para telefonia VoIP, como o SIP, o H.323, o Media Gateway Control Protocol (MGC), entre outros. Ele também suporta protocolos de comutação de circuito tradicionais, como o Integrated Service Digital Network (ISDN) e o Signalling System No. 7 (SS7) (BRYANT; MADSEN; MEGGELEN, 2013, p. 98). Através de scripts nos arquivos de configuração, é possível criar novas funcionalidades no Asterisk, adicionando módulos carregáveis escritos em C. Também é possível através da implementação de programas na interface Asterisk Gateway Interface (AGI), utilizando qualquer linguagem de programação capaz de se comunicar através do sistema de stream padrão ou por rede sockets (BRYANT; MADSEN; MEGGELEN, 2013, p. 583). 2.4.2 Elastix O Elastix é um sistema operacional baseado na distribuição Linux Debian com foco em ser um PABX baseado em software, utilizando o software 3CX. Usando padrões abertos, é compatível com telefones IP populares, gateways e troncos SIP. O Elastix possui vários recursos de comunicações unificadas, como videoconferência, bate-papo, e é compatível com softphones para diversos sistemas operacionais (ELASTIX, 2018). Desenvolvido pela Palosanto em conjunto com a comunidade open source, o Elastix teve sua marca adquirida pela empresa 3CX. A partir daí a comunidade open source fez um fork do projeto e o batizou como Issabel (DONN SOLUÇÕES, 2018). A partir da versão 5 do Elastix, sob o controle da 3CX, o mecanismo de telefonia passou a ser a solução da 3CX e o sistema operacional base passou a ser a distribuição Linux Debian (MARCO LAGOA, 2016). A versão do Elastix utilizada no trabalho é a 2.5, ainda baseado no CentOS e no Asterisk (Figura 5). 24 Figura 5 - Elastix 2.5 executando numa máquina virtual Fonte: elaborado pelo autor. 2.4.3 Linphone O Linphone é um software de telefone SIP de código aberto. Ele serve para efetuar chamadas de voz e vídeo e mensagens instantâneas, e funciona em computadores e dispositivos móveis (Linux, Android, MAC OSX, iOS, Windows e Windows 10 UWP). A interface de usuário e o núcleo do Linphone são separados, permitindo a criação de vários tipos de interface de usuário sobre as mesmas funcionalidades. O Linphone utiliza o protocolo SIP, podendo ser usado com qualquer operadora VoIP (LINPHONE, 2017a). O Linphone foi o primeiro software SIP de código aberto para Linux. Lançado em 2001, ele foi portado para outras plataformas ao longo do tempo: desktop Windows em 2006, Android e iOS em 2010, Windows Phone 8 em 2013 (não mais suportado), Blackberry em 2016 e Windows UWP em 2016 (LINPHONE, 2017b). A Figura 6 apresenta a arquitetura do Linphone. O Liblinphone é uma Application Programming Interface (API) de alto nível que integra todos os recursos de chamada SIP e mensagens instantâneas. Ela utiliza o Mediastreamer2 para o streaming de voz e o Belle-SIP para a comunicação SIP. O MediaStreamer2 é uma biblioteca de código aberto que serve para o recebimento e envio de fluxos multimídia como captura de voz e vídeo, codificação, decodificação e renderização. O Belle-SIP, que também é uma biblioteca de código aberto, é responsável pela implementação das camadas de transporte, transação e diálogo do protocolo SIP (LINPHONE, 2017b). 25 Figura 6 - Arquitetura do Linphone Fonte: Linphone (2017b). 2.5 TRABALHOS CORRELATOS Foram selecionados três trabalhos correlatos. O trabalho de Leite (2014) descreve uma plataforma de comunicação via áudio e vídeo para dispositivos de baixo custo utilizando protocolos de transmissão seguros. O trabalho de Américo Filho et al. (2012) trata de uma arquitetura de hardware e software livres para telefonia VoIP. O trabalho de Destefani e Paukner (2013) descreve um sistema de telefonia VoIP integrado a um sistema de segurança domiciliar de baixo custo. 2.5.1 Plataforma de comunicação multimedia para dispositivos de baixo custo com o uso de protocolos seguros Desenvolvido por Leite (2014) em sua dissertação de mestrado, é uma plataforma de comunicação de áudio e vídeo para o dispositivo Raspbery Pi. Essa plataforma é composta por um servidor proxy SIP, uma interface web para acesso ao servidor, e a aplicação cliente. A aplicação cliente contém as APIs para a implementação dos protocolos, a interface de usuário e todo o desenvolvimento envolvido para o usuário se comunicar. A interface de usuário é simples, permitindo realizar as operações mais básicas como login, indicar usuário a ser contatado, realizar chamada e desligar chamada (LEITE, 2014). 26 O servidor proxy SIP é utilizado para estabelecer a conexão entre os usuários. Ele é utilizado na fase inicial da comunicação, onde são trocadas as mensagens SIP. Ele recebe o pedido de comunicação do usuário que solicitou, verifica sua identidade e envia o pedido ao destinatário. Ao receber a resposta do destinatário, irá verificar a identidade do mesmo, e estabelecerá uma conexão ponto a ponto entre o usuário que solicitou a comunicação e o destinatário. Além disso, o servidor armazena dados relativos às comunicações realizadas e os usuários cadastrados. Esses dados são acessados através de uma interface web (LEITE, 2014). A linguagem de programação utilizada foi o Java, e os protocolos de comunicação foram o SIP, para o controle de sessão, e o Secure Real-time Transport Protocol (SRTP), para a transferência de dados multimídia de forma segura. Para reforçar a segurança, foi implementado o algoritmo Diffie-Hellman, que é um método de criptografia específico para troca de chaves (LEITE, 2014). Leite (2014) concluiu que quase todos os objetivos de seu trabalho foram concluídos. Como trabalho futuro ele sugere algumas melhorias: implementar a utilização do protocolo Transport Layer Security (TLS), evoluir a implementação do RTP, melhorar a interface de usuário e integrar uma webcam ao trabalho. 2.5.2 Uma Arquitetura de Hardware e Software Livres para um Telefone VoIP Américo Filho et al. (2012) desenvolveu um telefone VoIP utilizando hardware e software livres. Seu hardware utiliza o processador ADSP-BF518, que é um Digital Signal Processor (DSP) de ponto fixo de 32 bits da família Blackfin, fabricado pela Analog Devices. Ele é um DSP com algumas características de General Purpose Processor (GPP), como controlador Liquid-crystal Display (LCD) e ethernet. Como DSP, ele é responsável pela transmissão e recepção dos sinais de voz, da codificação e decodificação, além de outros tratamentos, como cancelamento de eco e controle automático de ganho. Todo esse processamento de sinais deve ser executado em tempo real, por isso que o uso de um DSP se fez necessário. Ele também desempenha funções de GPP, como o tratamento de pacotes de rede e o gerenciamento da interface com o usuário (AMÉRICO FILHO ET. AL., 2012). A complexidade de um telefone VoIP torna necessário o uso de um sistema operacional embarcado. O sistema operacional escolhido foi o μClinux, portado para a família de processadores Blackfin. Como o nome sugere, o μClinux é uma distribuição Linux voltada para microcontroladores. Ela suporta diversas plataformas além da Blackfin, como Coldfire, 27 Microprocessor Without Interlocked Pipeline Stages (MIPS), ARM, etc. (UCLINUX, 2018) (AMÉRICO FILHO ET. AL., 2012). A biblioteca Liblinphone foi utilizada para implementar as funções de alto nível do telefone VoIP, como estabelecimento de sessão, gerenciamento de chamadas e proxy, controle de parâmetros de mídia e rede, entre outros. Suas funções fazem uso de outros componentes de software, como o Exosip2 para controle de sessão via protocolo SIP, o oRTP para a transmissão dos pacotes via protocolo RTP e o Mediastreamer2 para envio e recebimento de fluxos de áudio, incluindo captura, codificação e decodificação, entre outros (AMÉRICO FILHO ET. AL., 2012). A interface com o usuário é composta de um teclado matricial, um display LCD, além de botões de funções e Light-emitting Diodes (LED) indicativos (AMÉRICO FILHO ET. AL., 2012). Américo Filho et al. (2012) testou o telefone IP desenvolvido num cenário onde tem um PABX IP e um telefone VoIP proprietários, obtendo sucesso na realização e recebimento de chamadas. Ele também concluiu que é possível desenvolver todo o software do projeto utilizando bibliotecas de código aberto, reduzindo os custos e flexibilizando o desenvolvimento. 2.5.3 Servidor VoIP com sistema de segurança doméstica integrada de baixo custo Destefani e Paukner (2013) desenvolveram um produto chamado Fly-IP, que é composto por dois servidores: um para telefonia VoIP e outro para gerenciar uma interface GPIO para a segurança doméstica. Esses servidores se comunicam entre si para que seja possível controlar funções de segurança doméstica via internet, como a abertura e fechamento de um portão eletrônico. O produto implementou os dois servidores num único hardware, que é o minicomputador Raspberry Pi, executando o sistema operacional Debian. Para a parte de VoIP foi utilizado o software livre Asterisk. Para a segurança domiciliar, foi utilizada uma placa com drivers para sensores e atuadores, ligada diretamente na interface GPIO do Raspberry Pi. Todo sinal que os sensores e os atuadores enviam são tratados diretamente pelas saídas do processador, por isso não é necessário utilizar um protocolo de comunicação. Para essas funções, foi desenvolvido um software na linguagem de programação Python (DESTEFANI; PAUKNER, 2013). A interface com o usuário é, na grande maioria do tempo, seu próprio celular, através de um aplicativo SIP-phone. O celular deverá estar registrado no servidor VoIP para que ele possa se comunicar com o resto do sistema (DESTEFANI; PAUKNER, 2013). 28 Foi concluído por Destefani e Paukner (2013) que é necessário separar em dois blocos o protótipo para que ele possa se transformar em produto: uma central de ligações e uma central de atuadores. Também foi concluído que, o projeto se mostrou viável financeiramente, mas que pode ter o custo otimizado com a separação sugerida. 29 3 DESENVOLVIMENTO DO PROTÓTIPO Este capítulo demonstra as etapas do desenvolvimento do protótipo. Na seção 3.1 são apresentados os principais requisitos. A seção 3.2 apresenta a especificação. A seção 3.3 descreve de forma detalhada a implementação. Por fim, a seção 3.4 demonstra os resultados dos testes, sugestões e melhorias do protótipo. 3.1 REQUISITOS O protótipo deverá: a) disponibilizar uma interface gráfica com funções semelhantes às de um interfone (Requisito Funcional - RF); b) exigir autenticação do usuário para utilizar o interfone (RF); c) permitir chamadas de áudio, com ou sem vídeo, entre os interfones (RF); d) encaminhar chamada para telefone caso não seja atendida (RF); e) armazenar um histórico de chamadas feitas e recebidas para consulta dos usuários (apenas seus dados) e do administrador (todos os dados) (RF); f) disponibilizar uma interface para acesso a todas as funções e dados referentes a administração do sistema, como cadastro de interfones, relatórios de chamadas, etc. (RF); g) permitir que o usuário possa bloquear outros usuários, impedindo-os de efetuarem chamadas, com exceção dos usuários que o administrador definir como não bloqueáveis (RF); h) permitir o cadastro de interfones e usuários no servidor (RF); i) permitir que o usuário que receber a chamada decida, por motivos de segurança, se o outro usuário pode ver ou não sua imagem (RF); j) permitir que o usuário, através do interfone, controle outros equipamentos, como portões eletrônicos (RF); k) utilizar o minicomputador Raspberry Pi para os interfones (Requisito Não Funcional - RNF); l) utilizar os seguintes periféricos para os interfones: display LCD, placa de som USB, amplificador de áudio, monofone, webcam e teclado numérico (RNF); m) executar no sistema operacional Raspbian (RNF); n) funcionar numa rede local com ou sem fio (RNF); o) utilizar o software Asterisk no servidor como plataforma de telefonia VoIP (RNF); p) se comunicar por VoIP, via protocolos utilizados para esse fim, como SIP, RTP, 30 etc. (RNF); q) ser implementado utilizando a linguagem de programação Python (RNF); r) utilizar o banco de dados MariaDB (RNF). 3.2 ESPECIFICAÇÃO Esta seção apresenta a especificação do protótipo através de diagramas da Unified Modeling Language (UML). A ferramenta utilizada foi o Draw.io. Neste trabalho, foram especificados os diagramas de distribuição, de casos de uso, de atividades, Modelo Entidade Relacionamento (MER), diagrama de pacotes e diagrama de classes resumido. 3.2.1 Diagrama de distribuição A Figura 7 apresenta o diagrama de distribuição de hardware do sistema. Esse diagrama apresenta o cenário utilizado no trabalho, mostrando os equipamentos e suas respectivas funções. Segue abaixo uma descrição das funções e seus equipamentos associados: a) Servidor: função executada através de uma máquina virtual com o sistema operacional Elastix, pode ser executada em um computador pessoal ou em um servidor. Ele pode utilizar qualquer sistema operacional que tenha suporte para o Sistema de Gerenciamento de Banco de Dados (SGBD) e para o software de PABX IP utilizados no trabalho (MariaDB e Asterisk, respectivamente). A função dele é armazenar o banco de dados e fazer o intermédio das chamadas de VoIP dos interfones. Ele também faz o encaminhamento de chamadas para telefones comuns através do sistema de PABX IP e de uma operadora VoIP contratada. Apenas essa última função do sistema necessita de acesso à internet, que pode ser liberado apenas para o servidor; b) Interfones: função executada no notebook e no protótipo de interfone com Raspberry Pi, pode ser executada em computadores com Linux, Raspberrys Pi ou outros minicomputadores compatíveis. A função de interfone utiliza a aplicação de interfone desenvolvida neste trabalho e o softphone Linphone. Os interfones farão chamadas entre si e com telefones comuns (caso o interfone de destino não atenda), intermediados pelo Servidor. No interfone que recebeu a chamada, ele pode registrar ações a serem processadas pelo controlador de ações, também por intermédio do servidor; 31 c) Controlador de ações: executando num protótipo com Raspberry pi, essa função pode ser executada no mesmo tipo de equipamento dos interfones, mas precisa ter portas GPIO. Essa função utiliza a aplicação de controle de ações desenvolvida neste trabalho. Como não precisa de intervenção do usuário, não há a necessidade de dispositivos de entrada e de saída. Ele busca no banco de dados ações a processar, e as processa, caso estejam aptas. Essas ações são sinais enviados para equipamentos externos, como o comando de abertura de um portão eletrônico, por exemplo. Neste trabalho, os equipamentos externos são simulados através de uma placa com LEDs; d) Administrador: essa função é executada no notebook, mas não precisa necessariamente ser executada em um equipamento separado. Pode ser o servidor, um dos interfones ou o controlador de ações, desde que tenha o Python instalado e possua teclado, mouse e monitor. Ele executará a aplicação da administração do sistema, responsável pelas configurações, cadastros e consultas. Figura 7 - Diagrama de distribuição Fonte: elaborado pelo autor. 3.2.2 Diagramas de casos de uso Foram especificados três diagramas de casos de uso para o protótipo. O primeiro diagrama representa a aplicação de interfone, o segundo representa a aplicação de administração e o terceiro representa a aplicação de controle de ações. 32 3.2.2.1 Diagrama de casos de uso do interfone O diagrama de casos de uso apresentado na Figura 8 mostra as principais funcionalidades da aplicação do interfone. Foi identificado apenas um ator, denominado Usuário. No UC01 – Efetuar login, o Usuário se autentica através de seu id de usuário e senha. Todos os outros casos de uso dependem de o Usuário estar autenticado. No UC02 – Efetuar chamada, o Usuário pode iniciar uma chamada informando o número do apartamento de destino. Nesse momento, são registrados os dados da chamada (UC06 – Registrar dados da chamada). No UC03 – Atender chamada, o Usuário pode atender uma chamada feita por outro interfone. No UC04 – Desligar chamada, o Usuário pode cancelar uma chamada feita ainda não atendida, recusar uma chamada recebida e encerrar uma chamada em andamento. Caso ele seja o autor da chamada, nesse momento será registrado o fim da chamada (UC10 – Registrar fim de chamada). Durante uma chamada, o Usuário pode definir se quer mostrar ou esconder o vídeo (caso seja uma chamada com vídeo e ele tenha o privilégio de escondê-lo, UC07 – Mostrar/esconder vídeo), ligar ou desligar o microfone (UC08 – Mudo/som) e efetuar uma ação (caso ele seja o receptor da chamada e tenha o privilégio de efetuar ações, UC09 – Efetuar ação). Por fim, no UC05 – Bloquear/desbloquear apartamentos, o Usuário pode fazer o bloqueio ou o desbloqueio de apartamentos, impedindo que ele receba chamadas desses apartamentos. Para que ele possa bloquear um apartamento, é necessário que ele tenha o privilégio de bloquear apartamentos, e o apartamento desejado tenha sido configurado como bloqueável. 33 Figura 8 - Diagrama de casos de uso do interfone Fonte: elaborado pelo autor. 3.2.2.2 Diagrama de casos de uso da aplicação de administração A Figura 9 apresenta o diagrama de casos de uso da aplicação de administração do sistema. Assim como no interfone, foi identificado apenas um ator, denominado Usuário. No UC01 – Efetuar login, o Usuário se autentica através de seu id de usuário e senha. Todos os outros casos de uso dependem de o Usuário estar autenticado. No UC02 – Gerenciar parâmetros do sistema, um Usuário com privilégios de administrador pode alterar os parâmetros do sistema, como o idioma, o endereço IP do servidor VoIP, etc. No UC03 – Gerenciar usuários, um Usuário com privilégios de administrador pode cadastrar, editar, excluir e consultar contas de usuário do sistema. Um Usuário sem esses privilégios pode apenas editar alguns dados referentes a sua conta. No UC04 – Gerenciar apartamentos, um Usuário com privilégios de administrador pode cadastrar, editar, excluir e consultar apartamentos. Um Usuário sem esses privilégios pode apenas visualizar as informações de seu apartamento. No UC05 – Gerenciar dispositivos, um Usuário com privilégios de administrador pode cadastrar, editar, excluir e consultar dispositivos. Um Usuário sem esses privilégios pode apenas visualizar as informações do dispositivo associado ao seu apartamento. No UC06 – Gerenciar ações, um Usuário com privilégios de administrador pode cadastrar, editar, excluir e consultar ações do sistema. No UC07 – 34 Consultar chamadas, o Usuário pode consultar um histórico de todas as chamadas do sistema. Caso ele não tenha privilégios de administrador, ele pode consultar apenas as chamadas na qual ele esteja envolvido. No UC08 – Consultar ações efetuadas, o Usuário pode consultar um histórico de ações efetuadas no sistema. Caso ele não tenha privilégios de administrador, ele pode consultar apenas as ações relacionadas as chamadas na qual ele esteja envolvido. No UC09 – Consultar usuários bloqueados, o Usuário pode consultar todos os usuários bloqueados no sistema. Caso ele não tenha privilégios de administrador, ele poderá consultar apenas bloqueios nos quais ele esteja envolvido. Por fim, no UC10 – Bloqueio emergencial de ações, um Usuário com privilégio de administrador pode bloquear todas as ações do sistema, impedindo que as ações efetuadas durante as chamadas sejam processadas. Figura 9 - Diagrama de casos de uso da aplicação de administração Fonte: elaborado pelo autor. 3.2.2.3 Diagrama de casos de uso do controle de ações O protótipo de controle de ações deste trabalho funciona sem a intervenção do usuário, utilizando uma aplicação em modo texto que inicia o processamento assim que o protótipo é ligado. No entanto, também está disponível uma aplicação para ser utilizada sob a supervisão de um usuário. A Figura 10 apresenta o diagrama de casos de uso do controle de ações dessa versão da aplicação. Assim como nas outras aplicações, foi identificado apenas um ator, denominado Usuário. 35 No UC01 – Efetuar login, o Usuário se autentica através de seu id de usuário e senha. Todos os outros casos de uso dependem de o Usuário estar autenticado. No UC02 – Iniciar processamento, o Usuário inicia a thread de processamento de ações. Essa thread busca uma ação com status “0 - a processar” (UC04 – Buscar ação a processar). Caso encontre, ela verifica se essa ação está apta a processar e fará ou não o processamento (UC05 – Gerenciar processamento da ação). Se a ação estiver apta, seu status será alterado para “1 - processada” e ela será executada (por exemplo, será enviado o comando para um portão eletrônico abrir). Caso não esteja apta, seu status será alterado para o status correspondente ao motivo (por exemplo, “2 – timeout) e ela não será executada. Essa thread repetirá esses processos indefinidamente, com um intervalo entre as repetições definido nos parâmetros do sistema. Por fim, no UC03 – Parar processamento, o Usuário pode encerrar a thread de processamento. Figura 10 - Diagrama de casos de uso do controle de ações Fonte: elaborado pelo autor. 3.2.3 Diagramas de atividades Para especificar o comportamento do protótipo, foram feitos quatro diagramas de atividades. Os três primeiros representam o interfone e o último, o controle de ações. 3.2.3.1 Diagrama de atividades do interfone – Inicialização/encerramento Na Figura 11, são apresentadas as atividades referentes a inicialização e encerramento da aplicação do interfone. Foram definidas 4 regiões, onde as três primeiras executam no interfone e a quarta no servidor. As duas primeiras são threads da aplicação de interfone desenvolvida neste trabalho, a terceira representa o softphone Linphone e a quarta representa o PABX IP Asterisk. Primeiramente, o usuário efetua login na aplicação de interfone através de seu id de usuário e senha. Após isso, a thread principal dessa aplicação inicializa o Linphone, que por 36 sua vez inicializa seu daemon. A comunicação entre a aplicação de interfone e o Linphone é através de um conjunto de scripts chamado Linphonecsh. Com o daemon do Linphone funcionando, a thread principal tenta se registrar nele por até 5 vezes, encerrando a aplicação caso não tenha sucesso. São enviados ao Linphone o número do ramal SIP associado ao usuário, a senha desse ramal e o endereço IP do servidor que está executando o Asterisk. A partir desses dados, o Linphone autentica o ramal no Asterisk. A comunicação do Linphone com o Asterisk é através do protocolo SIP. Após a autenticação no Linphone e no Asterisk, a thread principal da aplicação de interfone inicializa a thread de status do interfone. Essa thread executa a cada 1 segundo e é responsável pelos controles do formulário e do controle de chamadas da aplicação de interfone, de acordo com o status de chamada obtido através do Linphone (mais detalhes no próximo diagrama). A partir desse momento, o interfone está apto para efetuar e receber chamadas. Por fim, quando o usuário efetuar o logout, a thread principal da aplicação de interfone desfará todos os registros. Ela enviará um comando para desfazer o registro no Linphone, que por sua vez desconectará o ramal do Asterisk. Ela também enviará um comando para encerrar o Linphone, que por sua vez desligará seu daemon e encerrará. 37 Figura 11 - Diagrama de atividades do interfone – Inicialização/encerramento Fonte: elaborado pelo autor. 3.2.3.2 Diagrama de atividades do interfone – thread de status de chamada A Figura 12 apresenta o diagrama de atividades da thread de status de chamada do interfone. Foram definidas duas regiões, que representam as regiões com mesmo nome no diagrama anterior. Como citado anteriormente, essa thread é inicializada após a aplicação de interfone estar aberta, com o usuário autenticado e seu ramal registrado no Linphone e no Asterisk. A cada um segundo, a thread lê o status de chamada do Linphone e executa atividades correspondentes a ela. 38 No início, uma variável que armazena o status anterior é inicalizada como “inativa”. Algumas atividades dependem da relação entre os status de chamada anterior e atual para serem executadas. Após isso, é feita a leitura do status de chamada atual do Linphone. Esses são os status possíveis e seus respectivos tratamentos: a) “desconectado”: esse status significa que o Linphone não está operando. Ele pode estar desconectado do Asterisk ou fechado. Detectando esse status, a thread efetua login novamente, realizando as atividades descritas no diagrama anterior; b) “inativa”: significa que não tem nenhuma chamada ativa, em andamento. Nesse momento o interfone está apto a fazer e receber chamadas. A thread faz o controle do formulário da aplicação do interfone referente a este status, habilitando os controles necessários para que o usuário possa efetuar uma chamada e para fazer o bloqueio e o desbloqueio de apartamentos (caso ele tenha esse privilégio). Caso o status anterior seja “chamando” ou “em chamada feita”, significa que uma chamada acabou de ser encerrada. Nesse momento, a thread registra o término da chamada; c) “chamando”: o usuário está efetuando uma chamada, que ainda não foi atendida. A thread habilita apenas os controles que permitem que o usuário encerre essa chamada. Caso o status anterior seja “inativa”, significa que o usuário acabou de iniciar essa chamada. Nesse momento, a thread registra os dados de início da chamada; d) “em chamada feita”: a chamada que o usuário efetuou foi atendida. A thread habilitará os controles referentes a chamadas feitas em andamento, como desligar a chamada, mostrar e esconder o vídeo (caso o usuário tenha esse privilégio), ligar e desligar o microfone, etc. Se o status anterior era “chamando”, significa que a chamada acabou de ser atendida. Nesse momento, a chamada é marcada como atendida. e) “recebendo”: o interfone está recebendo uma chamada. A thread habilitará apenas os controles necessários para atender ou recusar a chamada; f) “em chamada recebida”: significa que uma chamada recebida foi atendida e está em andamento. A thread habilitará os mesmos controles que habilitaria no status “em chamada feita”, mais os controles necessários para executar uma ação (caso o usuário tenha esse privilégio). 39 Por fim, a variável do status anterior recebe o valor do status atual e ocorre uma pausa de um segundo antes de reiniciar o processo. Figura 12 - Diagrama de atividades do interfone – thread de status de chamada Fonte: elaborado pelo autor. 3.2.3.3 Diagrama de atividades do interfone – chamada entre interfones A Figura 13 apresenta o diagrama de atividades de uma chamada entre interfones. O diagrama possui 7 regiões. As três primeiras executam num interfone, as três últimas no outro, e a quarta no servidor. Todas elas representam o mesmo que as regiões de nome equivalente do primeiro diagrama de atividades deste trabalho, da subseção Diagrama de atividades do interfone – Inicialização/encerramento. Após os dois interfones estarem com login efetuado, Linphone registrado e a thread de status de chamada executando, eles estão aptos a se comunicarem. O usuário do interfone 1, 40 ao efetuar chamada, informa o número do apartamento do interfone 2. A thread principal do interfone 1 envia para o Linphone um comando para discar para o ramal associado ao usuário que está ligado ao apartamento informado. Utilizando o protocolo SIP, o Linphone do interfone 1 inicia a chamada para o ramal de destino através do Asterisk. O Linphone do interfone 2 recebe a chamada, e começa a tocar como um telefone. Assim que o usuário do interfone 2 atende a chamada, os Linphones dos dois interfones estabelecem uma conexão de stream através do Asterisk, utilizando o protocolo RTP. O vídeo é exibido aos usuários através de uma janela que o Linphone abre ao iniciar a chamada. O diagrama mostra também alguns exemplos de atividades que podem ser feitas durante uma chamada: Efetuar ação, ocultar vídeo e desligar microfone. Efetuar ação basicamente é o usuário de destino da chamada solicitar o acionamento de um equipamento externo, como um portão eletrônico. Essa ação é salva no banco de dados para a aplicação de controle de ações processar (detalhes no próximo diagrama). Quando o usuário encerra a chamada, a thread principal da aplicação de interfone envia um comando para o Linphone, que por sua vez envia para o destino pelo Asterisk através do protocolo SIP. O stream é encerrado, a janela de vídeo dos Linphones fecha. 41 Figura 13 - Diagrama de atividades do interfone – chamada entre interfones Fonte: elaborado pelo autor. 3.2.3.4 Diagrama de atividades do controlador de ações Na Figura 14, é apresentado o diagrama de atividades do controlador de ações. O diagrama possui três regiões: as duas primeiras representam as threads da aplicação do controle de ações e a terceira, um equipamento externo, como um portão eletrônico. Primeiramente, o usuário efetua login na aplicação de interfone através de seu id de usuário e senha. Depois, assim que o usuário iniciar o processamento, a thread de busca e processamento de ações é inicializada. Essa thread busca e processa uma ação por vez, num intervalo determinado nos parâmetros do sistema. Assim que a thread de busca e processamento de ações encontra uma ação com status a processar, ela faz alguns testes para verificar se a ação está apta a ser processada: a) caso a data e hora da ação seja maior que a data e hora corrente, significa que há um problema na data e hora do interfone que executou a ação ou do controlador de ações. Nesse caso, a ação não é processada e seu status muda para não processada – horário incoerente; 42 b) cada ação tem um tempo limite em segundos. Caso tenha passado esse tempo desde que a ação foi gerada, ela não é processada e seu status muda para não processada – timeout; c) caso não tenha sido determinado um pino GPIO no cadastro da ação, ela não é processada e seu status muda para não processada – pino GPIO não definido; d) caso a ação esteja bloqueada, ela não é processada e seu status muda para não processada – ação bloqueada; e) caso a ação esteja inativa, ela não é processada e seu status muda para não processada – ação inativa. Caso a ação passe nos testes citados, a thread de busca e processamento de ações envia um sinal para o equipamento externo através da GPIO do dispositivo usado como controlador de ações. Caso algum erro aconteça, o status da ação muda para “não processada – falha técnica”. Caso contrário, o status muda para “processada”. Concluindo essa etapa, a thread faz uma pausa e reinicia o processo. O tempo dessa pausa é determinado por um parâmetro do sistema. A thread só para quando o usuário finaliza o processamento. 43 Figura 14 - Diagrama de atividades do controlador de ações Fonte: elaborado pelo autor. 44 3.2.4 MER A Figura 15 apresenta o MER do banco de dados. Esse diagrama possui oito entidades, que representam as tabelas criadas para este trabalho. O banco de dados é o mesmo para as três aplicações. Essas são as tabelas e suas respectivas funções: a) parameters: representa os parâmetros do sistema. Ela armazena o idioma, o endereço IP do servidor Asterisk, o apartamento padrão e o tempo de busca do controle de ações; b) user: representa os usuários do sistema; c) apartment: armazena os apartamentos. Cada usuário é ligado a um apartamento, e vice-versa. As chamadas dos interfones são feitas a partir do número do apartamento; d) device: representa os tipos de dispositivo que estão sendo usados nos apartamentos como interfone. Serve para armazenar a altura e a largura da janela de vídeo ideal para cada tipo de dispositivo; e) calls: registra os dados referentes às chamadas feitas, como usuário e apartamento de origem, usuário e apartamento de destino, datas e horas, etc. f) action: representa os tipos de ação que serão executadas durante as chamadas; g) actioncall: registra as ações executadas durante as chamadas; h) userblock: registra os bloqueios entre usuários. Figura 15 - MER Fonte: elaborado pelo autor. 45 3.2.5 Diagrama de pacotes Na Figura 16 é mostrado o diagrama de pacotes, que apresenta a estrutura do códigofonte das aplicações. A implementação desta estrutura foi baseada nos padrões de projeto Model-View-Controller (MVC) e Data Access Object (DAO) com o objetivo de tornar o sistema modular. Esses são os pacotes e suas respectivas funções: a) model: implementa as classes que representam as entidades descritas no MER e os enumerados; b) view: implementa as interfaces de usuário das aplicações. As interfaces da aplicação de interfone, da aplicação de administração e de uma versão da aplicação de controle de ações foram feitas para desktop em modo gráfico. A interface da outra versão da aplicação de controle de ações foi feita para desktop em modo texto; c) controller: implementa as regras de negócio e faz o intermédio entre a interface de usuário e o acesso aos dados; d) controller.dao: é a parte do controller que acessa e manipula os dados do sistema. Cada entidade descrita no MER possui uma classe para controlar seus respectivos dados; e) controller.dao.utils: é a parte do dao que faz a conexão com um sistema de armazenamento de dados. Figura 16 - Diagrama de pacotes Fonte: elaborado pelo autor. 3.2.6 Diagrama de classes resumido A Figura 17 mostra o diagrama de classes resumido. Nele, são mostradas todas as classes, agrupando as semelhantes e dividindo-as em seus pacotes. Essas são as principais classes: 46 a) <nome da tabela>: as classes do pacote model com os nomes das tabelas do banco de dados representam essas tabelas no sistema. Destaque para a classe Parameters que, além de representar a tabela de mesmo nome, tem propriedades para guardar os dados da sessão das aplicações durante a execução das mesmas; b) ActionCallStatus: enumeração que representa os status de processamento de ações; c) CallStatus: enumeração que representa os status de chamada do softphone Linphone; d) <nome da tabela>Dao: são as classes que fazem a manipulação dos dados das tabelas no banco de dados; e) ConnectionMySql: é a classe que faz a conexão com o banco de dados; f) <nome da tabela>Dao: são as classes que implementam as regras de negócio para o uso das tabelas. Destaque para a ParameterController que, além de implementar as regras referentes a tabela Parameters, ela cria um objeto único da classe Parameters para guardar os dados da sessão das aplicações enquanto elas estiverem executando; g) MainController: é a classe responsável pelos controles e regras de negócio das aplicações. Cada aplicação possui uma classe que herda da MainController para seus controles e regras específicas. Suas classes filhas são: AdminMainController, IntercomMainController e ProcessActionsMainController, utilizadas pelas aplicações de administração, interfone e controle de ações, respectivamente; h) SIPServiceController: utilizada na aplicação de interfone, serve para fazer a comunicação com o Linphone; i) FrmIntercomMain: formulário da aplicação de interfone; j) FrmAdminMain: formulário principal da aplicação de administração; k) FrmProcessActions: formulário da versão em modo gráfico da aplicação de controle de ações; l) ConsoleProcessActions: classe principal da versão em modo texto da aplicação de controle de ações; m) FrmParameters: formulário de cadastro dos parâmetros do sistema, utilizado na aplicação de administração; 47 n) FrmRegister<nome da tabela>: formulários de cadastros relacionados as tabelas do banco de dados. Utilizados na aplicação de administração para incluir, editar e excluir esses dados; o) FrmConsult<nome da tabela>: formulários de consultas relacionados as tabelas do banco de dados, utilizados na aplicação de administração; p) FrmConsult<nome da consulta>: formulários com as outras consultas da aplicação de administração como consulta de chamadas e consulta de usuários bloqueados. Figura 17 - Diagrama de classes resumido Fonte: elaborado pelo autor. 3.3 IMPLEMENTAÇÃO Esta seção mostra o detalhamento da implementação do trabalho. Na seção 3.3.1, são apresentados os detalhes da construção do hardware do protótipo. A seção 3.3.2 mostra as técnicas e ferramentas utilizadas. A seção 3.3.3 detalha a instalação e a configuração dos softwares e das redes. A seção 3.3.4 mostra o código-fonte. Por fim, a seção 3.3.5 detalha a operacionalidade da implementação. 48 3.3.1 Hardware do protótipo Para o protótipo deste trabalho, foram construídos dois dispositivos. Um deles é utilizado como interfone e o outro como controlador de ações. Os diagramas a seguir mostram os equipamentos utilizados em suas construções. 3.3.1.1 Hardware do interfone A Figura 18 mostra os equipamentos que compõem o hardware do interfone. Esses são os equipamentos utilizados e suas respectivas funções: a) Raspberry Pi 3 B+: minicomputador que executa todas as funções de interfone; b) cartão de memória: cartão micro SD responsável pelo armazenamento de dados do Raspberry Pi, desde o sistema operacional Raspbian até os softwares utilizados pelo interfone. Está conectado ao Raspberry Pi através de uma porta específica para esse tipo de cartão; c) webcam: conectada através de uma porta USB, é utilizada para transmitir a imagem do usuário durante uma chamada; d) teclado numérico: é utilizado para a operação do interfone. Conectado via USB, é possível acessar todas as funcionalidades do interfone através dele; e) placa de som: É utilizada para o envio e o recebimento de áudio durante uma chamada. Também é conectada via USB; f) monofone: é um monofone de telefone comum, adaptado para ser conectado na placa de som. Serve para, durante uma chamada, captar o áudio do usuário e executar o áudio recebido; g) amplificador de áudio: retirado de uma caixa de som genérica para computador, serve para executar o toque do interfone. Está conectado ao Raspberry Pi através de sua saída de áudio padrão; h) display LCD: conectado via HDMI, é utilizado para mostrar a interface gráfica do interfone; i) fonte: serve para alimentar todos os equipamentos do interfone. Sua tensão é 5 volts e sua corrente é 3 amperes. 49 Figura 18 - Diagrama do hardware do interfone Fonte: elaborado pelo autor. Esses equipamentos foram montados dentro de uma caixa de plástico para prototipagem, formando um só dispositivo. A Figura 19 mostra como os equipamentos estão dispostos dentro dessa caixa e a Figura 20 mostra o interfone montado e em funcionamento, executando a aplicação de interfone. 50 Figura 19 - Equipamentos dispostos no interfone Fonte: elaborado pelo autor. Figura 20 - Interfone montado Fonte: elaborado pelo autor. 51 3.3.1.2 Hardware do controlador de ações A Figura 21 mostra os equipamentos que compõem o controlador de ações. Esses são os equipamentos e suas respectivas funções: a) Raspberry Pi 2 B: minicomputador que executa as funções de controlador de ações; b) cartão de memória: cartão micro SD responsável pelo armazenamento de dados do Raspberry Pi, desde o sistema operacional Raspbian até a aplicação de controle de ações. Está conectado ao Raspberry Pi através de uma porta específica para esse tipo de cartão; c) módulo Wi-Fi: como a versão 2 B do Raspberry Pi não possui um módulo Wi-fi integrado, foi necessário utilizar um módulo externo via USB; d) placa com LEDs: desenvolvida para este trabalho, essa placa é conectada ao Raspberry Pi através das portas GPIO. Ela é utilizada para simular equipamentos externos, como portões eletrônicos; e) fonte: serve para alimentar todos os equipamentos do controle de ações. Sua tensão é 5 volts e sua corrente é 3 amperes. Figura 21 - Diagrama do hardware do controlador de ações Fonte: elaborado pelo autor. A Figura 22 - Controlador de ações montado mostra o controlador de ações montado, com todos os periféricos conectados. 52 Figura 22 - Controlador de ações montado Fonte: elaborado pelo autor. 3.3.1.2.1 Placa com LEDs A placa com LEDs foi construída para simular equipamentos externos, como portões eletrônicos. Ela possui três LEDs e um resistor de 1000 ohms, e cada LED simula um equipamento. Os polos negativos dos LEDs estão ligados ao resistor, que por sua vez, está ligado ao pino GPIO 6 do Raspberry Pi. Esse pino serve como aterramento. Os polos positivos dos LEDs vermelho, amarelo e verde estão ligados aos pinos GPIO 12, 16 e 18, respectivamente. Esses pinos servem como entrada e saída, sendo usados como saída neste trabalho. A Figura 23 mostra como os componentes da placa com LEDs estão conectados ao Raspberry Pi. 53 Figura 23 - Placa com LEDs Fonte: elaborado pelo autor. 3.3.2 Técnicas e ferramentas utilizadas As três aplicações desenvolvidas neste trabalho, que são a aplicação de interfone, a aplicação de administração e as duas versões da aplicação de controle de ações (modo gráfico e modo texto), foram escritas na versão 2.7 da linguagem de programação Python. Foi utilizado o ambiente de desenvolvimento Eclipse, na versão 4.9, com o plugin PyDev. As interfaces gráficas foram desenvolvidas com o GIMP Toolkit (GTK), utilizando a ferramenta Glade. Para a integração entre Python e GTK, é utilizado o plugin Python-gi. O SGBD utilizado é o MariaDB, e o gerenciamento do banco de dados é feito através da ferramenta MySQL Workbench. A conexão entre o Python e o MariaDB é através do plugin MySQLdb. Para a criptografia das senhas dos usuários é utilizado o Bcrypt. Todo o desenvolvimento foi feito num notebook com sistema operacional Lubuntu 18.04 LTS, que é uma variação da distribuição Linux Ubuntu com o ambiente gráfico Lightweight X11 Desktop Environment (LXDE). O servidor é uma máquina virtual com o sistema operacional Elastix, versão 2.5, executando no software VirtualBox, da Oracle, que por sua vez executa no mesmo notebook utilizado no desenvolvimento. Esse notebook também é utilizado como um dos interfones. 54 Para fazer a conexão do Asterisk com a rede de telefonia convencional é utilizada a operadora VoIP Tellfree. No interfone e no controlador de ações, é utilizado o sistema Operacional Raspbian, versão 9 (Stretch). O ambiente gráfico utilizado no sistema operacional é o LXDE. A aplicação do interfone utiliza o softphone Linphone para a comunicação VoIP e o software de controle de janelas Wmctrl para manter sua interface gráfica em primeiro plano. 3.3.3 Instalação e configuração de softwares e redes do sistema Esta seção detalha o processo de instalação e configuração das redes e dos softwares dos equipamentos utilizados neste trabalho. Na seção 3.3.3.1 é mostrada a configuração de rede. A seção 3.3.3.2 apresenta as configurações do servidor. A seção 3.3.3.3 mostra as configurações do protótipo do interfone. Por fim, a seção 3.3.3.4 apresenta as configurações do controlador de ações. 3.3.3.1 Rede O ambiente onde foi desenvolvido este trabalho utiliza duas redes. Ambas as redes geram endereços IP dinâmicos e possuem um roteador com access point cada. Os equipamentos podem ser conectados a elas através de cabos de rede ou Wi-Fi. Uma delas, com acesso à internet, é utilizada somente pelo servidor. Ela serve apenas para fazer o encaminhamento de chamadas para telefones comuns através de uma operadora VoIP. A outra rede conecta todos os outros equipamentos, inclusive o servidor, e é utilizada para as demais funções do sistema. 3.3.3.2 Servidor Para o servidor, foi criada uma máquina virtual com o sistema operacional Elastix no notebook através do software VirtualBox. Essa máquina virtual executa as funções de servidor VoIP e de servidor de banco de dados. Para se conectar às duas redes do ambiente, essa máquina virtual utiliza os dois adaptadores de rede do notebook, um de rede cabeada e outro de Wi-Fi, em modo bridge (Figura 24). Nos testes, foi percebido que o Elastix utiliza apenas o adaptador 1 para acessar a internet, caso ele utilize mais de um adaptador. Como o notebook está conectado à rede com internet através do adaptador de rede sem fio, esse foi definido como o adaptador 1. 55 Figura 24 - Adaptadores de rede do servidor Fonte: elaborado pelo autor. Após isso, foi feita a instalação do Elastix a partir de uma imagem de disco baixada do site oficial do mesmo. Durante a instalação, foram feitas as configurações iniciais do sistema operacional e dos serviços pré-instalados, como o Asterisk e o MariaDB. Após a instalação concluída, ao inicializar o sistema e efetuar login, o Elastix exibe os endereços IP para que ele possa ser acessado a partir de outros dispositivos que fazem parte das redes nas quais ele está conectado (Figura 25). Figura 25 - Servidor Elastix em execução Fonte: elaborado pelo autor. As configurações do Elastix e de seus serviços podem ser feitas remotamente através de uma interface web acessível por outros dispositivos conectados na mesma rede. Essa interface é executada num navegador a partir do endereço IP do Elastix. Na Figura 26, essa interface foi utilizada para habilitar o suporte a chamadas com vídeo no Asterisk. Para isso, 56 foi utilizada a ferramenta de edição de arquivos do Asterisk para editar o arquivo sip_general_custom.conf. Figura 26 - Habilitando suporte a chamadas com vídeo do Asterisk Fonte: elaborado pelo autor. Para conectar o Asterisk à operadora VoIP foi criado um tronco SIP. Para a configuração desse tronco foram utilizados os seguintes dados fornecidos pela operadora: ID de autenticação, senha e endereço do servidor SIP (Figura 27). 57 Figura 27 - Configurando tronco SIP Fonte: elaborado pelo autor. Para a utilização de tronco SIP para efetuar chamadas foi necessária a criação de uma rota de saída. A Figura 28 mostra os dados da rota criada no trabalho. No campo Dial Patterns that will use this Route foi definido que nesta rota para discar um número de telefone externo será informado “0” antes do número. Como o protótipo deste trabalho não foi desenvolvido para receber chamadas de telefones comuns, não foi necessária a criação de uma rota de entrada. 58 Figura 28 - Configurando rota de saída Fonte: elaborado pelo autor. Após o tronco SIP e sua rota serem criados foram cadastrados os ramais para serem utilizados nos interfones. Cada interfone precisa de um ramal para poder se comunicar com outros interfones, e outro ramal para fazer o encaminhamento de chamadas para telefones comuns. A Figura 29 mostra um exemplo de ramal cadastrado para encaminhar chamadas para telefones comuns. No lado esquerdo estão as informações básicas do cadastro do ramal, como o número, a senha, o nome de exibição, etc. No lado direito estão as informações de encaminhamento de chamada. O campo Follow-Me List define os números que serão chamados ao discar para esse ramal. No exemplo, um desses números é de um telefone celular convencional. O campo Destination if no answer define o que fazer com a chamada caso não seja atendida. No exemplo, foi definido para responder com o tom de ocupado e desligar a chamada. 59 Figura 29 - Cadastro de ramal Fonte: elaborado pelo autor. Um ramal para ser utilizado entre os interfones é cadastrado da mesma forma que o ramal do exemplo anterior, o que difere são as informações de encaminhamento de chamada. O campo Follow-Me List só possui o número do próprio ramal e, se esse ramal utilizar encaminhamento de chamadas, o campo Destination if no answer é definido para que, caso a chamada não seja atendida, seja encaminhada para outro ramal. Por fim, foi criado o banco de dados das aplicações. Com o SGBD MariaDB préinstalado e configurado, foi utilizada a ferramenta MySQL Workbench para fazer a criação do banco de dados intercom. A Figura 30 mostra a criação do banco de dados e de duas tabelas do sistema. 60 Figura 30 - Criação do banco de dados Fonte: elaborado pelo autor. 3.3.3.3 Protótipo do interfone Após o hardware do protótipo do interfone ter sido montado de acordo com a seção 3.3.1.1, foram instalados e configurados os softwares necessários para que possa ser executada a aplicação de interfone. Primeiramente, foi instalado o sistema operacional Raspbian num cartão de memória micro SD de 8 GB a partir de uma imagem de disco baixada do site da Raspberry Pi Foundation. Após a instalação, o protótipo foi conectado à internet apenas para a instalação das atualizações do sistema operacional e dos softwares necessários. Foram instalados os seguintes softwares: Bcrypt, Linphone, LXDE, MySQLdb, Python-gi e Wmctrl. Esses softwares também foram instalados no notebook, que é utilizado como um dos interfones. Todos eles estão disponíveis nos repositórios oficiais dos sistemas operacionais Raspbian e Lubuntu. Para o funcionamento do display de LCD utilizado no trabalho foi necessária a instalação de um driver disponibilizado pelo fabricante. Esse driver, entre outras coisas, mudou a resolução da imagem para 800x480, que é a única suportada pelo display. Além disso, ele sobrepôs o driver OpenGL, que é responsável pela renderização de vídeo por hardware. A impossibilidade da utilização do driver OpenGL com esse display causou prejuízos no desempenho das aplicações com vídeo, pois a renderização por software não utiliza todo o potencial do processador de vídeo do Raspberry Pi. Após a instalação dos softwares foi feita a configuração do Linphone. As configurações do Linphone são salvas no arquivo .linphonerc, no diretório do usuário do 61 sistema operacional. Ele pode ser configurado num editor de texto ou através da interface gráfica do Linphone. A Figura 31 mostra as configurações do Linphone no notebook. Para o interfone funcionar, essas são as configurações que precisam ser definidas: a) Playback device: define o dispositivo que vai executar o som recebido durante as chamadas. No interfone é utilizada a placa de som USB; b) Ring device: define o dispositivo que vai executar o toque durante ao receber uma chamada. No interfone é utilizado o dispositivo de som interno do Raspberry Pi; c) Capture device: define o dispositivo responsável pela captura do áudio a ser enviado durante uma chamada. No interfone é utilizada a placa de som USB; d) Video input device: define o dispositivo responsável pela captura do vídeo a ser enviado durante uma chamada. No interfone é utilizada a webcam USB; e) Prefered vídeo resolution: define a resolução de vídeo das chamadas. A resolução Quarter Common Intermediate Format (QCIF), que é a mais baixa, foi escolhida porque é a única que funciona no interfone de forma fluída. Resoluções mais altas não funcionam de forma satisfatória por causa do problema no driver de vídeo anteriormente citado; f) Video codecs: todos os codecs de vídeo foram testados, mas apenas o VP8 funcionou no Raspberry Pi. Figura 31 - Configurações do Linphone Fonte: elaborado pelo autor. Por fim, o ambiente gráfico LXDE é configurado para que a aplicação de interfone seja executada após a sua inicialização, que acontece após a inicialização do sistema operacional. O arquivo autostart.sh, criado no diretório /home/pi/.config, faz a chamada da aplicação. Para que essa chamada seja feita pelo LXDE ao inicializar, é adicionada uma chamada ao autostart.sh no arquivo autostart do LXDE, que fica no diretório 62 home/pi/.config/lxsession/LXDE. A Figura 32 mostra o arquivo autostart.sh. A primeira linha define que os scripts desse arquivo executarão no terminal Linux Bash. A segunda linha habilita a tecla numlock. A terceira linha rotaciona a tela para a direita, mudando a orientação para modo retrato. A quarta linha executa uma função em Python para dar uma pausa de 15 segundos para garantir que dê tempo de o sistema operacional conectar na rede e inicializar todos os serviços necessários. A quinta linha posiciona o terminal no diretório onde está instalada a aplicação do interfone. Por fim, sexta linha inicializa a aplicação de interfone, passando por parâmetro o ID do usuário e a senha. Figura 32 - Arquivo de chamada da aplicação de interfone Fonte: elaborado pelo autor. A Figura 33 mostra o arquivo autostart do LXDE. A última linha foi acrescentada para fazer a chamada do arquivo autostart.sh após a inicialização do LXDE. Figura 33 - Arquivo de inicialização do LXDE Fonte: elaborado pelo autor. 3.3.3.4 Controlador de ações Depois do controlador de ações ter o seu hardware montado de acordo com a seção 3.3.1.2, os softwares necessários para a execução da aplicação de controle de ações foram instalados e configurados. Primeiramente, foi instalado o sistema operacional Raspbian da mesma forma que no protótipo do interfone. Após a instalação, o controlador de ações também foi conectado à internet apenas para a instalação das atualizações do sistema operacional e dos softwares necessários, que são o Bcrypt e o MySQLdb. 63 Por fim, o Raspbian foi configurado para executar em modo texto através do software Raspi-config e inicalizar a aplicação de controle de ações após a inicialização do sistema operacional. Para inicializar essa aplicação, foi necessário editar o arquivo profile, do diretório /etc. Figura 34 mostra as linhas acrescentadas a esse arquivo. A primeira linha executa uma função em Python para dar uma pausa de 15 segundos para garantir que dê tempo de o sistema operacional conectar na rede e inicializar todos os serviços necessários. A segunda linha habilita a tecla numlock. A terceira linha posiciona o terminal no diretório onde está instalada a aplicação do controle de ações. Por fim, quarta linha inicializa a aplicação de controle de ações, passando por parâmetro o ID do usuário, a senha e o comando para iniciar o processamento de ações. Figura 34 - Arquivo de inicialização do Raspbian Fonte: elaborado pelo autor. 3.3.4 Código-fonte Esta seção apresenta os códigos-fonte das principais funcionalidades das aplicações. As funcionalidades mostradas são: interface gráfica, conexão com o banco de dados, comunicação com o Linphone, controladores das aplicações e a thread de status do interfone. 3.3.4.1 Interface gráfica Conforme mostrado no diagrama de pacotes da seção 3.2.5, a interface de usuário faz parte da camada view. As aplicações com interface gráfica utilizam formulários escritos em GTK para as interações com o usuário. Neste trabalho, os formulários foram criados utilizando a ferramenta Glade. A Figura 35 mostra o formulário da aplicação de interfone sendo construído nessa ferramenta. 64 Figura 35 - Construção do formulário da aplicação de interfone Fonte: elaborado pelo autor. Um formulário construído no Glade é salvo num arquivo no formato XML que representa os componentes visuais de um formulário, com suas propriedades e comportamentos. O Quadro 1 mostra a representação de um componente do formulário da aplicação de interfone, o botão de efetuar chamada. A tag signal representa um sinal (ou evento), que é uma ação realizada quando há uma interação com o componente. O sinal clicked é ativado quando o usuário clica no componente com o botão esquerdo do mouse. No exemplo, esse sinal ativa a função makeCall, a ser implementada. Quadro 1 - Representação de um componente visual 01. <object class="GtkButton" id="btnCall"> 02. <property name="label" translatable="yes">Call</property> 03. <property name="visible">True</property> 04. <property name="can_focus">True</property> 05. <property name="receives_default">True</property> 06. <property name="image">imgCallStart</property> 07. <signal name="clicked" handler="makeCall" swapped="no"/> 08. </object> Fonte: elaborado pelo autor. Para o uso dos formulários em GTK no Python, é utilizada a biblioteca gi. O Quadro 2 mostra um exemplo, usando o formulário da aplicação de interfone num programa básico em Python. Esse programa contém o mínimo necessário para utilizar e manipular componentes visuais de um formulário em GTK. No exemplo, as primeiras linhas importam as bibliotecas necessárias e definem a versão do GTK utilizada. No construtor da classe Main, é criada uma variável do tipo GTK.Builder, necessária para a leitura do arquivo do formulário. Em seguida, o formulário é lido e os sinais dos componentes são conectados às suas respectivas funções. Ao fazer essa 65 conexão, é necessário que todas as funções que foram associadas aos sinais dos componentes sejam implementadas. No exemplo, foi implementada a função makeCall, associada ao botão de efetuar chamada. Depois, o botão de efetuar chamada foi associado a uma variável através da função get_object para poder ser manipulado. A linha 14 mostra um exemplo de manipulação de componente, modificando o texto do botão. Quadro 2 - Exemplo de programa em Python utilizando GTK 01. import gi 02. gi.require_version("Gtk", "3.0") 03. from gi.repository import Gtk 04. 07. class Main(object): 08. def __init__(self): 09. self.builder = Gtk.Builder() 10. self.builder.add_from_file('FrmIntercomMain.ui') 11. self.builder.connect_signals(self) 12. 13. self.btnCall = self.builder.get_object('btnCall') 14. self.btnCall.set_label("Chamar") 15. 16. def makeCall(self, widget): 17. pass 18. 19. if __name__ == '__main__': 20. Main() 21. Gtk.main() Fonte: elaborado pelo autor. 3.3.4.2 Conexão com o banco de dados Para a conexão das aplicações com o banco de dados MariaDB foi criada uma classe no pacote controller.dao.utils chamada ConnectionMySql. Essa classe utiliza a biblioteca MySQLdb para a conexão e implementa funções para usar os principais comandos DML da linguagem SQL: insert, update, delete e select. O Quadro 3 apresenta uma parte do código-fonte desta classe, mostrando as funções de conexão, desconexão e insert. Os dados de acesso ao banco de dados (endereço, usuário, senha e o nome do banco) são armazenados num arquivo texto. 66 Quadro 3 - Classe de conexão ao banco de dados 01.import MySQLdb 02. 03. class ConnectionMySql: 04. connection = None 05. 06. def getConnection(self): 07. arqCfg = open('../controller/dao/util/db.cfg', 'r') 08. dbValues = arqCfg.readlines() 09. arqCfg.close() 10. if (self.connection == None) or (not self.connection.open): 11. self.connection = MySQLdb.connect(host = dbValues[0]. replace("\n",'') , user = dbValues[1].replace("\n",''), passwd = dbValues[2].replace("\n",''), db = dbValues[3].replace("\n",'')) 12. return self.connection 13. 14. def closeConnection(self): 15. self.connection.close() 16. 17. def insert(self, table, fields, values): 18. self.getConnection() 19. if fields.strip() == "": 20. self.connection.cursor().execute("insert into {0} values ({1})".format(table, values)) 21. else: 22. self.connection.cursor().execute("insert into {0} ({1}) values ({2})".format(table, fields, values)) 23. self.connection.commit() 24. self.closeConnection() Fonte: elaborado pelo autor. Para a manipulação dos dados das tabelas do banco de dados foram criadas classes dentro do pacote controller.dao. Cada tabela possui uma classe com o seu nome mais “Dao”. Essas classes implementam funções para salvar, editar, excluir e consultar os dados dessas tabelas. O Quadro 4 mostra uma parte do código-fonte da classe ApartmentDao, contendo funções de salvar, excluir e buscar apartamentos no banco de dados. 67 Quadro 4 - Classe de manipulação de dados da tabela de apartamentos 01. import sys 02. sys.path.insert(0, '../controller/dao/util') 03. sys.path.insert(0, '../model') 04. from ConnectionMySql import ConnectionMySql 05. from Apartment import Apartment 06. 07. class ApartmentDao: 08. def __init__(self): 09. self.connectionDB = ConnectionMySql() 10. self.allFields = "{0}, {1}, {2}".format(Apartment.ID_FIELD, Apartment.DESCRIPTION_FIELD, Apartment.IDDEVICE_FIELD) 11. 12. def save(self, apartment): 13. self.connectionDB.insert(Apartment.APARTMENT_TABLE, self.allFields, "{0}, '{1}', {2}".format(apartment.getId(), apartment.getDescription(), apartment.getIdDevice())) 14. 15. def delete(self, idApartment): 16. self.connectionDB.delete(Apartment.APARTMENT_TABLE, Apartment.ID_FIELD + " = {0}".format(idApartment)) 17. 18. def searchApartment(self, idApartment): 19. listConditions = [Apartment.ID_FIELD + " = {0}".format(idApartment)] 20. listFields = [self.allFields] 21. line = self.connectionDB.selectOneResult(Apartment.APARTMENT_TABLE, listFields, listConditions) 22. if line != None: 23. return self.assignValues(line) 24. return None Fonte: elaborado pelo autor. As regras de negócio e as validações referentes as tabelas do banco de dados são feitas por classes dentro do pacote controller. Cada tabela possui uma classe com o seu nome mais “Controller”. O Quadro 5 mostra a função save, da classe ApartmentController, responsável por validar os dados de um apartamento antes de salvá-lo no banco de dados. Após a validação, essa função envia os dados para a classe ApartmentDao inserir ou alterar esse apartamento. 68 Quadro 5 - Função de salvamento de apartamento com validações 01. def save(self, apartment): 02. if apartment.getId() == 0: 03. raise Exception (self.parametersController.getParameters() .getLangFile()["NUMBER_NOT_INFORMED"]) 04. if apartment.getDescription().strip() == "": 05. raise Exception (self.parametersController.getParameters() .getLangFile()["DESCRIPTION_NOT_INFORMED"]) 06. if apartment.getIdDevice() == 0: 07. raise NotExistingId(self.parametersController.getParameters() .getLangFile()["DEVICE_ID_NOT_SET"]) 08. if self.apartmentDao.searchApartment(apartment.getId()) == None: 09. self.apartmentDao.save(apartment) 10. else: 11. self.apartmentDao.update(apartment) Fonte: elaborado pelo autor. 3.3.4.3 Comunicação com o Linphone Neste trabalho, a comunicação por VoIP dos interfones é feita através do softphone Linphone. A aplicação de interfone se comunica com o Linphone utilizando um conjunto de scripts chamado Linphonecsh. Esses scripts são enviados para o Linphone através de chamadas do sistema SIPServiceController, operacional. Essa comunicação é feita pela classe do pacote controller. O Quadro 6 mostra as funções start e stop. A função start serve para inicializar o Linphone e registrá-lo no Asterisk. As funções os.system e os.popen, da biblioteca os, fazem chamadas para o sistema operacional. Através delas, são enviados os comandos para o Linphone. A diferença entre elas é que a função os.popen serve para comandos que esperam resposta. Na função start, o comando linphonecsh init inicializa o daemon do Linphone. O parâmetro -c determina um arquivo de configuração para o Linphone carregar, que no caso é o .linphonerc, do diretório do usuário do sistema operacional. O parâmetro -V define que o Linphone utilizará chamadas com vídeo. Ao inicializar existe a possibilidade de o Linphone efetuar registro automaticamente, caso o arquivo de configurações carregado tenha informações de endereço de servidor, usuário e senha salvos. Para a utilização da aplicação de interfone essas não são as informações corretas. Para desfazer imediatamente esse registro, caso aconteça, é executado o comando linphonecsh unregister após a inicialização do Linphone. Após o daemon do Linphone ser inicializado serão feitas até 5 tentativas de registrar o Linphone no Asterisk. Para isso é utilizado o comando linphonecsh register. São passados como parâmetros o endereço IP do servidor, vindo dos parâmetros do sistema, o 69 número e a senha do ramal SIP, vindos das informações do usuário logado na aplicação de interfone. Para verificar se o Linphone está devidamente registrado é utilizada o comando linphonecsh status register. Por fim, a função stop serve para desfazer o registro e encerrar o Linphone. Para isso, são utilizados os comandos linphonecsh unregister e linphonecsh exit, respectivamente. Quadro 6 – Funções de inicialização e encerramento do Linphone 01. def start(self): 02. attempts = 1 03. self.stop() 04. self.__connected = False 05. self.__muted = False 06. if self.parametersController.getParameters().getUser() .getVideoCall(): 07. os.system("linphonecsh init -c ~/.linphonerc -V") 08. else: 09. os.system("linphonecsh init -c ~/.linphonerc") 10. os.system("linphonecsh unregister") 11. time.sleep(1) 12. while (attempts < 6) and (self.__connected == False): 13. os.system("linphonecsh register --host " + self.parametersController.getParameters().getIpAddress() + " --username " + str(self.parametersController.getParameters().getUser().getSipId()) + " --password " + self.parametersController.getParameters().getUser() .getSipPassword()) 14. time.sleep(1) 15. s = os.popen("linphonecsh status register") 16. return_os = s.read() 17. self.__connected = return_os.find("registered=", 0) == -1 18. attempts = attempts + 1 19. time.sleep(1) 20. self.hidePreviewWindow() 21. 22. def stop(self): 23. os.system("linphonecsh unregister") 24. os.system("linphonecsh exit") 25. self.__connected = False Fonte: elaborado pelo autor. O Quadro 7 apresenta as principais funções de chamada que usam o Linphone, implementadas na classe SIPServiceController. Essas funções servem para: iniciar uma chamada, atender uma chamada, terminar uma chamada, desligar o microfone, ligar o microfone, mostrar vídeo e esconder vídeo. 70 Quadro 7 - Funções de chamada def startCall(self, sipNumber): if self.__connected: self.__muted = False os.system("linphonecsh dial sip:" + str(sipNumber) + "@" + self.parametersController.getParameters().getIpAddress()) def answerCall(self): if self.__connected: self.__muted = False os.system('linphonecsh generic "answer"') def terminateCall(self): if self.__connected: os.system('linphonecsh generic "terminate"') self.__muted = False def mute(self): if self.__connected: os.system('linphonecsh generic "mute"') self.__muted = True def unmute(self): if self.__connected: os.system('linphonecsh generic "unmute"') self.__muted = False def showVideo(self): if self.__connected: os.system('linphonecsh generic "camera on"') self.__showvideo = True def hideVideo(self): if self.__connected: os.system('linphonecsh generic "camera off"') self.__showvideo = False Fonte: elaborado pelo autor. O Quadro 8 mostra a função findCalls que verifica o status de chamada do Linphone. De acordo com a mensagem retornada pelo comando linphonecsh status hook, essa função determina se o Linphone está desconectado (status UNCONNECTED), se ele está sem chamadas ativas (INACTIVE), se está efetuando uma chamada (CALLING), se está recebendo uma chamada (RECEIVING), (ACTIVE_CALLING) ou se se está está com com uma uma chamada chamada feita recebida em andamento em andamento (ACTIVE_RECEIVING). Essa função também identifica o ramal de origem de uma chamada recebida. 71 Quadro 8 - Função de status de chamada do Linphone 01. def findCalls(self): 02. if self.__connected: 03. s = os.popen('linphonecsh status hook') 04. output = s.read() 05. if output == "": 06. return CallStatus.UNCONNECTED 07. if output.find("Call out", 0) != -1: 08. return CallStatus.ACTIVE_CALLING 09. if output.find("answered", 0) != -1: 10. return CallStatus.ACTIVE_RECEIVING 11. if output.find("ringing", 0) != -1: 12. return CallStatus.CALLING 13. if output.find("Incoming call", 0) != -1: 14. ini = output.find("<sip:") + 5 15. fim = output.find("@") 16. self.__sipIdReceiveCall = output[ini:fim] 17. return CallStatus.RECEIVING 18. return CallStatus.INACTIVE 19. return CallStatus.UNCONNECTED Fonte: elaborado pelo autor. Quando uma chamada com vídeo é estabelecida, o Linphone abre uma janela exibindo a imagem recebida e a imagem enviada. Nesse momento, a interface do interfone possui duas janelas: a janela da aplicação do interfone e a janela de vídeo do Linphone (Figura 36). Esse é o único momento em que o Linphone fica visível ao usuário. Figura 36 - Janelas exibidas durante uma chamada Fonte: elaborado pelo autor. 72 Para que a janela de vídeo do Linphone pareça estar integrada a janela da aplicação de interfone foram implementadas funções de ajuste de posição e tamanho. O Quadro 9 mostra a implementação dessas funções na classe SIPServiceController. A função setPosWindow determina em qual posição da tela a janela de vídeo do Linphone vai aparecer utilizando o comando linphonecsh generic “vwindow pos”. A função setSizeWindow ajusta o tamanho dessa janela utilizando o comando linphonecsh generic “vwindow size”. Quadro 9 - Controles de tamanho e posição da janela de vídeo 01. def setPosWindow(self, x, y): 02. if self.__connected: 03. os.system('linphonecsh generic "vwindow pos {0} {1}"'.format(x, y)) 04. 05. def setSizeWindow(self, width, height): 06. if self.__connected: 14. os.system('linphonecsh generic "vwindow size {0} {1}"'.format(width, height)) Fonte: elaborado pelo autor. 3.3.4.4 Controladores das aplicações Os controles e regras de negócio das aplicações de interfone, de administração e de controle de ações foram implementados na classe MainController e em suas derivadas. Cada aplicação tem sua classe derivada da MainController: IntercomMainController, AdminMainController e ProcessActionsController, respectivamente. Essas classes fazem parte do pacote controller. Outra classe importante desse pacote é a ParametersController, que entre outras coisas, guarda os dados da sessão. 3.3.4.4.1 Classes MainController e ParametersController A classe MainController implementa as funções em comum das três aplicações, que são as funções de sessão (login e logout). Para guardar os dados da sessão é utilizada a classe ParametersController. O Quadro 10 mostra a implementação das funções login e logout. A função login faz todas as validações necessárias para verificar se um usuário pode ter acesso à aplicação. São feitas validações de ID de usuário, senha, se o usuário existe, se está ativo, entre outras. Após as validações, as informações de usuário, seu apartamento e seu dispositivo são guardadas na instância da ParametersController. A função logout apenas limpa essas informações da ParametersController. 73 Quadro 10 - Funções de login e logout da classe MainController 01. def makeLogin(self, idUser, password): 02. if idUser == 0: 03. raise NotInformedIdUser(self.parametersController .getParameters().getLangFile()["ID_NOT_INFORMED"]) 04. if password == 0: 05. raise NotInformedPassword(self.parametersController .getParameters().getLangFile()["PASSWORD_NOT_INFORMED"]) 06. user = self.userController.searchUser(idUser) 07. if user == None: 08. raise LoginError(self.parametersController.getParameters() .getLangFile()["USER_DOES_NOT_EXIST"]) 09. if not user.getActive(): 10. raise LoginError(self.parametersController.getParameters() .getLangFile()["INACTIVE_USER"]) 11. if not self.userController.validatePasswordHash(password, user.getPassword()): 12. raise LoginError(self.parametersController.getParameters() .getLangFile()["INCORRECT_PASSWORD"]) 13. if user.getIdApartment() == 0: 14. self.parametersController.getParameters().setUser(user) 15. self.parametersController.getParameters().setApartment(None) 16. self.parametersController.getParameters().setDevice(None) 17. else: 18. apartment = self.apartmentController.searchApartment (user.getIdApartment()) 19. if apartment == None: 20. raise LoginError(self.parametersController .getParameters().getLangFile()["NON-EXISTENT_APARTMENT"] + ": {0}".format(user.getIdApartment())) 21. if apartment.getIdDevice() == 0: 22. raise LoginError(self.parametersController.getParameters() .getLangFile()["APARTMENT"] + " {0} {1}".format(apartment.getId(), self.parametersController.getParameters() .getLangFile()["DOES_NOT_HAVE_A_DEVICE_NUMBER"])) 23. device = self.deviceController.searchDevice (apartment.getIdDevice()) 24. if device == None: 25. raise LoginError(self.parametersController .getParameters().getLangFile()["APARTMENT"] + " {0}: {1}".format(apartment.getId(), self.parametersController.getParameters().getLangFile()["NONEXISTENT_DEVICE"] + ": {0}".format(apartment.getIdDevice()))) 26. self.parametersController.getParameters().setUser(user) 27. self.parametersController.getParameters() .setApartment(apartment) 28. self.parametersController.getParameters().setDevice(device) 29. 30. def makeLogout(self): 31. self.parametersController.getParameters().setUser(None) 32. self.parametersController.getParameters().setApartment(None) 33. self.parametersController.getParameters().setDevice(None) Fonte: elaborado pelo autor. A classe ParametersController teve sua implementação baseada no padrão de projeto Singleton. Isso significa que ela terá apenas uma única instância durante a execução da aplicação. Além dela cuidar dos controles e das regras de negócio relacionados a tabela 74 parameters do banco de dados, ela guarda o usuário autenticado na aplicação, seu apartamento e seu dispositivo enquanto a aplicação estiver sendo executada. O Quadro 11 mostra a implementação do Singleton da classe ParametersController. A função estática getInstance retorna a instância em execução da ParametersController. Caso não exista uma instância, ela criará uma. Quadro 11 - Implementação do Singleton na classe ParametersController 01. class ParametersController: 02. __instance = None 03. __parameters = None 04. 05. @staticmethod 06. def getInstance(): 07. if not ParametersController.__instance: 08. ParametersController.__instance = ParametersController() 09. return ParametersController.__instance Fonte: elaborado pelo autor. 3.3.4.4.2 Classe IntercomMainController A classe IntercomMainController é uma especialização da MainController utilizada para os controles e regras de negócio da aplicação de interfone. Ela implementa as regras de negócio para as funções de chamada, de registro de chamada, de bloqueio de usuários e de registro de ações. O Quadro 12 mostra as funções login e logout dessa classe. Elas são uma continuação das funções de mesmo nome da classe MainController. Na função login, após executar o login da MainController e validar os dados de usuário, apartamento e dispositivo, é feita a inicialização e o registro do softphone Linphone. A comunicação com o Linphone é feita através da classe SIPServiceController. Na função logout, a chamada que estiver em andamento é encerrada. Uma pausa de dois segundos é feita para garantir que o registro da chamada seja feito. Depois, é desfeito o registro do Linphone e ele é encerrado. Por fim, é executada a função logout da MainController. 75 Quadro 12 - Funções de login e logout 01. def makeLogin(self, idUser, password): 02. super(IntercomMainController, self).makeLogin(idUser, password) 03. if (self.parametersController.getParameters().getUser() .getSipId() != 0) and (self.parametersController.getParameters().getApartment() != None) and (self.parametersController.getParameters().getDevice() != None): 04. self.sipServiceController.start() 05. if not self.sipServiceController.getConnected: 06. raise SIPRegistrationError(self.parametersController .getParameters().getLangFile()["SIP_CONNECTION_ERROR"]) 07. 08. def makeLogout(self): 19. self.terminateCall() 10. time.sleep(2) 11. self.sipServiceController.stop() 12. super(IntercomMainController, self).makeLogout() Fonte: elaborado pelo autor. O Quadro 13 mostra um exemplo de função de chamada com validações, no caso a função makeCall, utilizada para efetuar chamadas. São feitas validações de apartamento, de usuário do apartamento, de bloqueio de usuário, entre outras. Após a validação, a chamada é feita através da classe SIPServiceController. Quadro 13 - Função de efetuar chamada 01. def makeCall(self, idApartment): 02. self.verifyUserActived() 03. if idApartment == 0: 04. idApartment = self.parametersController.getParameters() .getDefaultApartment() 05. self.validateIdApartment(idApartment) 06. self.user2 = self.userController.searchUserByApartment (idApartment) 07. if (self.user2 == None) or (self.user2.getSipId() == 0): 08. raise Exception(self.parametersController.getParameters() .getLangFile()["THE_CALLED_APARTMENT_CAN_NOT_RECEIVE_CALLS"]) 09. if (self.parametersController.getParameters().getUser() .getBlockable()) and (self.user2.getCanBlock()) and (self.userBlockController.isBlocked(self.user2.getId(), self.parametersController.getParameters().getUser().getId())): 10. raise Exception(self.parametersController.getParameters() .getLangFile() ["YOU_WERE_BLOCKED_BY_APARTMENT"] + " {0}".format(idApartment)) 11. if not self.user2.getActive(): 12. raise Exception(self.parametersController.getParameters() .getLangFile()["DEACTIVED_APARTMENT"]) 13. self.sipServiceController.startCall(self.user2.getSipId()) 14. time.sleep(1) 15. callStatus = self.sipServiceController.findCalls() 16. if callStatus == CallStatus.INACTIVE: 17. raise Exception(self.parametersController.getParameters() .getLangFile()["THE_CALLED_APARTMENT_IS_OFFLINE"]) Fonte: elaborado pelo autor. 76 As chamadas efetuadas geram registros no banco de dados. São registrados os tempos de início, de término, se a chamada foi atendida, entre outros. O momento em que esses registros são feitos é determinado pelo status de chamada. A função que busca o status de chamada é a findCalls, mostrada no Quadro 14. Ela busca o status de chamada do Linphone através da classe SIPServiceController e define em qual momento ela registra os dados de início de chamada, se ela foi atendida e o encerramento da mesma. Ela é chamada na thread de status do interfone, na aplicação de interfone. Além de gerenciar o registro de chamada, ela retorna o status para essa thread, que por sua vez faz o gerenciamento do formulário da aplicação. Quadro 14 - Função de status de chamada 01. def findCalls(self): 02. callStatus = self.sipServiceController.findCalls() 03. if callStatus != callStatus.UNCONNECTED: 04. if callStatus == CallStatus.INACTIVE: 05. if (self.actualCallStatus == CallStatus.CALLING) or (self.actualCallStatus == CallStatus.ACTIVE_CALLING): 06. self.saveCallRegister() 07. if callStatus == CallStatus.ACTIVE_CALLING: 08. if self.actualCallStatus == CallStatus.CALLING: 09. self.calls.setAttended(True) 10. if callStatus == CallStatus.CALLING: 11. if self.actualCallStatus == CallStatus.INACTIVE: 12. self.createCallRegister() 13. if callStatus == CallStatus.RECEIVING: 14. if self.actualCallStatus == CallStatus.INACTIVE: 15. self.user2 = self.userController .searchUserBySipID(self.sipServiceController.getSipIdReceiveCall()) 16. self.actualCallStatus = callStatus 17. return callStatus Fonte: elaborado pelo autor. O Quadro 15 mostra as funções que registram os dados de chamada. A função createCallRegister grava os dados iniciais de chamada, e a função saveCallRegister grava os dados de término. 77 Quadro 15 - Funções de registro de chamada 01. def createCallRegister(self): 02. self.calls = Calls() 03. self.calls.setId(self.callsController.getNextId()) 04. self.calls.setIdUser1(self.parametersController.getParameters() .getUser().getId()) 05. self.calls.setIdApartment1(self.parametersController.getParameters() .getUser().getIdApartment()) 06. self.calls.setIdUser2(self.user2.getId()) 07. self.calls.setIdApartment2(self.user2.getIdApartment()) 08. self.calls.setAttended(False) 09. self.calls.setStartDateTime(datetime.now()) 10. self.calls.setEndDateTime(self.calls.getStartDateTime()) 11. self.callsController.save(self.calls) 12. 13. def saveCallRegister(self): 14. if self.calls != None: 15. self.calls.setEndDateTime(datetime.now()) 16. self.callsController.save(self.calls) 17. self.calls = None Fonte: elaborado pelo autor. Durante uma chamada recebida o usuário poderá efetuar ações caso tenha privilégio pra isso. Essas ações, como abrir portões eletrônicos, são salvas usando a função makeAction (Quadro 16). Uma ação ActionCallController a processar é gerada e é enviada para a classe salvar. Essa ação será processada pela aplicação de controle de ações processar. Quadro 16 - Função de efetuar ação 01. def makeAction(self, idAction): 02. self.verifyUserActived() 03. if self.receivedCall != None: 04. actionCall = ActionCall() 05. actionCall.setId(0) 06. actionCall.setIdCall(self.receivedCall.getId()) 07. actionCall.setIdAction(idAction) 08. actionCall.setStartDateTime(datetime.now()) 09. actionCall.setStatus(ActionCallStatus.PROCESSING.value) 10. actionCall.setIdUserProcessed(0) 11. actionCall.setProcessDateTime(0) 12. self.actionCallController.save(actionCall) Fonte: elaborado pelo autor. Como citado anteriormente, ao estabelecer uma chamada com vídeo, uma janela de vídeo do Linphone é aberta. Para que a janela da aplicação de interfone continue em primeiro plano é utilizado o software Wmctrl. Esse software recebe um comando através de uma chamada para o sistema operacional (função os.system). O parâmetro -a indica o texto que aparece na barra de títulos da janela que deverá ficar em primeiro plano (Quadro 17). Quadro 17 - Função que mantém a janela do software de interfone em primeiro plano 01. os.system('wmctrl -a "{0}"'.format(self.parametersController .getParameters().getLangFile()["INTERCOM_BAMPI"])) Fonte: elaborado pelo autor. 78 As regras de bloqueio e desbloqueio de usuários também são implementadas através dessa classe. A função blockOrUnBlockApartment recebe o apartamento como parâmetro, e a partir dele localiza o usuário a bloquear ou desbloquear (Quadro 18). Após validações, os dados serão enviados para a classe UserBlockController fazer o bloqueio ou desbloqueio do usuário. Quadro 18 - Função de bloqueio e desbloqueio de usuário 01. def blockOrUnBlockApartment(self, idApartment): 02. self.validateIdApartment(idApartment) 03. user = self.userController.searchUserByApartment(idApartment) 04. if user == None: 05. raise Exception(self.parametersController.getParameters() .getLangFile()["APARTMENT_NOT_OCCUPIED"]) 06. if self.userBlockController.isBlocked(self.parametersController .getParameters().getUser().getId(), user.getId()): 07. self.userBlockController.unBlockUser(self .parametersController.getParameters().getUser().getId(), user.getId()) 08. return 2 09. else: 10. self.userBlockController.blockUser(self .parametersController.getParameters().getUser().getId(), user.getId()) 11. return 1 12. return 0 Fonte: elaborado pelo autor. 3.3.4.4.3 Classe ProcessActionsMainController A classe MainController, ProcessActionsMainController é uma especialização da criada com o objetivo de implementar os controles e regras de negócio da aplicação de controle de ações. Entretanto, como ela manipula dados de apenas uma tabela do banco de dados, sua principal função apenas retorna o valor da função de mesmo nome da classe ActionCallController, onde efetivamente são implementadas as regras do processamento das ações. O Quadro 19 mostra a implementação dessa função da classe ProcessActionsMainController, chamada de a processActionCall. Quadro 19 - Função de processamento de ações da classe ProcessActionsMainController 01. def processActionCall(self): 02. return self.actionCallController.processActionCall() Fonte: elaborado pelo autor. O Quadro 20 mostra a função de mesmo nome, implementada na classe ActionCallController, onde efetivamente os controles e regras de processamento de ações são implementados. Os status de processamento são definidos conforme explicado no diagrama de atividades da seção 3.2.3.4. Caso a ação esteja apta a processar é enviado um sinal para o pino GPIO correspondente a ação utilizando a biblioteca RPi.GPIO. Esse pino é definido como saída e é ligado. É feita uma pausa de um segundo, e em seguida o pino é 79 desligado. No protótipo de controlador de ações o LED correspondente ao pino GPIO é aceso por um segundo. Quadro 20 - Função de processamento de ações da classe ActionCallController 01. def processActionCall(self): 02. actionCall = self.searchUnprocessedActions() 03. if actionCall != None: 04. actions = self.actionsController.searchActions(actionCall .getIdAction()) 05. if time.mktime(datetime.now().timetuple()) < actions.getTimeout(): 06. actionCall.setStatus(ActionCallStatus .UNPROCESSED_INCOHERENT_TIME.value) 07. else: 08. if (time.mktime(datetime.now().timetuple()) - time.mktime (actionCall.getStartDateTime().timetuple())) > actions.getTimeout(): 09. actionCall.setStatus(ActionCallStatus.UNPROCESSED_TIMEOUT .value) 10. else: 11. if actions.getGpio_pin() == 0: 12. actionCall.setStatus(ActionCallStatus .UNPROCESSED_NO_GPIO_PIN.value) 13. else: 14. if actions.getBlocked(): 15. actionCall.setStatus(ActionCallStatus .UNPROCESSED_BLOCKED.value) 16. else: 17. if not actions.getActive(): 18. actionCall.setStatus(ActionCallStatus .UNPROCESSED_INACTIVE.value) 19. else: 20. try: 21. import RPi.GPIO as GPIO 22. GPIO.setwarnings(False) 23. GPIO.setmode(GPIO.BOARD) 24. #Defining pin as output 25. GPIO.setup(int(actions.getGpio_pin()), GPIO.OUT) 26. GPIO.output(int(actions.getGpio_pin()), 1) 27. time.sleep(2) 28. GPIO.output(int(actions.getGpio_pin()), 0) 29. #print actions.getGpio_pin() 30. actionCall.setStatus(ActionCallStatus.PROCESSED .value) 31. except: 32. actionCall.setStatus(ActionCallStatus .UNPROCESSED_TECHNICAL_FAILURE.value) 33. actionCall.setIdUserProcessed(self.parametersController .getParameters().getUser().getId()) 34. actionCall.setProcessDateTime(datetime.now()) 35. self.actionCallDao.update(actionCall) 36. return actionCall Fonte: elaborado pelo autor. 3.3.4.4.4 Classe AdminMainController A classe AdminMainController é uma especialização da MainController, criada com o objetivo de implementar os controles e regras de negócio da aplicação de 80 administração. Entre suas funções estão o bloqueio emergencial de ações e as especializações das funções de salvar usuário, apartamento e dispositivo. Na maioria das tabelas do banco de dados, as funções utilizadas para salvar os dados são as das classes de controle dessas tabelas. No caso das tabelas de usuário, apartamento e dispositivo, que são dados utilizados na sessão, foram criadas funções para isso na classe AdminMainController. O objetivo é que, caso os dados alterados dessas tabelas sejam referentes ao usuário ativo na sessão, os dados da sessão também sejam alterados. O Quadro 21 mostra a função saveUser. Ela é uma especialização da função save da classe UserController. Após salvar os dados do usuário, ela verifica se o usuário é o mesmo que está logado. Caso seja, alterará também os dados da sessão. Quadro 21 - Função de salvar dados do usuário 01. def saveUser(self, user, repeatPassword): 02. self.userController.save(user, repeatPassword) 03. if user.getId() == self.parametersController.getParameters() .getUser().getId(): 04. parameters = self.parametersController.getParameters() 05. parameters.setUser(user) 06. if user.getIdApartment() == 0: 07. parameters.setApartment(None) 08. parameters.setDevice(None) 09. else: 10. parameters.setApartment(self.apartmentController .searchApartment(user.getIdApartment())) 11. if parameters.getApartment().getIdDevice() == 0: 12. parameters.setDevice(None) 13. else: 14. parameters.setDevice(self.deviceController .searchDevice(parameters.getApartment().getIdDevice())) 15. self.parametersController.setParameters(parameters) Fonte: elaborado pelo autor. Outra função importante dessa classe é a blockAllActions. Ela serve para fazer o bloqueio emergencial de ações. Na classe AdminMainController, ela apenas faz a chamada da função de mesmo nome da classe ActionsController (Quadro 22), que por sua vez faz a chamada da função de mesmo nome da classe ActionsDAO. Quadro 22 - Função de bloqueio emergencial de chamadas da AdminMainController 01. def blockAllActions(self): 02. self.actionsController.blockAllActions() Fonte: Elaborado pelo autor. O Quadro 23 mostra a implementação da função blockAllActions da classe ActionsDao. Essa função basicamente altera o valor do campo blocked de todos os tipos de ação (tabela actions) para 1, que indica que estão bloqueados. Isso impede que as ações desses tipos sejam processadas pela aplicação de controlador de ações. 81 Quadro 23 - Função de bloqueio emergencial de chamadas da ActionsDao 01. def blockAllActions(self): 02. listConditions = None 03. listChanges = ["{0} = {1}".format(Actions.BLOCKED_FIELD, 1)] 04. self.connectionDB.update(Actions.ACTIONS_TABLE, listChanges, listConditions) Fonte: Elaborado pelo autor. 3.3.4.5 Thread de status do interfone Conforme apresentado no diagrama de atividades da seção 3.2.3.2, a thread de status do interfone faz parte do formulário da aplicação de interfone e executa a cada um segundo. O formulário da aplicação do interfone está na classe FrmIntercomMain, do pacote view. Essa thread serve para gerenciar os controles do formulário e os registros de chamada. Ela é inicializada após efetuar login, através de uma função do GTK que recebe por parâmetro um tempo em segundos e uma função (Quadro 24). Essa função do GTK faz a função passada por parâmetro executar repetidas vezes, com uma pausa entre elas determinada pelo tempo em segundos passado por parâmetro. Quadro 24 - Função de inicialização de thread no GTK 01. GObject.timeout_add_seconds(1, self.findCalls) Fonte: Elaborado pelo autor. A função da thread de status do interfone, findCalls, busca o status de chamada da função de mesmo nome da classe IntercomMainController. De acordo com o status retornado, ela habilita os componentes visuais necessários para uma determinada função do interfone, como efetuar uma chamada, atender uma chamada, efetuar ações, etc. O Quadro 25 mostra uma parte da função findCalls da thread de status do interfone. Nesse trecho de código é feito o tratamento da rotina quando o status indicar que existe uma chamada em andamento (status ACTIVE_CALLING ou ACTIVE_RECEIVING). Os componentes visuais referentes as esses status são habilitados, como os botões de encerrar chamada, ligar/desligar o microfone, mostrar/esconder vídeo, efetuar ações, etc. Os outros componentes são desabilitados, como os botões de efetuar chamada, atender chamada, bloquear usuário, etc. 82 Quadro 25 - Trecho de código da função da thread de status do interfone 01. if (callStatus == CallStatus.ACTIVE_CALLING) or (callStatus == CallStatus.ACTIVE_RECEIVING): 02. self.disableUserBlockComponents() 03. if callStatus == CallStatus.ACTIVE_CALLING: 04. self.showOkMessage(self.parametersController .getParameters().getLangFile()["CALL_FOR_APARTMENT"] + " {0}".format(self.edtIdApartment.get_text())) 05. else: 06. idApartment = 0 07. if self.parametersController.getParameters().getUser() .getCanMakeActions(): 08. self.btnAction.show() 09. if self.mainController.getUser2() != None: 10. idApartment = self.mainController.getUser2() .getIdApartment() 11. self.showOkMessage(self.parametersController .getParameters().getLangFile()["CALL_FROM_APARTMENT"] + " {0}" .format(idApartment)) 12. self.btnCall.hide() 13. self.btnAnswer.hide() 14. self.btnTerminate.show() 15. self.btnApartmentBlock.hide() 16. self.spnCalling.stop() 17. if self.mainController.getMuted(): 18. self.btnMute.hide() 19. self.btnUnmute.show() 20. else: 21. self.btnMute.show() 22. self.btnUnmute.hide() 23. if (self.parametersController.getParameters().getUser() .getVideoCall()) and (self.parametersController.getParameters() .getUser().getCanHideVideo()): 24. if self.mainController.getShowVideo(): 25. self.btnShowVideo.hide() 26. self.btnHideVideo.show() 27. else: 28. self.btnShowVideo.show() 29. self.btnHideVideo.hide() 30. if (self.actualCallStatus == CallStatus.CALLING) or (self.actualCallStatus == CallStatus.RECEIVING): 31. self.disablePages() 32. self.setSizeVideoWindow() 33. self.btnTerminate.grab_focus() Fonte: Elaborado pelo autor. 3.3.5 Operacionalidade da implementação Esta seção mostra a operacionalidade da implementação. Serão demonstrados os cadastros básicos necessários e os principais casos de uso das três aplicações do protótipo, que são a aplicação de administração, a aplicação de interfone e a aplicação de processamento de ações. Para que o sistema de interfones esteja apto a funcionar, são necessários alguns cadastros. Antes de tudo, as redes utilizadas devem estar operando e o servidor funcionando. O servidor deverá estar conectado às redes, conforme mostra a Figura 37. 83 Figura 37 - Servidor iniciado e conectado Fonte: Elaborado pelo autor. Após inicializar o servidor será necessário cadastrar ramais no Asterisk. Para isso, através de um computador conectado na mesma rede que o servidor deve ser acessada a interface de configurações do Elastix. Essa interface é acessada no navegador através do endereço IP do servidor (Figura 38). Para cadastrar um ramal deve-se clicar nas opções abaixo. Figura 38 - Cadastrar ramais no Asterisk Fonte: Elaborado pelo autor. Deverão ser cadastrados ramais para todos os usuários do Interfone. Os cadastros devem ser feitos conforme explicado na seção 3.3.3.2 (Figura 39). 84 Figura 39 - Dados de um ramal Fonte: Elaborado pelo autor. Com os ramais cadastrados a aplicação de administração pode ser usada para fazer os cadastros básicos. Ao inicia-la deve-se efetuar login com um usuário com privilégio de administrador, informando o ID de usuário e senha (Figura 40). Figura 40 - Efetuar login na aplicação de administração Fonte: elaborado pelo autor. As funcionalidades da rotina de administração estão agrupadas em menus (Figura 41). Primeiramente devem ser verificadas as configurações do sistema acessando o menu “Administração” e “Parâmetros”. 85 Figura 41 - Aplicação de administração Fonte: elaborado pelo autor. Devem ser cadastrados o idioma, o endereço IP do servidor Asterisk e o tempo de busca de ações em segundos (Figura 42). O tempo de busca de ações determina de quanto em quanto tempo a aplicação de controle de ações buscará uma ação a processar. O apartamento padrão, opcional, define o apartamento que será chamado caso não seja informado nenhum na aplicação de interfone. Figura 42 - Parâmetros do sistema de interfones Fonte: elaborado pelo autor. Após os parâmetros configurados devem ser cadastrados os equipamentos utilizados como interfone. Eles são necessários para definir a altura e largura da janela de vídeo do Linphone para cada dispositivo. A Figura 43 mostra o cadastro do Raspberry Pi do protótipo de interfone. 86 Figura 43 - Cadastro de dispositivo Fonte: elaborado pelo autor. O próximo passo é cadastrar os apartamentos. É a partir do número dos apartamentos que são feitas as chamadas. Para ser utilizado num interfone é necessário que ele esteja associado a um dispositivo. A Figura 44 mostra o cadastro de um apartamento associando-o ao dispositivo cadastrado anteriormente. Figura 44 - Cadastro de apartamento Fonte: elaborado pelo autor. Por fim, devem ser cadastrados os usuários. Deverão ser cadastrados pelo menos um usuário para cada interfone (Figura 45). Além deles, é recomendável o cadastro de pelo menos um usuário para a aplicação de controle de ações. Para a utilização em interfones devese obrigatoriamente informar um apartamento, um ID de ramal SIP e a senha desse ramal. 87 Figura 45 - Cadastro de usuário Fonte: elaborado pelo autor. Após os cadastros feitos o controlador de ações pode ser inicializado. Considerando que ele está configurado conforme a seção 3.3.3.4, a aplicação de controle de ações em modo texto executará, fará login e iniciará o processamento de ações automaticamente ao inicializalo. Opcionalmente, pode ser ligado a um monitor para monitorar as ações processadas em tempo real. A Figura 46 mostra o controlador de ações inicializado e pronto para processar ações. Figura 46 - Controlador de ações inicializado Fonte: elaborado pelo autor. 88 Agora os interfones podem ser ligados. Ao inicializar a aplicação de interfone é necessário efetuar login (Figura 47), caso o dispositivo usado como interfone não esteja configurado para efetuar login num usuário determinado num arquivo de configuração conforme a seção 3.3.3.3. Figura 47 - Efetuar login na aplicação de interfone Fonte: elaborado pelo autor. Ao efetuar login o interfone estará apto a fazer e receber chamadas. Nesse momento, estarão habilitados os controles para efetuar chamada e para gerenciar o bloqueio de usuários (Figura 48). Figura 48 - Aplicação de interfone inicializada Fonte: elaborado pelo autor. Ao clicar no botão Bloqueio ou pressionar a tecla Home, são listados os apartamentos dos usuários bloqueados. Nesse momento, são habilitados os controles para fazer o bloqueio ou desbloqueio (Figura 49). 89 Figura 49 - Bloqueio de usuários Fonte: elaborado pelo autor. Ao digitar um número de apartamento e clicar em Ok ou pressionar a tecla Enter, o usuário relacionado ao apartamento informado é bloqueado e o apartamento aparecerá na lista de bloqueio (Figura 50). Figura 50 - Apartamento bloqueado Fonte: elaborado pelo autor. Ao fazer o mesmo processo para um usuário bloqueado ele é desbloqueado (Figura 51). 90 Figura 51 - Apartamento desbloqueado Fonte: elaborado pelo autor. Para efetuar uma chamada basta digitar o número do apartamento e clicar em Chamar ou pressionar a tecla Enter. Para cancelar a chamada basta clicar em Desligar ou pressionar a tecla del (Figura 52). Figura 52 - Efetuando uma chamada Fonte: elaborado pelo autor. No interfone de destino da chamada o usuário poderá atender (clicando em Atender ou pressionando a tecla Enter) ou recusar (clicando em Desligar ou pressionando a tecla del) a chamada. Será exibido o número do apartamento de origem (Figura 53). 91 Figura 53 - Recebendo uma chamada Fonte: elaborado pelo autor. Se o usuário do apartamento de destino atender aparecerá a janela de vídeo e a comunicação com áudio e vídeo iniciará. Os controles de chamada de vídeo estarão disponíveis, como mostrar ou esconder vídeo, ligar ou desligar o microfone, etc. (Figura 54). Figura 54 - Chamada de vídeo atendida Fonte: elaborado pelo autor. 92 No interfone de destino aparecerá a opção de efetuar ações caso o usuário tenha privilégio para isso. Ao clicar no botão Ações ou pressionar o botão Home é exibida uma lista com os tipos de ação disponíveis (Figura 55). Ao clicar em uma ou digitar o número correspondente e pressionar Enter, uma ação a processar é gerada. Figura 55 - Efetuando ação Fonte: elaborado pelo autor. Ao gerar uma ação o controlador de ações fará o processamento da mesma. O LED correspondente ao tipo da ação irá acender, a ação será processada e os dados dessa ação serão exibidos (Figura 56). 93 Figura 56 - Ação processada Fonte: elaborado pelo autor. Outro recurso disponível durante a chamada, caso o usuário tenha privilégio para isso, é de esconder o vídeo. Ao clicar em Esconder vídeo ou pressionar a tecla / a imagem do usuário que fez esse procedimento não estará mais visível (Figura 57). 94 Figura 57 - Vídeo oculto Fonte: elaborado pelo autor. A Figura 58 mostra a imagem vista pelo usuário de destino quando o usuário de origem oculta o vídeo. 95 Figura 58 - Vídeo oculto no usuário de origem Fonte: elaborado pelo autor. Ao desligar a chamada os dados da mesma são registrados. Para consulta-los é utilizada a consulta de chamadas da aplicação de administração (Figura 59). Figura 59 - Consulta de ligações Fonte: elaborado pelo autor. Na consulta de chamadas para ver as ações efetuadas durante uma chamada basta selecioná-la e clicar em Ações. A consulta de ações será exibida com os dados solicitados (Figura 60). 96 Figura 60 - Consulta de ações Fonte: elaborado pelo autor. 3.4 ANÁLISE DOS RESULTADOS Esta seção apresenta os resultados obtidos no desenvolvimento deste trabalho. Os resultados são demonstrados através das tecnologias e equipamentos testados e as resoluções dos principais problemas. Na seção 3.4.1, são apresentadas as soluções descartadas e suas substitutas. A seção 3.4.2 mostra os principais problemas e suas soluções. Por fim, a seção 3.4.3 compara este trabalho com os correlatos. 3.4.1 Soluções descartadas e suas substitutas Ao longo do desenvolvimento diversas tecnologias e equipamentos foram utilizados para que todos os requisitos fossem cumpridos. Para chegar à conclusão de que essas soluções foram capazes de resolver os problemas e cumprir os requisitos, essas e outras foram testadas e comparadas. Esta seção apresenta as soluções que foram descartadas, as suas substitutas e os motivos. 3.4.1.1 Java A linguagem de programação proposta para este trabalho foi o Java. No entanto, como a linguagem Python é praticamente nativa no Linux, com bibliotecas nativas para diversos recursos do Raspberry Pi como o acesso às portas GPIO, além de não precisar de uma máquina virtual para executar, concluiu-se que ela seria a linguagem ideal para este trabalho. A simplicidade da linguagem e a extensa documentação disponível facilitou o seu aprendizado. 3.4.1.2 Liblinphone A ideia inicial de tecnologia para a comunicação VoIP entre os interfones era a biblioteca Liblinphone, que é a base do softphone Linphone. O objetivo era fazer uma aplicação unificada, sem depender de outras. No entanto, ao tentar utilizá-la, diversos erros de 97 compilação ocorreram, como o do Quadro 26. Após não obter sucesso na resolução desses problemas foi decidida a utilização da aplicação Linphone. Quadro 26 - Erro de compilação da biblioteca Liblinphone Fonte: elaborado pelo autor. Apesar de ser uma aplicação separada da desenvolvida no trabalho, o fato do Linphone ter a opção de executar em background e poder ser acessado através de um conjunto de scripts chamado Linphonecsh manteve a aplicação de interfone com a usabilidade de uma aplicação única. Outras soluções para manter o aspecto de aplicação única foram utilizadas. Uma delas foi o uso do software Wmctrl para manter a janela da aplicação de interfone em primeiro plano durante as chamadas. Outra solução foi definir a posição e o tamanho da janela de vídeo do Linphone para que ela pareça estar “encaixada” na janela da aplicação de interfone, não disputando espaço na tela com a mesma. 3.4.1.3 Tkinter Para a interface gráfica das aplicações do trabalho, o Tkinter havia sido escolhido por ser a biblioteca gráfica padrão do Python. Isso garante que ela executará em qualquer sistema operacional que tenha suporte ao Python. No entanto, ela é uma biblioteca simples e com poucos recursos. Faltam componentes como o combobox, alguns recursos de manipulação de janelas, entre outros. Por esse motivo, foi decidido usar outra biblioteca. No lugar do Tkinter foi escolhido o GTK. Um dos motivos dessa escolha foi o fato de que ele é a biblioteca base do ambiente gráfico LXDE, utilizado neste trabalho. O GTK é usado em outros ambientes gráficos populares do Linux, como o Gnome, o XFCE, o Mate, etc. Apesar da curva de aprendizado maior que a do Tkinter, o GTK atendeu todas as necessidades deste trabalho. Felizmente, ele está disponível no repositório oficial dos sistemas operacionais utilizados. 3.4.1.4 Openbox O Openbox é um ambiente gráfico leve e minimalista. Por padrão, não possui menu principal, barras de tarefas, efeitos visuais, entre outros recursos. Para o protótipo de interfone, que precisa que apenas a aplicação de interfone apareça na tela, seria o ambiente gráfico ideal. No entanto, durante os testes foi percebido que o Openbox não é totalmente 98 compatível com a versão 3 da biblioteca gráfica GTK, fazendo com que os ícones dos botões da aplicação de interfone não fossem exibidos. Por esse motivo, foi decidido usar o ambiente gráfico LXDE. Apesar do LXDE possuir uma barra de ferramentas, ele permite ocultá-la, fazendo com que a aplicação de interfone seja a única a aparecer na tela. 3.4.2 Principais problemas e suas soluções Esta seção apresenta os principais problemas que ocorreram ao longo do desenvolvimento do trabalho e que não foram citados na seção anterior. Também são apresentadas suas soluções. 3.4.2.1 Chamadas caindo em poucos segundos Desde os primeiros testes utilizando apenas o Linphone até os testes utilizando a aplicação de interfone em desenvolvimento, as chamadas eram encerradas automaticamente após poucos segundos. As chamadas estavam sendo feitas entre um Raspberry Pi modelo 2B e o notebook utilizado no desenvolvimento. Foram verificadas as configurações do Asterisk para verificar se o tempo de timeout das chamadas estava curto demais, mas não era esse o problema. Foi verificado se o Linphone tinha alguma configuração semelhante, mas não tem. No final, ao testar via rede cabeada, foi constatado que o módulo Wi-fi utilizado no Raspberry Pi estava com defeito, desligando e religando sozinho durante o uso. Esse módulo, sem identificação de marca e modelo, foi substituído por um D-Link DWA-125 e o problema foi solucionado 3.4.2.2 Baixo desempenho em chamadas com vídeo no Raspberry Pi As chamadas com vídeo efetuadas no Raspberry Pi modelo 2B estavam apresentando um desempenho que tornava seu uso como interfone inviável. Tanto a imagem enviada quanto a imagem recebida estavam quase estáticas, demorando mais de dois segundos para atualizar. O uso do processador beirava os 90%. A causa dessa lentidão era o fato de que a renderização de vídeo por hardware do Raspberry Pi estava desabilitada. Isso fazia com que a renderização fosse feita por software, não utilizando o potencial do processador de vídeo. Para resolver esse problema, bastou habilitar o driver OpenGL nas configurações do sistema operacional Raspbian. Isso resolveu o problema momentaneamente, já que os testes estavam sendo feitos com o Raspberry Pi conectado numa TV de LCD comum. Para a montagem do protótipo de interfone foi adquirido um display de LCD de 5 polegadas. Para funcionar foi necessário instalar um driver que acompanhou o display. Após a 99 instalação feita, ao fazer os testes de chamada, o problema retornou. Foi descoberto que esse driver sobrescrevia o do OpenGL, impossibilitando a aceleração por hardware ao utilizar esse display. A primeira tentativa para uma nova solução, que funcionasse sem renderização de vídeo por hardware, foi mudar as configurações do Linphone. Foi baixada a resolução de vídeo para QCIF (176x144), a mais baixa possível. Ao testar, não fez efeito. Como a renderização por software utiliza o processador principal ao invés do processador de vídeo, chegou-se à conclusão que seria necessário um processador mais forte que o de 900 MHz do Raspberry Pi modelo 2B. Por esse motivo, foi adquirido um Raspberry Pi modelo 3B+, com seu processador de 1,4 GHz. Ao efetuar os mesmos testes com o Raspberry Pi modelo 3B+, o resultado foi o mesmo. Antes de chegar à conclusão de que não seria viável efetuar chamadas de vídeo utilizando renderização por software, novamente foram testadas as configurações do Linphone. Mudando diversas configurações, muitas sem nenhuma relação com chamadas de vídeo, foi constatado que ao utilizar o Linphone através dos scripts Linphonecsh, o arquivo de configuração não estava sendo carregado na inicialização. A documentação do conjunto de scripts Linphonecsh não tinha essa informação. Utilizando um parâmetro a mais no comando de inicialização do Linphone, foi possível carregar esse arquivo e aplicar as configurações editadas. Ao carregar as configurações do Linphone, a resolução QCIF foi aplicada, e foi suficiente para que o vídeo das chamadas fosse executado de forma fluída, mas com baixa resolução. Apesar da resolução baixa, a imagem não é prejudicada porque o display LCD utilizado no protótipo do interfone tem apenas 5 polegadas. 3.4.3 Comparação com os trabalhos correlatos O Quadro 27 apresenta um comparativo entre características deste trabalho e dos trabalhos correlatos. As características em comum entre todos os trabalhos são a utilização de protocolos VoIP para a comunicação e o modelo cliente-servidor para essa comunicação. Todos usam o protocolo SIP. Em relação aos objetivos, o trabalho mais parecido com o proposto é o de Destefani e Paukner (2013). Ambos são sistemas VoIP para automação residencial com foco em segurança e com comunicação com equipamentos externos. A diferença é que o trabalho de Destefani e Paukner (2013) foi feito para implementar funcionalidades de telefonia com voz. O trabalho proposto implementa funcionalidades de interfone com vídeo. 100 Os quatro trabalhos utilizam o modelo cliente-servidor para comunicação. O trabalho de Destefani e Paukner (2013) e o proposto utilizam o PABX IP Asterisk. O trabalho de Leite (2014) utiliza uma arquitetura própria. Já o trabalho de Américo Filho et al. (2012), que é um telefone IP, não tem foco em um PABX IP específico, abstraindo-o. A comunicação por vídeo está presente no trabalho de Leite (2014) e no trabalho proposto. Outra semelhança entre os dois é o uso da biblioteca Liblinphone. A diferença é que o trabalho proposto utiliza essa biblioteca de forma indireta, utilizando a aplicação pronta Linphone. O trabalho de Américo Filho et al. (2012) também utiliza o Liblinphone. Com exceção do trabalho de Américo Filho et al. (2012), todos os trabalhos utilizam como cliente VoIP o minicomputador Raspberry Pi. O trabalho de Américo Filho et al. (2012) utiliza uma arquitetura própria, a partir de um microprocessador do tipo DSP. Quadro 27 - Comparativo deste trabalho com os correlatos Características Leite (2014) Américo Filho et al. (2012) Destefani e Paukner (2013) Trabalho desenvolvido Comunicação via VoIP Sim Sim Sim Sim Comunicação por vídeo Sim Não Não Sim Arquitetura de hardware própria Não Sim Não Não Modelo clienteservidor Sim Sim Sim Sim Controle de dispositivos externos Não Não Sim Sim Fonte: elaborado pelo autor 101 4 CONCLUSÕES Este trabalho apresentou um projeto de protótipo de interfone sem fio com vídeo. Para esse objetivo, foi construído um sistema de interfones que envolveu a construção de um hardware de interfone usando um minicomputador Raspberry Pi modelo 3B+ e periféricos, um hardware de controlador de equipamentos externos, como portões eletrônicos, utilizando o Raspberry Pi modelo 2B e periféricos e um conjunto de softwares com as funcionalidades necessárias para viabilizar o projeto. As ferramentas e equipamentos utilizados atenderam as necessidades do projeto, tornando-o capaz de executar todas as funcionalidades de interfone propostas. Os softwares utilizados, desde o ambiente de desenvolvimento e linguagem de programação até as aplicações completas de PABX IP e comunicação VoIP mostraram que é possível o desenvolvimento de um sistema de automação residencial e segurança condominial completo utilizando apenas softwares livres. O uso de um minicomputador de propósito geral como o Raspberry Pi possibilitou que a solução ficasse modular, permitindo o uso de diversos equipamentos diferentes para obter as funcionalidades de um interfone. A capacidade da utilização de variados periféricos, sensores e atuadores do Raspberry Pi, além do poder de processamento do mesmo, faz com que o sistema de interfones possa não ser um fim, mas sim um ponto de partida para o desenvolvimento de um sistema de automação residencial e segurança condominial completo e integrado. Novas funcionalidades podem ser acrescentadas ao sistema como a possibilidade de controlar remotamente equipamentos de uma residência (como um ar condicionado, por exemplo), controle de alarmes, controle de acesso, entre outros. Este trabalho foi relevante por mostrar a possibilidade de implementar um sistema de automação residencial e segurança condominial com tecnologias livres e hardwares de fácil acesso. Também contribuiu para mostrar a possibilidade desse tipo de sistema ser desenvolvido para ser utilizado em minicomputadores de propósito geral como o Raspberry Pi. Os testes apresentaram resultados satisfatórios e pode-se concluir que os objetivos propostos foram alcançados. 4.1 EXTENSÕES Para melhorar as funcionalidades deste trabalho ou acrescentar novas, as seguintes extensões são sugeridas: 102 a) desenvolver uma versão para smartphones da aplicação de interfone, permitindo que um smartphone conectado à rede do sistema possa ser usado como um dos interfones, com todas as suas funcionalidades; b) desenvolver uma versão web do software de administração, permitindo que os usuários dos interfones possam consultar seus dados de chamada através de smartphones ou computadores conectados à rede; c) acrescentar recursos de acessibilidade, como comandos de voz, leitor de tela, etiquetas táteis no teclado, etc.; d) acrescentar novas funcionalidades ao sistema de interfone para torna-lo um sistema de automação residencial e segurança condominial mais amplo, como controle de equipamentos de uma residência, controle de alarmes, controle de acesso, entre outros; e) substituir a aplicação Linphone por uma biblioteca que possa ser implementada direto na aplicação de interfone, para que se torne uma única aplicação; f) melhorar a implementação da aplicação de controle de ações para se comunicar com equipamentos externos reais. 103 REFERÊNCIAS AMÉRICO FILHO, J. C. S. et al. Uma Arquitetura de Hardware e Software Livres para um Telefone VoIP. In: SIMPÓSIO BRASILEIRO DE TELECOMUNICAÇÕES, 30., 2012, Brasília. Anais... Brasília: SBRT, 2012. p. 1-2. ASTERISK. A Brief History of the Asterisk Project. [S.l.], 03 fev. 2016. Disponível em: <https://wiki.asterisk.org/wiki/display/AST/A+Brief+History+of+the+Asterisk+Project>. Acesso em: 18 nov. 2018. ASTERISK. Getting Started with Asterisk. [S.l.], 2018. Disponível em: <https://www.asterisk.org/get-started>. Acesso em: 06 nov. 2018. AURESIDE. Automação Residencial: demandas em diversos segmentos da construção civil. Brasil, set. 2015. Disponível em: <https://sebraeinteligenciasetorial.com.br/produtos/noticiasde-impacto/automacao-residencial-demandas-em-diversos-segmentos-da-construcaocivil/55e5d9aac3779d21009a1f5b >. Acesso em: 05 nov. 2018. BANANA PI. Introduction. [S.l.], nov. 2018. Disponível em: <http://wiki.bananapi.org/Main_Page>. Acesso em: 05 nov. 2018. BEAGLEBOARD. What is BeagleBone? Michigan, 2018. Disponível em: <http://beagleboard.org/bone>. Acesso em: 05 nov. 2018. BORDIM, Jacir L. Introdução à voz sobe IP e Asterisk. S.l: Escola Superior de Redes Rnp, 2010. 275 p. Disponível em: <https://pt.scribd.com/doc/127969553/Introducao-a-Voz-sobreIP-e-Asterisk>. Acesso em: 16 nov. 2018. BRYANT, Russell; MADSEN, Leif; VAN MEGGELEN, Jim. Asterisk™: The Definitive Guide. 4. ed. Sebastopol: O’ Reilly Media, Inc., 2013. 806 p. CEDOM. Qué es Domótica. Barcelona, 2018. Disponível em: <http://www.cedom.es/sobredomotica/que-es-domotica>. Acesso em: 05 nov. 2018. CUBIEBOARD DOCS. About. [S.l.], set. 2014. Disponível em: <http://docs.cubieboard.org/introduction>. Acesso em: 05 nov. 2018. DESTEFANI, Felipe Augusto; PAUKNER, Fillipe Luccuin. Servidor VoIP com sistema de segurança doméstica integrada de baixo custo. 2013. 69 f. Trabalho de Conclusão de Curso (Graduação) - Universidade Tecnológica Federal do Paraná, Curitiba. DMESG. O que é VoIP e como ele funciona? Palhoça, 2016. Disponível em: <https://www.dmesg.com.br/o-que-e-voip>. Acesso em: 16 nov. 2018. DONN SOLUÇÕES. Como funciona o sistema Issabel, sucessor do Elastix. São Paulo, 2018. Disponível em: <https://donnsolucoes.com.br/blog/como-funciona-o-sistema-issabelsucessor-do-elastix>. Acesso em: 19 nov. 2018. ELASTIX. Elastix 5 - Your next small business phone system. [S.l.], 2018. Disponível em: <https://www.elastix.org/pbx/small-business-phone-system>. Acesso em: 19 nov. 2018. GESSINGER, Armando K. Automação residencial: no Brasil ao menos, ainda não decolou. [S.l.], 2016. Disponível em: <http://armandogessinger.blogspot.com/2016/03/automacao-residencial-no-brasil-ao.html>. Acesso em: 14 nov. 2018. GROSS, Fabio Danieleski. VoIP com Asterisk. 1ª ed. São Paulo: Linux New Media do Brasil Editora Ltda, 2011. Coleção Academy. 104 LEITE, Diogo Lima Monteiro Costa. Plataforma de comunicação multimédia para dispositivos de baixo custo com o uso de protocolos seguros. 2014. 61 f. Dissertação (Mestrado Integrado em Engenharia Informática e Computação) - Faculdade de Engenharia da Universidade do Porto, Porto. LINPHONE. About. [S.l.], 2017a. Disponível em: <http://www.linphone.org/about.html>. Acesso em: 19 nov. 2018. LINPHONE. Overview. [S.l.], 2017b. Disponível em: < http://www.linphone.org/technicalcorner/linphone/overview>. Acesso em: 19 nov. 2018. LINS, Vitor; MOURA, Waldson. Domótica: automação residencial. Recife, dez. 2010. Disponível em: <http://www.unibratec.edu.br/tecnologus/wpcontent/uploads/2010/12/lins_moura.pdf>. Acesso em: 19 nov. 2018. MARCO LAGOA. Elastix 5 muda o mecanismo de telefonia para 3CX. Londres, 2016. Disponível em: <https://www.3cx.com.br/blog/elastix-5>. Acesso em: 19 nov. 2018. MICROSOFT. Windows 10 IoT Core for Raspberry Pi 2 / 3. [S.l.], 2018. Disponível em: <https://www.microsoft.com/en-us/download/details.aspx?id=55029>. Acesso em: 05 nov. 2018. MIGUEL, Jose Otavio; HENNING, Thomas Cortiano; TURATTI, Matheus Vinicius Barcaro. Automação Residencial: Como acender e apagar lâmpadas pela internet. Curitiba, 2017. Relatório. MURATORI, José Roberto; DAL BÓ, Paulo Henrique. Automação Residencial: histórico, definições e conceitos. 62. ed. São Paulo: Atitude Editorial, 2011. Disponível em: <http://www.instalacoeseletricas.com/download/Automacao_residencial1.pdf >. Acesso em 05 nov. 2018 RASPBERRY PI FOUNDATION. Raspberry Pi 2 Model B. [S.l.], 2018a. Disponível em: <https://www.raspberrypi.org/products/raspberry-pi-2-model-b>. Acesso em: 05 nov. 2018. RASPBERRY PI FOUNDATION. Raspberry Pi 3 Model B+. [S.l.], 2018b. Disponível em: <https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus>. Acesso em: 05 nov. 2018. RASPBERRY PI FOUNDATION. What is a Raspberry Pi? [S.l.], 2018c. Disponível em: <https://www.raspberrypi.org/help/what-%20is-a-raspberry-pi>. Acesso em: 05 nov. 2018. RASPBIAN. Welcome to Raspbian. [S.l.], 2018. Disponível em: <https://www.raspbian.org>. Acesso em: 05 nov. 2018. ROSARIO, Joao Mauricio. Automação industrial. São Paulo: Baraúna, 2009. ROSENBERG, J. et. al. SIP: Session Initiation Protocol. [S.I.], jun. 2002. Disponível em: <https://www.ietf.org/rfc/rfc3261.txt>. Acesso em: 18 nov. 2018. ROSS, Julio. VoIP: Voz sobre IP. Rio de Janeiro: Antenna Edições Técnicas, 2007. 52 p. SCHULZRINNE, H., et al. RTP: a transport protocol for real-time applications. [S.I.], jan 1996. Disponível em: <https://www.ietf.org/rfc/rfc1889.txt>. Acesso em: 18 nov. 2018. UBUNTU DEVELOPER. Get started. [S.l.], 2018. Disponível em: <https://developer.ubuntu.com/core/get-started>. Acesso em: 05 nov. 2018. UCLINUX. Embedded Linux/Microcontroller Project. [S.l.], 2018. Disponível em: <http://www.uclinux.org>. Acesso em: 05 nov. 2018.