CENTRO UNIVERSITÁRIO VILA VELHA CURSO DE CIÊNCIA DA COMPUTAÇÃO Alessandro Silveira Gonçalves Érica de Castro Roque Frederico da Silva Lamonica ACIONAMENTO 3D - ESTENDENDO PARA INTERNET VILA VELHA 2008 Alessandro Silveira Gonçalves Érica de Castro Roque Frederico da Silva Lamonica ACIONAMENTO 3D - ESTENDENDO PARA INTERNET Trabalho de Conclusão de Curso apresentado ao Centro Universitário de Vila Velha como requisito parcial para a obtenção do grau de Bacharel em Ciência da Computação. Orientador: Marcelo Oliveira Camponez VILA VELHA 2008 Alessandro Silveira Gonçalves Érica de Castro Roque Frederico da Silva Lamonica ACIONAMENTO 3D - ESTENDENDO PARA INTERNET BANCA EXAMINADORA Prof. Msc. Marcelo Oliveira Camponez Centro Universitário Vila Velha Orientador Prof. Msc. Marcelo Brunoro Centro Universitário Vila Velha Prof. Msc. Otacílio José Pereira Centro Universitário Vila Velha Trabalho de Conclusão de Curso aprovado em 26/11/2008. Aos meus pais pelo incentivo e carinho, a todos os meus familiares, a todos os meus colegas/amigos que torceram para mim e a todos os professores que me ajudaram na elaboração do trabalho. AGRADECIMENTOS Primeiramente agradeço a Deus por ter feito com que nós estivéssemos aqui para a conclusão de mais uma etapa de nossas vidas. Agradeço também a nossos pais, mães e familiares que na hora do descanso nos deram a motivação maior de continuar este trabalho. Agradeço também aos meus colegas de classe que nos ajudaram de forma direta e indireta na conclusão do curso. E não poderia deixar de agradecer a todos os professores, coordenadores, monitores e outros. Faço um agradecimento em especial ao meu coordenador de monografia, Marcelo Oliveira Camponez, por ter orientado o caminho para a elaboração do trabalho de conclusão de curso. A ciência pode construir o computador, mas não o operador." Dr. Werner LISTA DE TABELAS 1 CAMADAS E PROTOCOLOS. . . . . . . . . . . . . . . . . . . . . . . . 15 2 COMPARATIVO ENTRE AS ENGINES . . . . . . . . . . . . . . . . . . . 20 3 COMPARATIVO ENTRE EDITORES . . . . . . . . . . . . . . . . . . . . 21 4 COMPARATIVO ENTRE O RS-232 E O RS-485. . . . . . . . . . . . . . 25 5 DISTRIBUIÇÃO DOS PONTOS ELÉTRICOS. . . . . . . . . . . . . . . . 39 6 CUSTO MATERIAL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 7 CUSTO MÃO-DE-OBRA. . . . . . . . . . . . . . . . . . . . . . . . . . . 40 LISTA DE FIGURAS 1 Utilização dos protocolos TCP/IP para formar a estrutura de comunicação de rede (correio-eletrônico), compartilhamento de arquivos. . . . 15 2 Estrutura de rede TCP/IP conectada a Internet. . . . . . . . . . . . . . . 16 3 Computação Gráfica e subáreas. . . . . . . . . . . . . . . . . . . . . . . 17 4 Coordenada da câmera. . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5 Esquema de camadas do projeto. . . . . . . . . . . . . . . . . . . . . . 26 6 Diagrama de seqüência. . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 7 Funcionamento do protocolo TCP/IP. . . . . . . . . . . . . . . . . . . . . 32 8 Comunicação com o socket. . . . . . . . . . . . . . . . . . . . . . . . . . 33 9 Código. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 10 Diagrama de classe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 11 HAL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 12 Comunicação RS-232. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 13 Comunicação RS-485. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 14 Dispositivo AMP-12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 SUMÁRIO RESUMO 1 INTRODUÇÃO 11 2 REFERENCIAL TEÓRICO 14 2.1 TCP/IP (Transmission Control Protocol / Internet Protocol) . . . . . . . . 14 2.1.1 Protocolo TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.1.2 Protocolo IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.2 Computação Gráfica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.3 Engine 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.4 Editores 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.5 Banco de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.6 RS-232 e RS-485 23 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Desenvolvimento 26 3.1 Cliente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.1.1 TCP/IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.2 Servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.3 Banco de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.4 Hal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.5 Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4 FINANCEIRO 39 5 CONCLUSÃO 41 6 TRABALHOS FUTUROS 42 ANEXO A -- Anexo A - Código desenvolvido do Cliente 43 ANEXO B -- Anexo B - Código desenvolvido do Servidor 68 RESUMO Neste projeto é desenvolvida uma aplicação cliente-servidor, no qual parte-se de uma interface 3D (modelo 3D do ambiente controlado) instalada em seu computador pessoal. O usuário será capaz de controlar o ambiente, acionando equipamentos elétricos (lâmpadas, ventiladores, motores, etc.) através da Internet. Esta aplicação é uma continuação de um TCC (Trabalho de Conclusão de Curso) feito anteriormente, no qual cliente e servidor eram executados na mesma máquina. Neste trabalho, cliente e servidor ficam situados em computadores diferentes interligados por uma rede TCP/IP. Palavras-chave: Computação Gráfica, redes de computadores, banco de dados, RS 232, RS 485 e RS 422. 11 1 INTRODUÇÃO A Internet surgiu em meados dos anos 1960 e 1970 durante a Guerra Fria. Importantes informações eram armazenadas em servidores que se localizavam em quartéis generais estratégicos, e o medo de perdê-las no caso de um ataque a esses estabelecimentos era enorme. Nesse momento nos Estados Unidos, a ARPA (Agência de Projetos de Pesquisas Avançadas) criou a primeira rede - ARPAnet - com o objetivo de conectar os computadores dos seus departamentos de pesquisa. Com o passar dos anos, as universidades e outras instituições que faziam trabalhos relativos à defesa tiveram permissão para se conectar a ARPAnet. A rede havia crescido tanto que seu protocolo de comutação de pacotes, o NPC, tornou-se inadequado tendo que mudar para um novo protocolo chamado TCP/IP. Em meados dos anos 1990, a Internet deixou de ser uma instituição de natureza apenas acadêmica e passou a ser explorada comercialmente. Foi criado o primeiro browser para a web, fazendo com que a Internet se popularizasse cada vez mais e começasse a fazer parte do cotidiano de pessoas comuns. Atualmente há vários tipos de serviços disponíveis na Internet, desde uma simples compra em um site, jogos virtuais e até mesmo cirurgias. Isso é possível graças a enorme expansão da Internet e das tecnologias que a usam, como softwares (usados para as conexões entre os clientes / servidores e para o controle dos dispositivos) e hardwares (usados como a parte física, no caso de uma cirurgia seriam as mãos e ferramentas do médico). Uma das tecnologias mais usadas na Internet é o comércio eletrônico (E-Commerce). Em 1995, surgiu a primeira empresa de e-commerce, a americana Amazon.com, e cinco anos mais tarde essa tecnologia veio para o Brasil. O ato de comprar e vender pela Internet foi tão bem aceito pela sociedade, que em 2005 houve um movimento de R$ 12,5 bilhões em compras on-line no Brasil. E não para por ai, a estimativa para 2010 é de R$ 100,90 milhões. (Gazeta Mercantil, 04.01.2006) De acordo com o site 12 WNews no ano de 2005, cientistas australianos da Universidade de Queensland realizaram a primeira cirurgia a laser via Internet para operar células que estavam em San Diego, na Califórnia. Eles utilizaram um software chamado de RoboLase para produzir furos com menos de um milésimo de milímetro em células humanas. Os dois laboratórios precisaram de um link de um gigabyte por segundo para garantir a precisão da operação. Além disso, conseguiram operar ferramentas como pinças a laser para imobilizar um espermatozóide em movimento. Atualmente, uma prática que vem se tornando mais comum pela Internet são os jogos onlines. Na Internet há milhares de gêneros (ação, estratégia, tiro, etc). Como exemplos podemos citar: Quake, Counter-Strike e Second Life. Esses simulam um ambiente onde o usuário é um personagem que interage com outros jogadores. Todos os usuários têm a aplicação em funcionamento no próprio computador e estão conectados a Internet. A conexão é feita da seguinte forma: tendo a aplicação do jogo iniciada, ela se conecta ao servidor via Internet e faz a integração com os outros usuários. Uma vertente que utiliza a internet e vem se destacando cada vez mais no mercado mundial é a domótica, também conhecida como edifícios inteligentes. Com a finalidade de trazer mais conforto, comodidade e segurança para a vida agitada das pessoas, essa área tem como característica controlar aparelhos eletrônicos por meio de uma central computadorizada. Esse tipo de aplicação tem atraído olhares de empresas e clientes particulares e tem sido utilizada não só pela comodidade e conforto, mas também pela economia de energia elétrica. Usando computadores, telefones móveis e outros meios que se conectam a Internet, os usuários podem controlar todos os equipamentos de sua casa como luz, cortinas, ar condicionado, entre outros aparelhos eletrônicos. A domótica está presente na aplicação que será desenvolvida neste TCC, de forma que um usuário através de seu computador pessoal (cliente) entrará na aplicação que simulará uma casa em 3D, e através dela acionará dispositivos (lâmpadas, motores e etc) de sua casa real. Ao selecionar o acionamento / desacionamento, a aplicação automaticamente se conectará ao computador servidor via Internet e passará o comando de acionamento da carga especifica. A casa 3D será uma réplica virtual da casa real, para facilitar os controles de acionamento. Serão necessários alguns dispositivos para realizar os acionamentos, pois eles servirão de forma intermediária entre o computador servidor e os motores, lâmpadas e outras cargas. 13 Esse projeto é a continuação de uma aplicação desenvolvida no ano de 2007, quando foi criado um software que executado em um computador pessoal, era capaz de controlar em uma residência itens como: lâmpadas, motores, entre outros aparelhos eletrônicos. Para interface com o usuário foi desenvolvido um modelo em 3D, que é uma réplica do ambiente real. A interação acontece semelhante a um jogo em primeira pessoa. O acionamento da carga elétrica se dá a partir de dispositivos diretamente ligados ao computador pessoal através de um conversor RS-232. O projeto atual é semelhante ao anterior, porém usa a Internet como mediadora do acionamento. O objetivo deste TCC é separar a interface 3D que controla o ambiente do computador servidor, tendo a mesma, sua localização no computador pessoal do usuário. Serão feitas mudanças na aplicação para que quando o usuário acionar alguma carga no ambiente 3D seja enviado o comando para o servidor. Esse envio será feito através da Internet. O servidor deverá ser modificado para aceitar conexões vindas do cliente, interpretar o comando recebido, se comunicar com um banco de dados e com os dispositivos de acionamentos. 14 2 REFERENCIAL TEÓRICO Neste item será feita uma revisão teórica dos principais conceitos e tecnologias que serão utilizados, como por exemplo: TCP/IP, engines, editores, banco de dados, entre outros. 2.1 TCP/IP (Transmission Control Protocol / Internet Protocol) A história do TCP/IP começa com a ARPANET. Nesse período universidades e repartições públicas se conectavam a ela através de uma linha telefônica. Com a evolução da tecnologia, redes de rádio e satélite começaram a usar a ARPANET, porém surgiram problemas com os protocolos já existentes e isso forçou a criação de uma nova arquitetura de referência. Em 1974, foi criado por Cerf e Kahan o Modelo de Referência TCP/IP. De acordo com Tanenbaum (2001), o TCP/IP é uma arquitetura flexível capaz de se adaptar a aplicações com necessidades diferentes, como por exemplo: transações bancárias e transmissão de Voip (voz sobre IP). Ela é dividida em cinco camadas: • Camada física: define a organização da estrutura de conexão física entre o sistema computacional e a rede. Usa estruturas como conectores, cabeamento e etc. • Camada de enlace: tem a função de fazer a transmissão de informações entre computadores, desde que haja um meio físico conectando-os. • Camada de rede: trata da comunicação entre as máquinas. Ela é responsável pelo roteamento dos dados desde a origem até o destino desejado. • Camada de transporte: responsável por pegar os dados enviados da camada de 15 aplicação e enviá-los à camada de rede. Ele conecta programas, diferente das camadas que conectam equipamentos. • Camada de aplicação: fornece uma interface direta com os aplicativos do usuário, fazendo a comunicação entre os aplicativos. A Tabela.1 relaciona os principais protocolos de cada camada CAMADAS Física Enlace Rede Transporte Aplicação PROTOCOLOS RDIS, RS-232, EIA-422, RS-449, USB Ethernet, 802.11 WIFI, IEEE 802.1 Q, 802.11g, HDLC, PPP, Token Ring, Frame Relay IP (Ipv4, Ipv6), ARP, RARP, ICMP, IPSec TCP, UDP FTP, Telnet , SMTP , DNS , HTTTP, POP3, RDP Tabela 1: CAMADAS E PROTOCOLOS. Seguem nas Figura.1 e Figura.2 alguns exemplos de aplicações de arquiteturas distintas de rede baseadas em TCP/IP, por exemplo, redes internas de empresas baseadas em transporte TCP/IP, serviços de redes de empresas online e provedores de acesso a Internet. Figura 1: Utilização dos protocolos TCP/IP para formar a estrutura de comunicação de rede (correio-eletrônico), compartilhamento de arquivos. 16 Figura 2: Estrutura de rede TCP/IP conectada a Internet. 2.1.1 Protocolo TCP Protocolo que especifica o formato dos dados e das confirmações que dois computadores trocam, e os procedimentos para assegurar que os dados cheguem corretamente. O protocolo TCP divide o processo de comunicação em três fases: • O cliente envia segmento tipo SYN (pedido de conexão). • O servidor reconhece o pedido de conexão enviando segmento tipo SYN com bit de reconhecimento (ACK) ligado para o cliente. • A transferência de dados e o encerramento da conexão podem ser iniciados tanto pelo cliente como pelo servidor enviando um segmento FIN (sinalizando fim da conexão). 2.1.2 Protocolo IP É o protocolo responsável pelo roteamento entre redes em uma estrutura de rede TCP/IP, provendo a capacidade de comunicação entre cada elemento componente da rede para permitir o transporte de uma mensagem da origem até o destino. 17 2.2 Computação Gráfica Segundo a ISO (International Organization for Standardization), Computação Gráfica pode se definir como: um conjunto de ferramentas e técnicas para converter dados de um dispositivo gráfico através do computador. [Azevedo, Eduardo] Em 1950, com finalidades acadêmicas e militares, foi criado o primeiro computador com recursos gráficos, o Whirlwind I, desenvolvido pelo MIT. Porém, só em 1959 que surgiu o termo Computer Graphics (Computação Gráfica), criado por Verne Hudson. Para gerar uma imagem por computador é necessário entender a base da computação gráfica, que pode ser dividida em três grandes subáreas: • Síntese de imagens, que representa objetos criados a partir de especificações geométricas; • Processamento de imagens, que seria a forma digital de melhorar uma imagem; • Análise de imagens, onde é feita uma análise da imagem para a obtenção das características desejadas. O diagrama da Figura.3 ilustra o relacionamento da Computação Gráfica e suas subáreas. Figura 3: Computação Gráfica e subáreas. Neste TCC, o foco na utilização da Computação Gráfica está na síntese de imagens, principalmente em 3D. Por este motivo, o texto a partir deste ponto se aprofundará apenas nesta subárea, sendo descrito a partir da visão do usuário final. Existem vários softwares chamados de editores gráficos, que auxiliam na manipulação e na criação de imagens e cenas. No mercado existem vários tipos de editores, 18 porém quanto mais especifico for o software para a criação, mais real será a imagem final. As cores de uma imagem projetada na tela do computador são compostas por clusters. Um cluster é composto de três pixels (pontos que compõem uma imagem), sendo cada um de uma cor (vermelho, azul e verde, que ao serem projetadas se misturam opticamente). Esse espaço de cor projetado é chamado de RGB (Red, Green, Blue). Os desenvolvedores, a fim de obter uma representação gráfica virtual realista, precisam trabalhar diretamente ou indiretamente com a manipulação de pontos de um gráfico matricial (pixels). [Corrigan, John] Para a representação e manipulação de imagens são usados gráficos vetoriais (imagens formadas por cálculos matemáticos executados pelo computador) e gráficos matriciais (imagens formadas pelo preenchimento de uma matriz de pixels)[Azevedo, Eduardo]. As características das imagens, sejam matriciais ou vetoriais, são: Imagens Matriciais: • Formadas por uma grade matricial composta por pixels; • Por ser baseada em pixels, geralmente são usadas para imagens desenvolvidas em um programa de pintura ou para processar imagens fotográficas; • São exemplos de imagens criadas com os programas Corel Photopaint e Adobe Photoshop. Imagens Vetoriais: • Constituídas por linhas e curvas definidas matematicamente, de espessura e cor constante; • Por ter a definição matemática, a imagem pode se movida, redimensionada ou rotacionada como um objeto independente; • São exemplos de imagens criadas pelos programas Corel Draw e Adobe Ilustrador. A geração de imagens 3D pelo computador é dada a partir da descrição dos elementos que compõe uma cena. Uma imagem é composta por três tipos diferentes de elementos: os objetos, as fontes de luz e as câmeras. Geralmente são eles que são visualizados na imagem final. 19 Um objeto, ou um nó como é descrito nos editores 2D e 3D, é um desenho que compõe uma cena e pode ser caracterizado por dois tipos de atributos: os ópticos e os geométricos. O primeiro está associado a características como cor, textura, transparência e brilho. O segundo se baseia na sua forma geométrica e no espaço em que ocupa. A iluminação de uma cena é dada a partir das fontes luminosas que a compõe. São elas que permitem que o objeto seja visto. Existem vários tipos, como: • Ambiente: representada por uma iluminação uniforme; • Pontual: representada por um ponto de luz, que é introduzido em todas as direções; • Spot: definida por um cone de iluminação; O último elemento que compõe a síntese de uma imagem é a câmera. Ela é responsável pela projeção de um plano de imagem bidimensional em um plano tridimensional. O plano tridimensional é controlado pelas posições x, y e z. Podemos citar como elementos o ponto de observação, a orientação e o foco. Ponto de observação é representado pela localização da câmera dentro da cena. O foco representa para onde a mesma está apontando. A orientação é controlada pela posição x, y, z, pelo foco e pelo vetor que indica a vista superior da cena 3D.[Azevedo, Eduardo]. A Figura.4 representa os elementos de uma câmera. Figura 4: Coordenada da câmera. Para fazer a animação das imagens criadas pelos editores 3D são usadas APIs gráficas, que são conjuntos de rotinas e padrões utilizados por programas aplicativos, os quais fazem a comunicação entre o modelo 3D, o software e o hardware das placas de vídeo. Os mais conhecidos hoje em dia são o DirectX e o OpenGL. 20 2.3 Engine 3D O desenvolvimento de aplicações com imagens 3D utilizando DirectX e OpenGL, que são APIs complexas por serem chamadas rotinas de baixo nível, não possibilita uma boa produtividade, o que estimulou os desenvolvedores a criarem engines 3D (encapsulamento das APIs de baixo nível). Em meados da década de 90, eram utilizadas engines para auxiliar o programador na criação de ambientes 3D. O uso dessas bibliotecas de código se tornou mais freqüente depois da criação dos jogos Quake e Doom. Ao invés dos programadores começarem a desenvolver um novo jogo do início, eles utilizavam rotinas já prontas. Em 1998, essa prática era tão comum que se pagava muito caro por uma licença do código. Existem várias ferramentas no mercado, como por exemplo, Irrlicht, Agar, 3D Coding BlackHole Engine, 3DgameStudio, entre outros. Cada biblioteca possui características próprias como ferramentas especificas, funcionalidades suportadas, APIs gráficas encapsuladas, linguagens de programação disponível, plataformas, som e vídeo, recursos gráficos como iluminação, sombreamento, malhas e texturas. Cabe ao desenvolvedor escolher a engine que mais se adapta ao sistema a ser criado. A Tabela.2 mostra um comparativo entre diversas engines no mercado. Engines Irrlicht C4 Engine Torque Game Engine Reality Factory TV3D SDK 6.5 3DGameStudio OGRE Open Source X X Uso Comercial X X X X X APIS Gráficas OpenGl | Directx OpenGl OpenGl | Directx OpenGl | Directx Directx Directx OpenGl | Directx Linguagem de Programação C/C++,ASP.Net C/C++ C/C++ C/C++ C/C++,ASP.Net C/C++,Delphi C/C++ Tabela 2: COMPARATIVO ENTRE AS ENGINES 2.4 Editores 3D São ferramentas usadas para o desenvolvimento de objetos, personagens, cenários, entre outras coisas em três dimensões. Existem vários tipos de editores, como: 3D Studio Max, Rhinoceros 3D, LightWave 3D, IrrEdit, Maya, Cinema 4d, SketchUp, 21 ZBrush, Blender, L3P, Wings 3D, AutoCad, QC Pro, Promob, Corel Bryce, entre outros. A Tabela.3 mostra uma pequena comparação entre os editores mais populares. Editores Desenvolvida por 3D Studio Max IrrEdit Maya Blender Discreet,Kinetix Ambiera Alias Blender Foundantion Usada para desenvolvimento de Personagens Cenários Cenários Objetos Extensões .3ds, .dxf, .dwg .bsp, .irr, .irrmesh .rpm, .ma .dxf,.x,.flt, .dae,.ply Tabela 3: COMPARATIVO ENTRE EDITORES 2.5 Banco de dados Os sistemas de banco de dados surgiram na década de 60, como uma evolução dos sistemas de informação baseados em arquivos em discos magnéticos. No início da computação, o armazenamento de dados ocorria dentro dos programas. Com o surgimento dos discos magnéticos, os dados passaram a ser armazenados de forma distinta do código executável dos programas. [C. J. Date, 2004] Para resolver o problema de armazenamento e recuperação de informações são usados bancos de dados. Esse sistema de armazenamento deve ser usado quando um conjunto de informações possui muitas variáveis interligadas entre si. Essas funcionalidades, como por exemplo: cadastro, recuperação e relacionamento entre dados, muitas vezes não são encontradas em sistemas de arquivos comuns. A seguir é mostrada a diferença entre usar um banco de dados e um sistema de arquivo. Sistema de banco de dados • Dados e metadados: dados e descrições são armazenados na base e gerenciados pelo SGBD. • Independência de dados: a modificação de um campo não afeta o programa. • Redundância: único repositório de dados, eliminando o problema de redundância. Sistema de arquivos 22 • Dados e Meta-Dados: Dados são armazenados através de interação com aplicações. • Independência de Dados: Modificação de um campo afeta o programa. • Redundância: Gasto de espaço e necessidades de esforços para manter consistência. Ao longo do tempo foi criada uma arquitetura para sistemas de banco de dados, com o objetivo de separar o banco de dados físico das aplicações com o usuário, por meio de três níveis de esquemas [C. J. Date, 2004]: • Esquema interno: descreve a estrutura física de armazenamento do banco de dados, a organização de arquivos e seus métodos de acesso. • Esquema conceitual: descreve a estrutura do banco de dados representando os dados que vão ser utilizados, escondendo os detalhes de armazenamento. • Esquema externo: descreve os dados, ou parte dos dados, que mais interessam aos usuários. Como exemplo de modelos de bancos de dados, podemos citar: banco de dados relacional, orientado a objeto, hierárquico, entre outros. Neste texto descreveremos dois modelos, o orientado a objeto e o relacional. • Banco de dados relacional: no modelo relacional, o banco organiza os dados em relações. Cada relação pode ser vista como uma tabela, na qual cada coluna corresponde a atributos da relação, e as linhas correspondem a registros ou elementos da relação. O relacionamento entre tabelas é feito a partir de chaves. Uma chave é um conjunto de um ou mais atributos que determinam a unicidade de cada registro. Temos dois tipos: chave primária, que é a chave com a função de identificar cada registro dando-lhe unicidade (nunca se repetirá), e chave estrangeira, formada através de um relacionamento com a chave primária de outra tabela. • Banco de dados orientado a objeto: neste modelo as informações são armazenadas em forma de objetos. Os dados só podem ser manipulados pelos métodos definidos pela classe a que estes objetos pertencem. O acesso aos dados pode ser rápido, já que as junções geralmente não são necessárias pois um objeto pode ser obtido diretamente sem busca, seguindo os ponteiros [Kim, Won, 1990]. 23 Um fator que leva à adoção do banco de dados orientado a objetos no lugar do banco de dados relacional, é que no relacional a dificuldade em manipular dados complexos é maior. Outro fator se encontra na manipulação dos dados, que é feita através de uma aplicação, tendo seu código a necessidade de ser traduzido entre a representação do dado e os registros da tabela relacional, o que consome tempo. Um sistema de banco de dados pode ser utilizado em vários tipos de aplicações. Uma delas é uma aplicação cliente - servidor. Quando uma aplicação para o ambiente cliente - servidor é projetada, ela estará fisicamente separada do banco de dados por várias camadas de componentes. [MELO, Rubens; SILVA, Sidney; TANAKA, Asterio, 1997] Seu funcionamento se baseia no seguinte esquema: o usuário do sistema, através da aplicação cliente, envia o pedido de requisição a aplicação servidor, que por sua vez devolve ao cliente os resultados solicitados. As aplicações rodam sobre o controle do sistema operacional que coordena todos os recursos do sistema computacional utilizado. 2.6 RS-232 e RS-485 No início da década de 1960, o RS-232 foi criado para a conexão de modens e impressoras nos computadores da IBM e era definido como o único meio para aumentar a distância de comunicação serial à baixa taxa de baund (velocidade em que os dados são enviados através de um canal) [Tanenbaum, Andrew S., 2001]. As principais limitações do RS-232 são: ele é ponto a ponto, que é uma restrição severa quando vários instrumentos são necessários, e a distância máxima de 15 metros, que é curta para a maioria dos sistemas de controle. No RS-232, os sinais são representados por níveis de tensão referentes ao fioterra, possuindo um fio para transmissão e outro para recepção. A especificação do RS-232 define: • Sinais elétricos característicos; • Características mecânicas da interface; • Descrição funcional dos circuitos. 24 O RS-232 é popular e bastante utilizado, apesar de possuir muitas limitações. Em conseqüência, outras interfaces que superam algumas dessas limitações têm sido bastante utilizadas, como o RS-485 e o RS-422. As mesmas são interfaces seriais comumente confundidas uma com a outra, muito bem sucedidas em aplicações industriais e no controle das aplicações, onde é necessária a comunicação entre elas, mesmo não sendo diretamente compatíveis. No começo dos anos 70 foi introduzida a interface RS-422, que é usada por um sistema de dois fios separados para cada sinal. Isso permite uma grande transmissão de dados e minimiza os problemas de variação do potencial do solo, já que o mesmo não é usado como referência de voltagem, como o RS-232. O RS-485 é o mais versátil entre as interfaces RS citadas, tendo semelhanças com a RS-422. Permiti uma grande distância de comunicação e uma grande velocidade de transferência de dados. Além disso, aumenta o número de transmissões e recebimentos na linha, o que o torna muito útil quando o sistema usa vários instrumentos ou controladores que podem ser conectados na mesma linha [John Park, Steve Mackay e Edwin Wright, 2003]. A maior diferença entre eles é que o RS-485 é usado por um sistema de dois fios multidrop, que transmite dados em uma única direção por vez em um canal bidirecional e o RS-422 é usado por um sistema de quatro fios ponto a ponto, que transmite dados em um canal em duas direções simultaneamente. O RS-232 e o RS-485 são comumente confundidos um com o outro. A Tabela.4 mostra as principais diferenças entre o RS-232 e o RS-485: 25 TRANSMISSOR Modo de operação Max. no. de drivers e receptores Tamanho do cabo recomendado Taxa máxima de transferência de dados Voltagem máxima Sinal do driver de saída Programa de carga Sensibilidade do receptor Resistência do receptor de entrada RS-232 Desequilibrado 1 driver e 1 receptor 15 metros 20 Kbps RS-485 Diferencial 32 drivers e 32 receptores 1200 metros 10 Mkps +20V a -20V +- 5.0V mínimo +- 25V máximo >3 ohm +- 3.0 V +1V a -1V +- 1.5V mínimo +- 6.0V máximo 120 ohm +- 200 mV -12V <= Vem <= 12V > 12 kiloohm 3 kiloohm a 7 kiloohm Tabela 4: COMPARATIVO ENTRE O RS-232 E O RS-485. 26 3 Desenvolvimento A solução proposta para este TCC foi dividida em 5 camadas. Para cada camada é desenvolvida uma aplicação própria, tornando possível a transferência de informações desde um computador cliente, passando pelo servidor e chegando até o acionamento de uma carga. Na Figura.5 abaixo, são mostradas as cinco camadas e o relacionamento entre elas: Figura 5: Esquema de camadas do projeto. A primeira camada será a do cliente, onde o usuário terá o controle de sua casa, interagindo com uma interface 3D. A segunda camada, a do servidor, terá uma aplicação desenvolvida para o controle das informações vindas do cliente. A camada de banco de dados conterá todas as informações da casa (quartos, localização das lâmpadas e etc), o estado em que as cargas estão (acionadas ou não), e o comando que acionará a carga específica. Uma quarta camada, apelidada de HAL (Hardware 27 Abstraction Layer), será a intermediária entre o banco de dados e a camada de hardware. A última camada é a de hardwares. É nessa camada que se encontram os dispositivos RS-232, RS-485 e o conversor, os quais controlarão fisicamente o acionamento de cargas. Os dispositivos e o conversor usados neste projeto serão fornecidos pela empresa KRL Tecnologia. Na Figura.6 é mostrado o diagrama de seqüência da aplicação. Figura 6: Diagrama de seqüência. 3.1 Cliente O projeto é iniciado no computador do cliente, onde existirá uma aplicação simulando o ambiente que será controlado, dada na forma de uma interface em três dimensões. A aplicação será uma réplica fiel do ambiente, por exemplo, de um apartamento. Ela será criada a partir da ferramenta irrEdit. IrrEdit é uma ferramenta que edita ambientes em três dimensões e a luminosidade dos mesmos. Nela foi criado um protótipo de um quarto para que fosse possível simular a funcionalidade do projeto. Ao ser criado o quarto estará somente com sua moldura, faltando então adicionar objetos tais como: lâmpadas, interruptores e etc. A inserção desses objetos é dada através de engines, dentre elas a IrrLitch que foi usada neste TCC. A IrrLitch foi usada como editor de objetos do ambiente e a integração deles com o sistema. Ela funciona através da linguagem C++, sendo a codificação feita dentro do compilador DevC++. Cada objeto no código é dado em forma de uma figura na cena. Tanto a IrrEdit quanto a IrrLitch foram utilizadas para a criação e modelagem 28 do ambiente, e para o posicionamento dos objetos na cena. Sendo um projeto de continuidade, estas ferramentas serão utilizadas também com o fim de modificar o ambiente atual e a ação dos objetos em cena. A diferença entre este TCC e o antigo é o comportamento dos objetos. Antes, ao clicarmos em um interruptor, a própria aplicação implementada se conectava aos dispositivos para o acionamento da lâmpada. Hoje, a conexão com os dispositivos é feita pelo servidor, cabendo então ao cliente informar ao servidor qual lâmpada deverá ser acionada. Neste projeto, o principal foco foi separar a aplicação 3D, que está no computador do cliente, do acionamento das cargas presentes no servidor, que se encontra no ambiente controlado. A comunicação e a troca de informações entre eles serão dadas pela Internet, através do protocolo TCP. Tanto o computador cliente quanto o servidor deverão estar conectados a Internet, para que a troca de informações seja realizada. Se um dos dois não estiver devidamente conectado a troca de informações será falha, e o sistema retornará um erro de falha na conexão. A aplicação Cliente foi desenvolvida no paradigma de orientação a objetos. Nesse caso, o programa foi modelado em quatro objetos: CMainMenu, Serial, CAmbiente, Main A Classe CMainMenu é formada por: • CMainMenu() - O construtor da classe é iniciado com os parâmetros em que o menu deve aparecer, com a engine que será usada, o endereço IP, a porta TCP, e se a tela aparecerá em modo fullscreen. • Bool run (bool outFullscreen, bool outCom1, bool outCom2, vídeo :: E_DRIVER_TYPE outDriver) - Método que requisita as funções responsáveis pela criação do menu. Nele são passadas como parâmetro as variáveis alteradas ou não do bloco principal. Ele é responsável pela criação dos objetos que, por exemplo, tratam a parte gráfica da aplicação, gerenciam todos os nós adicionados à cena, e outros objetos que manipulam dados úteis para a construção do aplicativo 3D. • virtual bool OnEvent(SEvent event) - Usado para tratar eventos vindos do clique do mouse ou quando teclas do teclado são pressionadas. Neste caso, é usado este método para tratar os itens selecionados. • void setTransparency() - Função que aplica transparência no menu. 29 • gui::IGUIButton* startButton - O nome da variável que é informada sobre o pressionamento do botão "START". • IrrlichtDevice *device - Variável principal. É a partir dela que tudo é criado. • s32 selected - Aonde é definido o renderizador escolhido pelo usuário. Na classe Main estão definidas as variáveis que representam as opções de fullscreen e de porta de comunicação apresentadas no menu principal. São definidos também os comandos de chamada para os objetos CMainMenu e CAmbiente. A biblioteca OPENGL é responsável pela criação do menu na classe CMainMenu e do ambiente na classe CAmbiente. Os outros objetos são estruturados de forma diferente. Eles possuem métodos, funções e variáveis necessárias para a criação objetivo. No CMainMenu, é implementado o menu. Ele será composto por duas guias: uma fornecendo algumas opções da aplicação para o usuário, e a outra que irá exibir um texto sobre o projeto. Dessa forma, é necessário criar um controlador de guias. Nessas guias são fornecidas opções para o usuário como: o tipo de renderizador gráfico, a opção de fullscreen e a porta de comunicação. A engine IrrLicht disponibiliza alguns renderizadores gráficos. Esses renderizadores são listados no menu para que atenda aos diferentes usuários de acordo com suas preferências. Depois que o usuário escolheu as opções desejadas, a interação com o ambiente 3D é feita pressionando o botão "Start". Ao selecionar o botão "Start", a aplicação inicia o objeto CAmbiente. Ele possui os métodos responsáveis pela criação do ambiente, os nós responsáveis pela criação da cena, as funções que tratam a parte gráfica da aplicação como textura e cores, e o gerenciador de cena. Estes três nós criados anteriormente são a estrutura básica para qualquer aplicação que utiliza a engine IrrLicht. A partir daí, basta carregar o ambiente criado no editor IrrEdit usando o método LOADSCENE, pois é um arquivo de extensão .irr. Para carregar a cena criada é necessário usar dois nós, sendo um nó responsável pelo ambiente e outro pela iluminação. É preciso extrair o nó ambiente para aplicá-lo à técnica de detecção de colisão no ambiente. A técnica de detecção de colisão é necessária para que quando for criado qualquer objeto dentro de uma cena como, por exemplo, uma parede, um teto, um carro ou móveis, o usuário não os atravesse, dando assim a idéia de estar num ambiente real. Depois de criado o ambiente, uma câmera é necessária para a visualização e navegação dentro da cena. A câmera adicionada é controlada pelas teclas de dire- 30 cionamento e pelo mouse. Para que a câmera não atravesse os objetos dentro da interface é necessário criar um animador de desenhos, pois é ele que irá responder se houve ou não a colisão. Depois deve-se ligá-lo ao nó em que se deseja que a colisão seja feita, que neste caso, é a câmera. Também é necessário criar alguns objetos que participarão do acionamento de dispositivos como, por exemplo, lâmpadas, e outros para dar um pouco de vida ao ambiente. Primeiramente, criamos duas lâmpadas. Uma delas será posicionada no teto, e outra na parede. Estas lâmpadas terão dois estados: apagada e acesa, que serão definidos através de texturas. Para simular o acionamento virtual das lâmpadas, precisa-se criar uma fonte de luz para cada lâmpada e assim como interruptores. E para uma melhor simulação do ambiente real criam-se alguns objetos como janela, porta, quadros, entre outros. Esses objetos serão representados através de texturas. Para identificarmos o alvo da câmera, iremos criar um billboard. Um billboard é um ponto luminoso, geralmente usado para explosões, fogos, e semelhantes. Neste caso, o billboard seguirá o cursor do mouse. Isto é necessário pois o usuário precisa saber aonde estará clicando com o mouse para poder fazer o acionamento das lâmpadas através dos interruptores. Posteriormente criaremos um vetor que indicará o ponto de interseção entre o alvo da câmera e o objeto que ela estará olhando. Para obter esse ponto de interseção, precisamos do ponto de colisão entre o alvo e o objeto que estará sendo observado. O último método escrito no CAmbiente é utilizado para o acionamento dos dispositivos. Este método captura o clique do mouse. Se o usuário clicar com o botão esquerdo em cima de um interruptor, uma lâmpada se acenderá e o objeto Serial será criado. Se o usuário clicar com o botão direito em cima de um interruptor, essa lâmpada se apagará e o objeto Serial será criado. Quando um interruptor for acionado, será mostrada na tela uma lâmpada sendo acesa para que o usuário tenha conhecimento que a conexão com o servidor foi feita e a lâmpada foi acesa no ambiente controlado. A conexão criada é a Cliente / Servidor que foi feita através do protocolo TCP. O cliente se conecta ao servidor e envia uma palavra indicando qual das lâmpadas ou motores tem de ser acionado. Após o envio ter sido realizado, com sucesso ou não, a conexão é destruída, ficando disponível a abertura de novas conexões. 31 3.1.1 TCP/IP A comunicação entre o computador cliente e o computador servidor é feita através do protocolo TCP/IP. TCP/IP, que significa Transmission Control Protocol - Internet Protocol (Protocolo de Controle de Transmissão - Protocolo de Internet), é um protocolo de comunicação entre computadores em rede. A comunicação pelo protocolo é feita através da Internet, obrigando os computadores cliente e servidor a estarem conectados à mesma. A escolha do protocolo TCP/IP foi feita pelo fato dele ser o mais usado em redes. O TCP fornece um serviço de transporte orientado à conexão, e o IP fornece um serviço de rede não-orientado à conexão. Outro fator que facilitou a escolha do TCP/IP foi o fato dele ter arquitetura aberta e qualquer fabricante poder adotar a sua própria versão TCP/IP em seu sistema operacional, sem necessidade de pagamento de direitos autorais a ninguém. Com isso, todos os fabricantes de sistemas operacionais acabam adotando o TCP/IP, transformando-o em um protocolo universal, possibilitando que todos os sistemas possam se comunicar sem dificuldade. Uma das vantagens do TCP/IP em relação aos outros protocolos pesquisados é que ele é roteável, isto é, podem existir vários caminhos para o dado atingir o computador de destino. A escolha de um protocolo de comunicação se deu através de dois outros protocolos, o TCP/IP e o UDP, tendo como finalista o primeiro. A decisão foi baseada na principal diferença entre os dois protocolos e mostrou-se ideal para o projeto: • O TCP é um protocolo orientado à conexão, que inclui vários mecanismos para iniciar e encerrar a conexão, negociar tamanhos de pacotes e permitir a retransmissão de pacotes corrompidos. No TCP tudo isso é feito com muito cuidado, para garantir que os dados realmente cheguem inalterados, apesar de todos os problemas que possam existir na conexão; • O UDP transmite dados pouco sensíveis, como streaming de áudio e vídeo. No UDP não existe checagem nem confirmação. Os dados são transmitidos apenas uma vez. Os pacotes que chegam corrompidos são simplesmente descartados, sem que o emissor sequer saiba do problema. A idéia é justamente transmitir dados com o maior desempenho possível, eliminando dos pacotes quase tudo que não sejam dados. 32 Na Figura.7 é mostrada uma visão geral do funcionamento do protocolo TCP/IP na implementação do projeto, dada da seguinte forma: Figura 7: Funcionamento do protocolo TCP/IP. O protocolo TCP foi implementado no cliente e servidor a partir de sockets. O socket (porta de um canal de comunicação) permite a um processo (executado em um computador) enviar/receber mensagens para/de outro processo que pode estar sendo executado no mesmo computador ou num computador remoto. A Figura.8 mostra as camadas de uma aplicação por sockets. A aplicação no servidor foi implementada começando pela criação de um socket. Em seguida é atribuída a esse, a porta por onde a aplicação cliente solicitará a conexão. O socket é colocado em modo de escuta para poder aceitar pedidos de conexão dirigidos ao mesmo. A aplicação no cliente foi implementada criando-se um socket com os dados de Porta e IP do servidor para realizar a conexão. A conexão é feita quando o cliente cria uma chamada ao servidor através do socket. O servidor, que está executando no modo de escuta, estabiliza a conexão solicitada pela aplicação cliente e cria um canal de comunicação entre os sockets. 33 Figura 8: Comunicação com o socket. Com a conexão estabelecida, a aplicação cliente envia a informação para o servidor. Recebida a confirmação de recebimento do servidor, o cliente encerra a conexão e o servidor continua no modo de escuta, esperando novas conexões. 3.2 Servidor O servidor foi desenvolvido para ficar executando no ambiente real sem parar, esperando que conexões sejam realizadas pelo computador cliente. Mesmo quando a conexão com o cliente é encerrada, o servidor continua executando, esperando novas conexões. O servidor só para de funcionar se ele for desligado ou se não houver conectividade com a Internet. Quando a conexão entre o cliente e servidor é estabelecida, é realizado o envio via Internet de uma palavra por parte do cliente. O servidor executa uma comparação entre a palavra enviada e as cargas que desejam ser acionadas. Feita a comparação, o servidor envia um comando de update para o banco de dados, fazendo uma alteração no estado da carga. Após a alteração, o servidor procura no banco de dados o comando necessário para o acionamento, que se encontra junto ao estado alterado. O comando é enviado através da porta serial, para o acionamento da carga. O envio do comando é feito por um código que se encontra dentro do servidor. Esse código assegura que o dispositivo está conectado com o computador servidor, abre as portas necessárias para o acionamento, as configura e, depois de tudo configurado, a palavra está pronta para ser transmitida. Quando termina a transmissão, 34 as portas seriais utilizadas devem ser fechadas para dar acesso à outra solicitação. 3.3 Banco de dados Para o desenvolvimento do servidor de banco de dados, foi usado o MySQL. O MySQL é uma ferramenta de banco de dados relacional gratuita e desenvolvida pela Sun. Tem como usuários a NASA, o Banco Bradesco, a HP, a Nokia, entre outras empresas. Esse servidor foi escolhido porque possui compatibilidade com a linguagem C++ usada neste projeto, excelente desempenho e estabilidade quando há necessidade de busca de dados, suporte para vários tipos de tabelas e pouco exige quanto a recursos de hardware. O MySQL no computador servidor ficará rodando até que o computador cliente envie uma palavra. Isto acontece quando o usuário através de uma interface 3D clica em um interruptor situado no ambiente virtual. O computador cliente interpreta o posicionamento do click e envia uma palavra indicando o interruptor clicado. Quando a palavra chega ao servidor, é feita uma comparação com a chave primária da tabela "Objetos", identificando qual carga (lâmpada, ventilador, ar condicionado, etc), deve ser acionada. Feita a comparação, é alterado seu estado na tabela, em seguida o HAL envia o acionamento para os dispositivos ligando ou desligando o motor. A implementação é realizada no DevC++. Na Figura.9, é mostrado o momento da conexão com o servidor após ter sido acionado o interruptor. Esta conexão acontece na primeira linha. Quando realizada e verificado qual a palavra foi enviada, é feito um update no banco para que em seguida seja enviado um comando para os dispositivos. Caso ocorra uma falha na conexão é informado o tipo de erro. No banco de dados existirá dois tipo de tabelas: a do objeto, e do cômodo. Na primeira são encontradas as identificações do objeto como chave primária da tabela, a identificação do cômodo, a descrição do objeto, o status informando se está desligado ou ligado, o comando e o endereço MAC. E na segunda encontra-se a identificação do cômodo dita com chave primária da sua tabela e da sua descrição. Na Figura.10 são mostradas as tabelas e suas relações: 35 Figura 9: Código. Figura 10: Diagrama de classe. 36 3.4 Hal Para realizar a comunicação entre o banco de dados e os dispositivos, foi implementada uma aplicação chamada de HAL (Hardware Abstraction Layer). Essa aplicação ficará rodando no servidor com intervalos de poucos segundos até que uma carga seja modificada no banco de dados. Quando isto acontece, a palavra é comparada com o banco existente e seu estado é alterado em seguida. Após este procedimento, o servidor recolhe o comando de acionamento e envia para os dispositivos. Este comando é formado por 8 bits, contendo o endereço MAC do dispositivo 485 e qual a saída a ser acionada. Na Figura.11 é mostrado como acontece o recebimento e o envio da palavra. Figura 11: HAL. 3.5 Hardware Quando há alteração no banco de dados, a aplicação envia o comando através de um conjunto de bits para os dispositivos. O comando passa pela interface serial RS-232 instalada no computador, porém a RS-232 possui diversas limitações prejudicando o desempenho da aplicação desenvolvida. Sua implementação é simples e de baixo custo, estando disponível na maioria dos computadores. Na Figura.12 é mostrada a comunicação RS 232 simples. É necessário utilizar um conversor RS-232 para RS-485 a fim de aumentar a distância de comunicação do sistema serial RS-232. Esse conversor permite a comunicação de equipamentos RS-232 com equipamentos RS 485, além de tudo ele faz o isolamento elétrico dos sistemas. A saída do conversor possui dois fios, onde são 37 Figura 12: Comunicação RS-232. montadas as interfaces seriais RS-485 fazendo uma rede de comunicação entre elas. O RS-485 foi escolhido para esta aplicação, pois a mesma tem o enfoque principal na comunicação em rede, onde com apenas uma par de fios é possível se comunicar com diversos equipamentos em rede usando o mesmo barramento. Outra característica é que, de maneira extremamente confiável, ela permite a comunicação em distâncias de até 1200 metros. A Figura.13 mostra a comunicação RS 232 e a rede de dispositivos RS 485. Figura 13: Comunicação RS-485. O protocolo RS 485 é do tipo half-duplex, onde há um dispositivo transmissor e outro dispositivo receptor, ambos podendo transmitir e receber dados não simultaneamente. Por exemplo, um dispositivo A pode transmitir dados e outro dispositivo B receber dados, ou vice e versa. Nas Figura.14 é visualizado o dispositivo AMP-12 usado nesse projeto. Na Figura.14 é visualizado o dispositivo AMP-12 aberto. Dentro, é encontrado o MAC (A), as portas de entrada e saída do dispositivo (B), o relé de acionamento (C), o drive do barramento RS-485 (D), o microcontrolador (E), entre outros. 38 Figura 14: Dispositivo AMP-12. 39 4 FINANCEIRO Para que o projeto seja utilizado em um ambiente, é necessário ao final do projeto acrescentar um custo para a instalação da aplicação. Pode-se citar como exemplo uma casa de 200 metros quadrados com três quartos, dois banheiros, uma cozinha e uma sala, onde a aplicação foi instalada em vinte e quatro pontos elétricos. A Tabela.5 mostra a distribuição de pontos elétricos dentro da casa. Cômodos Quarto 1 Quarto 2 Quarto 3 Banheiro 1 Banheiro 2 Sala Cozinha Lâmpada 3 3 2 1 1 5 4 Ar Condicionado 1 1 0 0 0 1 0 Ventilador 0 0 1 0 0 0 1 Tabela 5: DISTRIBUIÇÃO DOS PONTOS ELÉTRICOS. Os dispositivos AMP-12 são confeccionados pela empresa KRL e possuem o valor de R$ 250,00. Considerando que cada dispositivo habilita oito pontos elétricos, serão necessários três dispositivos para realizar a instalação, totalizando um valor de R$ 750,00. A Tabela.6 mostra a quantidade de material necessário para a instalação segura e com sucesso da aplicação na casa. Material Cabo Dispositivo Fonte Valor Unitário R$ 1,00 por metro R$ 250,00 R$ 120,00 Quantidade Necessária 650 metros 3 unidades 1 unidade Valor Total R$ 625,00 R$ 750,00 R$ 120,00 Tabela 6: CUSTO MATERIAL. Para uma casa de 200 metros quadrados serão necessários 625 metros de cabo. Levando em consideração que cada metro de cabo tem o custo de R$ 1,00, o valor 40 total do cabeamento será de R$ 625,00. Considera-se que em cada metro quadrado de um ambiente serão gastos 2,5 metros de cabo. Para a ligação dos dispositivos na rede elétrica da casa serão necessárias fontes de energia. O valor de cada fonte no mercado é de R$ 120,00. Levando em consideração que uma fonte alimenta 30 dispositivos e a casa em questão necessita de três dispositivos, então será utilizada uma fonte, totalizando um valor de R$ 120,00. A Tabela.7 mostra os custos com a mão-de-obra especializada que acrescentará valor no projeto final. Mão-de-obra Instalação física Modelagem 3D Adequação programa Valor R$ 500,00 R$ 900,00 R$ 900,00 Tabela 7: CUSTO MÃO-DE-OBRA. O projeto final terá um custo total de R$ 3.795,00. Tendo o ambiente citado como exemplo, uma casa de 200 metros quadrados com 24 pontos instalados, cada ponto terá um valor em média de R$ 158,00. Conclui-se então que o software desenvolvido é viável financeiramente. No mercado já existe esse tipo de aplicação, porém o custo para a aquisição e instalação ainda é muito alto. A ONID Limited é uma empresa do Reino Unido, que instala e cria sistemas inteligentes para residências. Cada casa inteligente é desenhada de acordo com o ambiente construído, dando ênfase a sistemas personalizados. Nossa aplicação é semelhante a ONID, porém ainda falta desenvolver algumas características, como por exemplo, segurança para que se transforme em um produto comercial. 41 5 CONCLUSÃO A partir do desenvolvimento do trabalho, conclui-se que é possível visualizar um projeto que possibilita ao usuário, através de seu computador pessoal (cliente), entrar numa aplicação que simula uma casa em 3D e, através dela, acionar cargas de sua casa real via da Internet. Tendo em vista a extensão deste projeto, foi preciso separá-lo em etapas: a primeira, consiste no desenvolvimento de uma interface 3D que controle o ambiente real, executada no computador servidor. Após essa etapa, foi desenvolvido um código que permitirá ao computador cliente, através da Internet, o controle desse ambiente. A etapa final será sobre o desenvolvimento de novos tipos de controles. A aplicação foi criada exatamente como proposta, onde o usuário, através de seu computador pessoal, possa interagir com a interface 3D, navegando no ambiente igual ao da sua casa. A partir de um click em um dos interruptores da casa, é enviado ao servidor uma palavra. O servidor fica rodando até que uma palavra seja enviando pelo cliente. Quando isso acontece, é feita uma comparação com a chave primária da tabela objeto do banco de dados. Feito a comparação, é alterado no banco o estado da carga e enviado automaticamente o comando para os dispositivos, acionando o motor elétrico. O projeto é viável tecnologicamente, tecnicamente e financeiramente, pois, hoje já existem tecnologias capazes de controlar cargas e conectar-se pela Internet. Os custos dos dispositivos e mão-de-obra para a construção do projeto não são abusivos, facilitando o acesso para pessoas das mais diversas classes sociais e renda. A implementação não é difícil, pois qualquer programador com conhecimentos em programação orientado a objetos e protocolo TCP / IP é capaz de modificar o projeto. O projeto pode se tornar viável comercialmente. Para isso, é necessário que o mesmo tenha algumas melhorias nos quesitos de segurança, tecnologias compatíveis e modificação do ambiente 3D. 42 6 TRABALHOS FUTUROS Após a conclusão do protótipo, serão necessárias algumas atualizações para tornálo mais acessível ao cliente quanto às questões de segurança. São elas referentes às senhas e logins; as opções de cenário e objetos pré-existentes que facilitarão a interação dos usuários; a criação de outros tipos de controle, já que os acionamentos provêm de bancos de dados; uma possível aplicação via bluetooth e o desenvolvimento de outras aplicações para que o cliente tenha mais diversidade de controle em sua residência. 43 ANEXO A -- Anexo A - Código desenvolvido do Cliente // Classe que cria o AMBIENTE #include <conio.h> #include "CAmbiente.h" #include "Serial.h" #include <process.h> #include <errno.h> #include <stdio.h> // Método construtor CAmbiente::CAmbiente() {} // Método destrutor CAmbiente::~CAmbiente() {} /* Método que chama as funções responsáveis pela criação do AMBIENTE. Nele é passado como parâmetro as opções selecionadas no MENU. */ int CAmbiente::run(video::E_DRIVER_TYPE driverType, bool fullscreen) { // Como ja dito anteriormente, este é o nó principal, é a partir dele que toda a cena será criada. IrrlichtDevice* dispositivo = createDevice(driverType, core::dimension2d<s32>(640, 480),16,fullscreen,false,false,this); 44 if (dispositivo == 0) return 1; // É necessário criar um nó responsável pelas funções que tratam a parte gráfica da aplicação, como texturas, cores, etc. video::IVideoDriver* driver = dispositivo->getVideoDriver(); // Agora temos que criar o gerenciador de cena, que vai gerencias todos os nós criados dentro da cena. cena = dispositivo->getSceneManager(); /* Estes três nós criados anteriormente é a estrutura básica para qualquer aplicação que utiliza a engine IrrLicht. Praticamente todos os programas terão que criar um dispositivo, um driver gráfico e um gerenciador de cena. A partir daí, fica por conta do programador. Neste caso, iremos carregar o ambiente criado no editor IrrEdit, usando o método LOADSCENE, pois é um arquivo de extensão .irr. No caso de carregar um outro ambiente de uma outra extensão, criado por outro editor, este método não suportará (com exceção .3DS), tendo que utilizar um outro método. Carregando a cena criada no irredit. */ cena->loadScene("../../media/example.irr"); /* A cena criada no editor IrrEdit, é composta por 2 nós. O ambiente propriamente dito (de nome MESH), e uma luz de baixa intensidade, que simula uma iluminação ambiente. Então devemos extrair o nó do ambiente para posteriormente ser aplciado a técnica de detectado a colisão apenas no ambiente. Isso é feito da seguinte forma: */ scene::ISceneNode* no = cena->getSceneNodeFromType(scene::ESNT_MESH,NULL); io::IAttributes* atributo = dispositivo->getFileSystem()->createEmptyAttributes(); no->serializeAttributes(atributo); core::stringc nome = atributo->getAttributeAsString("Mesh"); atributo->drop(); scene::IAnimatedMesh* mesh = cena->getMesh(nome.c_str()); 45 /* Agora, para fazer a detecção de colisão, devemos criar um seletor de triângulos para o ambiente. Quando criamos qualquer coisa dentro de uma cena como, por exemplo, uma parede, um teto, um carro, móveis, e etc, estes objetos não existem fisicamente dentro do mundo virtual, ou seja, todos eles podem ocupar o mesmo espaço, permitindo que um atravesse o outro, sem que haja colisão entre eles. Sendo assim, um seletor de triângulos irá dar um estado físico para um determinado objeto (nó), sendo que cada objeto pode ter seu própiro seletor de triângulos. Neste caso, iremos criar um seletor de triângulos para o ambiente, para que possa ser feito a detecção de colisão nas paredes, no piso e no teto. */ scene::ITriangleSelector* seletor = 0; if (no){ seletor = cena->createTriangleSelector(mesh->getMesh(0),no); no->setTriangleSelector(seletor); seletor->drop();} /* Agora que a cena já está fisicamente criada, temos que criar uma câmera para visualizar e navegar dentro dela. A câmera que iremos adicionar dentro da cena é controlada pelas teclas de direcionamento e pelo mouse. */ scene::ICameraSceneNode* camera = cena->addCameraSceneNodeFPS(0, 70.0f, 40.0f, -1, 0, 0, true); camera->setPosition(core::vector3df(-5,23,-50)); /* Para que a colisão entre 2 objetos (nós) seja detectada, devemos criar um animador de desenhos, pois é ele que irá responder se houve ou não a colisão. Depois devemos ligá-lo neste caso, é a câmera. ao nó em que desejamos que a colisão seja feita, que */ scene::ISceneNodeAnimator* animador = cena->createCollisionResponseAnimator(seletor,camera,core::vector3df(10,10,10), core::vector3df(0,-0.1,0),core::vector3df(0,30,0)); camera->addAnimator(animador); animador->drop(); /* Nos próximos bolocos iremos criar alguns objetos que participarão do 46 acionamento de dispositivos como, por exemplo, lâmpadas. E outros para dar um pouco de vida ao ambiente. Em primeiro passo, iremos criar uma lâmpada e colocá-la no centro do teto do ambiente. Esta lâmpada terá dois estados: apagada e acesa, que serão definitos através de texturas. */ lampada = cena->addCubeSceneNode(15.0f,0,-1,core::vector3df(0,0,0),core::vector3df(0,0,0), core::vector3df(1.5f,0.1f,1.5f)); lampada->setPosition(core::vector3df(-10,58,10)); lampada->setMaterialFlag(video::EMF_LIGHTING,false); lampada->setMaterialTexture(0,driver->getTexture("../../media/luz_apagada.jpg")); // Carregando as texturas da lampada acesa1 = driver->getTexture("../../media/luz_acesa.jpg"); apagada1 = driver->getTexture("../../media/luz_apagada.jpg"); // Agora vamos criar um interruptor para esta lâmpada e posicioná-lo na parade. interruptor1 = cena->addCubeSceneNode(5.0f,0,-1,core::vector3df(0,0,0), core::vector3df(-4,60,0),core::vector3df(0.6f,1.0f,0.0f)); interruptor1->setPosition(core::vector3df(44,20,56)); interruptor1->setMaterialFlag(video::EMF_LIGHTING,false); interruptor1->setMaterialTexture(0,driver->getTexture("../../media/inter.bmp")); interruptor1->setID(1); int id = interruptor1->getID(); v1 = interruptor1->getPosition(); i1x=v1.X; i1y=v1.Y; i1z=v1.Z; // Para simular o acionamento virtual da lâmpada, temos que criar uma fonte de luz para representá-la luz_central = cena->addLightSceneNode(0, core::vector3df(-10,45,10),video::SColorf(1.0f,1.0f,1.0f,1.0f),3.5f); luz_central->setVisible(false); 47 /* Vamos criar uma outra lâmapda para o ambiente, que será do tipo arandela, posicinada na parede. Esta arandela também terá 2 estados: apadada e acesa, que também serão definidos através de texturas. */ arandela = cena->addCubeSceneNode(13.0f,0,-1,core::vector3df(0,0,0), core::vector3df(0,7,0),core::vector3df(0.7f,0.7f,0.7f)); arandela->setPosition(core::vector3df(-55,38,-35)); arandela->setMaterialFlag(video::EMF_LIGHTING,false); arandela->setMaterialTexture(0,driver-> getTexture("../../media/arandela_apagada.jpg")); // carregando as texturas da arandela acesa2 = driver->getTexture("../../media/arandela_acesa.jpg"); apagada2 = driver->getTexture("../../media/arandela_apagada.jpg"); // Agora temos que criar um outro interruptor para a arandela. interruptor2 = cena->addCubeSceneNode(5.0f,0,-1,core::vector3df(0,0,0), core::vector3df(-4,60,0),core::vector3df(0.6f,1.0f,0.0f)); interruptor2->setPosition(core::vector3df(48,20,50)); interruptor2->setMaterialFlag(video::EMF_LIGHTING,false); interruptor2->setMaterialTexture(0,driver->getTexture("../../media/inter.bmp")); interruptor2->setID(2); int id2 = interruptor2->getID(); v3 = interruptor2->getPosition(); i2x=v3.X; i2y=v3.Y; i2z=v3.Z; // Da mesma forma da lâmapda central, vamos criar uma fone de luz para a arandela luz_parede = cena->addLightSceneNode(0, core::vector3df(-35,55,-35),video::SColorf(1.0f,1.0f,1.0f,1.0f),2.5f); luz_parede->setVisible(false); /* Para simular mais ainda um ambiente real, vamos criar algumas objetos como janela, porta quadros, entre outros. Esses objetos serão representados 48 através de texturas. criando uma janela. */ scene::ISceneNode* janela = cena->addCubeSceneNode(15.0f,0,-1,core::vector3df(0,0,0),core:: vector3df(-5.9,5,1),core::vector3df(3.0f,3.0f,0.3f)); janela->setPosition(core::vector3df(0,38,63.5)); janela->setMaterialFlag(video::EMF_LIGHTING,false); janela->setMaterialTexture(0,driver->getTexture("../../media/janela3.jpg")); // Criando um quadro scene::ISceneNode* quadro = cena->addCubeSceneNode(15.0f,0,-1,core::vector3df(0,0,0), core::vector3df(9,0.5,0),core::vector3df(3.0f,3.0f,0.3f)); quadro->setPosition(core::vector3df(0,35,-66.5)); quadro->setMaterialFlag(video::EMF_LIGHTING,false); quadro->setMaterialTexture(0,driver->getTexture("../../media/mona.jpg")); // Criando uma porta scene::ISceneNode* porta = cena->addCubeSceneNode(15.0f,0,-1,core::vector3df(0,0,0), core::vector3df(-3,57,0),core::vector3df(2.5f,5.0f,0.3f)); porta->setPosition(core::vector3df(65,20,25)); porta->setMaterialFlag(video::EMF_LIGHTING,false); porta->setMaterialTexture(0,driver->getTexture("../../media/portamadeira.jpg")); /* Para identificarmos o alvo da câmera, iremos criar um billboard. Um billboard é um ponto luminoso, geralmente usado para explosões, fogos, e coisas do tipo. Neste caso, o billboard seguirá o cursor do mouse. Isso é necessário pois o usuário precisa saber aonde estará clicando com o mouse para poder fazer o acionamento das lampadas através dos interruptores. */ bill = cena->addBillboardSceneNode(); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0,driver->getTexture("../../media/particle.bmp")); bill->setMaterialFlag(video::EMF_LIGHTING,false); bill->setMaterialFlag(video::EMF_ZBUFFER,false); 49 bill->setSize(core::dimension2d<f32>(10.0f,10.0f)); video::SMaterial material; // Função utilizada para esconder a seta do mouse dispositivo->getCursorControl()->setVisible(false); // Inteiro para contar os frames por segundo da aplicação. int lastFPS = -1; /* Pronto, o MENU está criado. Agora o que devemos fazer é colcoar o dispositivo para funcionar, chamando o método RUN. Este método vai colocar o dispositivo em loop infinito até que o usuário termine a aplicação fechando a janela ou pressionando ALT+F4. */ while(dispositivo->run()) // Esta função é opcional, mas sem ela, o dispositivo não garante que o cursor do mouse // seja iniciado no centro da janela. if (dispositivo->isWindowActive()){ driver->beginScene(true, true, video::SColor(0,200,200,200)); // Para desenhar realmente o AMBIENTE na tela, temos que extrair todos os métodos e funções // utilizados para este propósito. Para isso, utilizamos a função DRAWALL. cena->drawAll(); /* Este bloco trata da posição do billboard para que este siga o alvo da câmera em tempo Em primeiro passo, temos que criar um linha que inicia na posição da câmera e vai até seu alvo. */ core::line3d<f32> linha; linha.start = camera->getPosition(); linha.end = linha.start + (camera->getTarget() linha.start).normalize()*1000.0f; 50 // Agora vamos criar um vetor que indicará o ponto de interseção entre o alvo da câmera // e o objeto em que ela está olhando. core::vector3df intersecao; core::triangle3df triangulo; // Para obter esse ponto de interseção, nós precisamos do ponto de colisão entre o alvo // e o objeto que está sendo observado. Para isto usamos o seguinte bloco: if (cena->getSceneCollisionManager()->getCollisionPoint (linha,seletor,intersecao,triangulo));{ bill->setPosition(intersecao); driver->setTransform(video::ETS_WORLD,core::matrix4()); driver->setMaterial(material); //driver->draw3DTriangle(triangulo,video::SColor(255,255,255,255)); } driver->endScene(); int fps = driver->getFPS(); // Para saber quantos frames por segundo o programa está sendo rodado e exibí-lo no // título da janela, nós utilizamos o seguinte bloco: if (lastFPS != fps) { core::stringw str = L"Frederico,Erica e Alessandro e sua Casa 3D["; str += driver->getName(); str += "] FPS:"; str += fps; dispositivo->setWindowCaption(str.c_str()); lastFPS = fps; 51 } } // Função usada para descarregar todos os nós depois que a aplicação é terminada. dispositivo->drop(); return 0; } /* Este é método utilizado para fazer o acionanemto dos dispositivos. Este método captura clique do mouse. Se o usuário clicar com o botão esquerdo em cima de um interruptor, uma lâmpada se acenderá. Se o usuário clicar com o botão direito em cima de um interruptor, essa lâmpada se apagará. */ bool CAmbiente::OnEvent(SEvent evento) { int chamada; if (evento.EventType == irr::EET_MOUSE_INPUT_EVENT) { v2 = bill->getPosition(); bx=v2.X; by=v2.Y; bz=v2.Z; switch (evento.MouseInput.Event) { case irr::EMIE_LMOUSE_LEFT_UP: // botao esquerdo é apertado if(x != 1){ if((bx>=43 && bx<=45)&&(by>=19 && by<=21)&&(bz>=55 && bz<=57)){ lampada->setMaterialTexture(0,acesa1); printf("\n\nLampada acesa!"); 52 luz_central->setVisible(true); cliente c; c.run("LMP2"); c.~cliente(); x=1;y=2;} } if(w != 1){ if((bx>=47 && bx<=49)&&(by>=19 && by<=21)&&(bz>=49 && bz<=51)){ arandela->setMaterialTexture(0,acesa2); printf("\n\nArandela acesa!"); luz_parede->setVisible(true); cliente c; c.run("LMP0"); c.~cliente(); w=1;z=2;} } break; case irr::EMIE_RMOUSE_LEFT_UP: // botao direito é apertado if(y != 1){ if((bx>=43 && bx<=45)&&(by>=19 && by<=21)&&(bz>=55 && bz<=57)){ lampada->setMaterialTexture(0,apagada1); printf("\n\nLampada apagada!"); luz_central->setVisible(false); cliente c; 53 c.run("LMP1"); c.~cliente(); y=1;x=2;} } if(z != 1){ if((bx>=47 && bx<=49)&&(by>=19 && by<=21)&&(bz>=49 && bz<=51)){ arandela->setMaterialTexture(0,apagada2); printf("\n\nArandela apagada!"); luz_parede->setVisible(false); cliente c; c.run("LMP3"); c.~cliente(); z=1;w=2;} } break; default: return false; } printf("\r\nx= %d",bx);printf(" y= %d",by);printf(" z= %d",bz); } return false; } // Bloco de declarações das variáveis, funções e métodos da classe que cria o AMBIENTE #include <irrlicht.h> using namespace irr; class CAmbiente : public IEventReceiver { public: 54 CAmbiente(); ~CAmbiente(); virtual bool OnEvent(SEvent evento); int run(video::E_DRIVER_TYPE DriverType, bool fullscreen); // nós que participam do evento de acionamento das lampadas scene::ISceneNode* lampada; scene::ISceneNode* arandela; scene::ISceneNode* interruptor1; scene::ISceneNode* interruptor2; scene::IBillboardSceneNode* bill; scene::ISceneNode* luz_central; scene::ISceneNode* luz_parede; // vetores e coordenadas da posicao do billboard e dos interruptores core::vector3df v1,v2,v3; int i1x,i1y,i1z,i2x,i2y,i2z,bx,by,bz,x,y,w,z; // nós que vao ser carregados com as texturas da luz acesa ou apagada video::ITexture* acesa1; video::ITexture* apagada1; video::ITexture* acesa2; video::ITexture* apagada2; scene::ISceneManager* cena; }; // Classe que cria o MENU #include "CMainMenu.h" CMainMenu::CMainMenu() : startButton(0), device(0), start(false), fullscreen(false), selected(0), com1(true), transparent(true), com2(true) { } 55 /* Método que chama as funções responsáveis pela criação do MENU. Nele é passado como parâmetro as variáveis declaradas no bloco principal.*/ bool CMainMenu::run(bool& outFullscreen, bool& outCom1, bool& outCom2,video::E_DRIVER_TYPE& outDriver) { // Primeiramente, é necessário criar um dispositivo principal para a aplicação. // É a partir deste nó que tudo é criado. device = createDevice( video::EDT_BURNINGSVIDEO,core::dimension2d<s32>(512, 384), 16, false, false, false, this); // Agora deve ser criado um objeto responsável pelas funções que tratam a parte gráfica da aplicação. video::IVideoDriver* driver = device->getVideoDriver(); // Depois é necessário criar um objeto para gerenciar todos os nós adicionados na cena. scene::ISceneManager* smgr = device->getSceneManager(); // Como nesta classe será criado um MENU, é necessário criar um objeto // que forneça uma relação gráfica para os usuários. gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); // Neste bloco, é setado o título da janela do programa. Junto ao título, será exibido a versão // da engine utilizada. core::stringw str = "Irrlicht Engine"; str += device->getVersion(); device->setWindowCaption(str.c_str()); // Para a criaçã do MENU, será utilizado um elemento semelhante à uma película transparente, // dando uma estética mais agradável para o MENU. Esse elemento é chamado de Skin. 56 gui::IGUISkin* newskin = guienv->createSkin( gui::EGST_BURNING_SKIN); guienv->setSkin(newskin); newskin->drop(); // Agora, será mudado a fonte dos textos inscritos no MENU. Deve-se ter um arquivo contendo // a fonte desejada. Depois é só indicá-lo pelo nome. gui::IGUIFont* font = guienv->getFont("../../media/fonthaettenschweiler.bmp"); if (font) guienv->getSkin()->setFont(font); const s32 leftX = 260; /* O MENU será composto por 2 guias: uma fornecendo algumas opções da aplicação para o usuário, e a outra que irá exibir um texto sobre o este projeto. Dessa forma, é necessário criar um controlador de guias. */ gui::IGUITabControl* tabctrl = guienv->addTabControl(core::rect<int>(leftX,10,512-10,384-10),0, true, true); // Guia que fornece opções para o usuário. Essas opções são: tipo de renderizador gráfico, opção // de fullscreen e porta de comunicação. gui::IGUITab* optTab = tabctrl->addTab(L"Menu"); // Guia que exibe um texto sobreo projeto. gui::IGUITab* aboutTab = tabctrl->addTab(L"Sobre"); // A Engine IrrLicht disponibiliza alguns renderizadores gráficos. Esses renderizadores são // listados no MENU para que atenda aos diferenes usuários de acordo com suas preferências. gui::IGUIListBox* box = guienv->addListBox(core::rect<int>(10,10,220,120), optTab, 1); box->addItem(L"OpenGL 1.5"); box->addItem(L"Direct3D 8.1"); 57 box->addItem(L"Direct3D 9.0c"); box->addItem(L"Burning's Video 0.38"); box->addItem(L"Irrlicht Software Renderer 1.0"); box->setSelected(selected); // Agora vamos dar algumas outras opções ao usuário. const s32 d = 50; // opção de fullscreen guienv->addCheckBox(fullscreen, core::rect<int>(20,85+d,130,110+d), optTab, 3, L"Fullscreen"); // porta de comunicação serial COM1 guienv->addCheckBox(com1, core::rect<int>(20,160+d,230,185+d), optTab, 6, L"IP: 192.168.0.90"); // porta de comunicação serial COM2 guienv->addCheckBox(com2, core::rect<int>(20,185+d,230,210+d), optTab, 7, L"PORTA: 8000"); // Depois que o usuário esquelheu suas opções desejadas, agora ele pode iniciar a interação // com o ambiente pressionado o botão "START", que é criado da seguinte maneira: startButton = guienv->addButton(core::rect<int>(30,295,200,324), optTab, 2, L"Start"); // Até agora foram criados os itens da primeira guia (guia "MENU"). Agora vamos criar um texto falando // sobreo projeto e colocá-lo na segunda guia (guia "SOBRE"). wchar_t* text2 = L"Para comecar, selecione um dispositivo que funcione melhor"\ L"com seu hardware e pressione 'start'. "\ L"Trata-se de um programa em que o usuario navega pelo ambiente e, ao clicar sobre "\ L"os interruptores instalados, lampadas referente a estes, serao acionados, "\ 58 L"no modo em que o usuario pode controlar os dispositivos reais atraves do ambiente virtual via web. "\ L"Este programa foi desenvolvido pelos alunos do curso de Ciencia da Computacao: "\ L"Frederico da Silva, Erica Roque, Alessandro Goncalves, orientado pelo Professor "\ L"Marcelo Camponez. Para mais informacoes, por favor entre em contato: [email protected]"; guienv->addStaticText(text2, core::rect<int>(10, 10, 230, 320),true, true, aboutTab); #if 1 #endif // Para deixar a tela de apresentação mais agradável, vamos colocar a logomarca da engine // IrrLicht e uma imagem do ambiente de fundo. bool oldMipMapState = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); guienv->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), core::position2d<s32>(5,5)); // criando a imagem de fundo. video::ITexture* irrlichtBack = driver->getTexture("../../media/imagem_menu.bmp"); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); // Estas funções são usadas para dar um detalhamento na estética do MENU. // Função que extrai a cor original do Skin. getOriginalSkinColor (); // Função que seta transparência no MENU. setTransparency(); 59 /* Pronto, o MENU está criado. Agora o que devemos fazer é colcoar o dispositivo para funcionar, chamando o método RUN. Este método vai colocar o dispositivo em loop infinito até que o usuário termine a aplicação fechando a janela ou pressionando ALT+F4. */ while(device->run()) { // Esta função é opcional, mas sem ela, o dispositivo não garante que o cursor do mouse // seja iniciado no centro da janela. if (device->isWindowActive()) { driver->beginScene(false, true, video::SColor(0,0,0,0)); if ( irrlichtBack ) driver->draw2DImage(irrlichtBack,core::position2d<int>(0,0)); // Para desenhar realmente o MENU na tela, temos que extrair todos os métodos e funções // utilizados para este propósito. Para isso, utilizamos a função DRAWALL. smgr->drawAll(); guienv->drawAll(); driver->endScene(); } } device->drop(); outFullscreen = fullscreen; outCom1 = com1; // Neste bloco é selecionado o renderizador escolhido pelo usuário. switch(selected) { case 0: outDriver = video::EDT_OPENGL; break; 60 case 1: outDriver = video::EDT_DIRECT3D8; break; case 2: outDriver = video::EDT_DIRECT3D9; break; case 3: outDriver = video::EDT_BURNINGSVIDEO; break; case 4: outDriver = video::EDT_SOFTWARE; break; } return start; } /* O método ONEVENT geralmente é usado para tratar eventos vindos do clique do mouse ou quando teclas do teclado são pressionadas. Neste caso, usaremos este método para tratar os ítens selecionados no MENU.*/ bool CMainMenu::OnEvent(SEvent event) { if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == KEY_F9 && event.KeyInput.PressedDown == false) { video::IImage* image = device->getVideoDriver()->createScreenShot(); if (image) { device->getVideoDriver()->writeImageToFile(image, "screenshot_main.jpg"); image->drop(); } } else if (event.EventType == irr::EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP ) { core::rect<s32> r(event.MouseInput.X, event.MouseInput.Y, 0, 0); gui::IGUIContextMenu* menu = device->getGUIEnvironment()->addContextMenu(r, 0, 45); menu->addItem(L"transparent menus", 666, transparent == false); menu->addItem(L"solid menus", 666, transparent == true); menu->addSeparator(); 61 menu->addItem(L"Cancel"); } else if (event.EventType == EET_GUI_EVENT) { s32 id = event.GUIEvent.Caller->getID(); switch(id) { case 45: if (event.GUIEvent.EventType == gui::EGET_MENU_ITEM_SELECTED) { s32 s = ((gui::IGUIContextMenu*)event.GUIEvent.Caller)->getSelectedItem(); if (s == 0 || s == 1) { transparent = !transparent; setTransparency(); } } break; case 1: if (event.GUIEvent.EventType == gui::EGET_LISTBOX_CHANGED || event.GUIEvent.EventType == gui::EGET_LISTBOX_SELECTED_AGAIN) { selected = ((gui::IGUIListBox*)event.GUIEvent.Caller)->getSelected(); //startButton->setEnabled(selected != 4); startButton->setEnabled( true ); } break; case 2: if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { device->closeDevice(); start = true; 62 } case 3: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) fullscreen = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); break; case 6: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) com1 = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); strcpy (pt,"com1"); break; case 7: //if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) // com2 = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); //strcpy (pt,"com2"); break; } } return false; } void CMainMenu::getOriginalSkinColor() { irr::gui::IGUISkin * skin = device->getGUIEnvironment()->getSkin(); for (s32 i=0; i<gui::EGDC_COUNT ; ++i) { SkinColor [ i ] = skin->getColor ( (gui::EGUI_DEFAULT_COLOR)i ); } } void CMainMenu::setTransparency() { irr::gui::IGUISkin * skin = device->getGUIEnvironment()->getSkin(); u32 i; for ( i=0; i<gui::EGDC_COUNT ; ++i) 63 { video::SColor col = SkinColor [ i ]; if ( false == transparent ) col.setAlpha( 255); skin->setColor((gui::EGUI_DEFAULT_COLOR)i, col); } } // Bloco de declarações das variáveis, funções e métodos da classe que cria o MENU #ifndef __C_MAIN_MENU_H_INCLUDED__ #define __C_MAIN_MENU_H_INCLUDED__ #include <irrlicht.h> using namespace irr; class CMainMenu : public IEventReceiver { public: CMainMenu(); bool run(bool& outFullscreen,bool& outCom1,bool& outCom2,video::E_DRIVER_TYPE& outDriver); virtual bool OnEvent(SEvent event); private: void setTransparency(); gui::IGUIButton* startButton; IrrlichtDevice *device; s32 selected; bool start; bool fullscreen; 64 bool com1; bool transparent; bool com2; char pt[5]; scene::IAnimatedMesh* quakeLevel; scene::ISceneNode* lightMapNode; scene::ISceneNode* dynamicNode; video::SColor SkinColor [ gui::EGDC_COUNT ]; void getOriginalSkinColor(); }; #endif // Classe que faz a comunicação serial através do envio de um caracter. #include "serial.h" #include <cstdlib> #include <iostream> #include<windows.h> #include<stdio.h> #include<string> using namespace std; // Primeiramente, temos que ter um identificador para a porta serial. Este identificador é do tipo // HANDLE. HANDLE hCom; // Agora nós precisamos de uma estrutra pra definir todos os parametros da comunicação. Essa // estrutura é do tipo DCB. DCB dcb; // Para controlar o tempo de leitura e escrita na porta serial, é necessário criar um timeout. 65 COMMTIMEOUTS CommTimeouts; // Método construtor da classe serial cliente::cliente(){} // Depois que tudo está configurado, a palavra pode ser enviado para o servidor. Para isto, utilizamos este // método. bool cliente::enviaCaracter(char *c){ // criar um socket SOCKET ServidorSocket; //struct que contém as configurações do socket: porta, host e famàlia struct sockaddr_in ServidorAddr; //variível auxiliar para inicializar o winsock WSADATA wsad; //utilizada para inicializar o winsock WSAStartup( MAKEWORD(2,2),&wsad); //criar um socket ServidorSocket = socket( AF_INET, SOCK_STREAM,0); //Configura socket ServidorAddr.sin_family = AF_INET; //transformar uma porta em network byte ServidorAddr.sin_port = htons(8000); //transformar um IP de string (xxx.xxx.xxx.xxx) para valor numérico ServidorAddr.sin_addr.s_addr = inet_addr("192.168.0.90"); //conectar-se a um host 66 connect(ServidorSocket,(struct sockaddr *)&ServidorAddr,sizeof(ServidorAddr)); //enviar dados para uma conexão ativa send(ServidorSocket,c,255,0); //fechar socket closesocket(ServidorSocket); //finalizar winsock WSACleanup(); } // Este é método principal da classe. É através dele que todos os outros métodos desta classe são // chamados. bool cliente::run(char *s){ enviaCaracter(s); } cliente::~cliente() { } // Bloco de declarações das variáveis, funções e métodos da classe que faz a comunicação cliente servidor. #pragma once class cliente { public: cliente(); bool enviaCaracter(char *c); 67 bool run(char *s); ~cliente(); }; 68 ANEXO B -- Anexo B - Código desenvolvido do Servidor // Classe que faz a comunicação serial através do envio de um caracter. #include "Serial.h" #include <cstdlib> #include <iostream> #include<windows.h> #include<stdio.h> #include<string> using namespace std; // Primeiramente, temos que ter um identificador para a porta serial. Este identificador é do tipo // HANDLE. HANDLE hCom; // Agora nós precisamos de uma estrutra pra definir todos os parametros da comunicação. Essa // estrutura é do tipo DCB. DCB dcb; // Para controlar o tempo de leitura e escrita na porta serial, é necessário criar um timeout. COMMTIMEOUTS CommTimeouts; // Méodo construtor da classe serial serial::serial(){} 69 // Este método é rsponsável pela abertura da porta serial, na qual serão enviados os caracteres // para as placas de acionamento. bool serial::abrirSerial(char *porta){ hCom = CreateFile(porta,GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); // condição de invalidade do handle if (hCom == INVALID_HANDLE_VALUE) { printf("erro"); return false; } printf("\r\n\nPorta serial: ok"); return true; } // Depois que a porta serial foi aberta, temos que configurá-la. bool serial::configuraPorta(){ // condição de de erro na leitura da dcb if( !GetCommState(hCom, &dcb)){ printf("\r\nProblemas na abertura da DCB!"); return false; } printf("\r\nAbertura da DCB: ok"); dcb.BaudRate = CBR_1200; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; // define novo estado if( SetCommState(hCom, &dcb) == 0 ){ printf("\r\nProblemas na configuracao da serial"); return false; } printf("\r\nConfiguracao da serial: ok"); return true; } 70 // Os timeouts são configurados de acordo com as necessidades da aplicação. bool serial::configuraTimeouts(){ // condição de erro nos timeouts if( GetCommTimeouts(hCom, &CommTimeouts) == 0 ){ printf("\r\nProblemas nos timeouts!"); return false; } CommTimeouts.ReadIntervalTimeout = 0; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.WriteTotalTimeoutMultiplier = 0; CommTimeouts.WriteTotalTimeoutConstant = 0; if( SetCommTimeouts(hCom, &CommTimeouts) == 0 ) return false; printf("\r\nTimeouts: ok"); return true; } // Depois que tudo está configurado, o carater pode ser transmitido. Para isto, utilizamos este // método. bool serial::enviaCaracter(char *c){ /* MYSQL conexao; mysql_init(&conexao); if ( mysql_real_connect(&conexao, "127.0.0.1", "root", "1234", "BANCO", 0, NULL, 0) ) { printf("conectado com sucesso!\n"); mysql_query(&conexao,"UPDATE estado set status = 'ligado' where posicao = c"); 71 mysql_close(&conexao); } else { printf("Falha de conexao\n"); printf("Erro %d : %s\n", mysql_errno(&conexao), mysql_error(&conexao)); }*/ DWORD BytesEscritos = 0; int TamaString; TamaString = strlen(c); if(!WriteFile( hCom, c, TamaString, &BytesEscritos, NULL )){ printf("\r\nProblemas ao escrever na serial!"); return false; } printf("\r\nCaracter enviado com sucesso!"); return true; } // Depois que o caracter foi enviado, devemos fechar a porta serial para dar acesso à outra // solicitação. void serial::fechaPorta(){ CloseHandle( hCom ); } // Este é método principal da classe. É através dele que todos os outros métodos desta classe são // chamados. bool serial::run(char *porta,char *s){ abrirSerial(porta); configuraPorta(); configuraTimeouts(); enviaCaracter(s); fechaPorta(); } 72 serial::~serial() { } #include "Serial.h" void Conexao(char Buffer[255]){ //declarando aonde deve ser feito a conexão MYSQL conexao; //iniciando a conexão mysql_init(&conexao); //depois de iniciada, enviado dados necessarios para entrar no MYSQL, e no banco necessario if ( mysql_real_connect(&conexao, "127.0.0.1", "root", "1234", "BANCO", 0, NULL, 0) ) { printf("\n \t conectado com sucesso!\n"); //Comparando a palavra para decidir aonde ela sera armazenada if(Buffer[3]=='2') //atualização na tabela, chamada da função de envio do caracter {mysql_query(&conexao,"update lampada set status = 'ligado' where status = 'desligado' and idLampada = 123;"); serial s; s.run("com1","FF"); s.run("com1","FF"); } if(Buffer[3]=='1') {mysql_query(&conexao,"update lampada set status = 'desligado' where status = 'ligado' and idLampada = 123;"); serial s; 73 s.run("com1","AA"); s.run("com1","AA"); }if(Buffer[3]=='0') {mysql_query(&conexao,"update lampada set status = 'ligado' where status = 'desligado' and idLampada = 124;"); serial s; s.run("com1","FF"); s.run("com1","FF"); }if(Buffer[3]=='3') {mysql_query(&conexao,"update lampada set status = 'desligado' where status = 'ligado' and idLampada = 124;"); serial s; s.run("com1","AA"); s.run("com1","AA"); } //fechando conexão com o banco mysql_close(&conexao); } else { printf("Falha de conexao\n"); printf("Erro %d : %s\n", //mostrando qual o erro com a conexão com o banco de dados mysql_errno(&conexao), mysql_error(&conexao)); } } // Bloco de declarações das variáveis, funções e métodos da classe que faz a comunicação serial. #pragma once class serial { 74 public: serial(); bool abrirSerial(char *p); bool configuraPorta(); bool configuraTimeouts(); bool enviaCaracter(char *c); bool recebeCaracter(); bool run(char *porta,char *s); void fechaPorta(); ~serial(); };