PONTIFÍCIA UNIVERSIDADE CATÓLICA DO PARANÁ ESCOLA POLITÉCNICA CURSO DE ENGENHARIA DE COMPUTAÇÃO CHRISTIAN ARROSI CHRISTIAN KITZMANN GOMES TITAN HIGHWAYS CURITIBA 2012 CHRISTIAN ARROSI CHRISTIAN KITZMANN GOMES TITAN HIGHWAYS Relatório apresentado ao curso de Engenharia de Computação, da Pontifícia Universidade Católica do Paraná, como requisito parcial de avaliação, da disciplina de Resolução de Problemas da Engenharia. Prof. Afonso Ferreira Miguel CURITIBA 2012 SUMÁRIO RESUMO ........................................................................................................................................ 5 GLOSSÁRIO DE SIGLAS ................................................................................................................... 6 GLOSSÁRIO DE PALAVRAS ............................................................................................................. 7 INDICE DE IMAGENS ...................................................................................................................... 8 METODOLOGIA............................................................................................................................ 11 OBJETIVOS ................................................................................................................................... 12 GERAL ...................................................................................................................................... 12 ESPECÍFICOS ............................................................................................................................ 12 MATERIAIS UTILIZADOS............................................................................................................... 12 EQUIPAMENTOS UTILIZADOS...................................................................................................... 13 SOFTWARES UTILIZADOS ............................................................................................................ 13 PROBLEMA APRESENTADOS ....................................................................................................... 13 INTERFACE ................................................................................................................................... 14 PROCESSADOR DE PACOTES ....................................................................................................... 15 BANCO DE DADOS ....................................................................................................................... 16 CÓDIGO INICIAL ....................................................................................................................... 17 CÓDIGO DE CONEXÃO DO BANCO DE DADOS .................................................................... 17 CÓDIGO DA CLASSE SENSORES ........................................................................................... 19 CÓDIGO DA CLASSE PRINCIPAL ........................................................................................... 20 MAQUETE .................................................................................................................................... 21 INTEGRAÇÃO ............................................................................................................................... 21 PLACA DE CIRCUITOS................................................................................................................... 21 CÓDIGO FINAL DO PROJETO ....................................................................................................... 22 INTEGRAÇÃO DOS CÓDIGOS ................................................................................................... 22 jFInterface ........................................................................................................................... 22 MainClass ............................................................................................................................ 25 BytesArray ........................................................................................................................... 25 ProcessadorPacotes ............................................................................................................ 26 Sensor .................................................................................................................................. 26 Connection .......................................................................................................................... 27 OpcodeHandlerlor. .............................................................................................................. 28 MANUAL DO USUÁRIO ................................................................................................................ 30 HISTÓRICO DE DESENVOLVIMENTO............................................................................................ 31 RESUMO O desenvolvimento do mesmo visa melhorar a segurança dos usuários de autoestradas, controlando a iluminação e integrado ao mesmo, um sistema integrado de segurança inteligente. O projeto visa integrar dois módulos distintos criando algo inovador, trazendo assim mais tecnologia para a vida diária das pessoas. Separando as autoestradas em várias partes é possível monitorar a quantidade de veículos transitando em cada trecho da estrada, integrado com um sistema de iluminação que atuará nas faixas e nas placas de transito presentes na estrada. Adicionalmente os olhos-de-gato serão substituídos por pequenas lanternas. O sistema de iluminação será ativado durante a noite e quando existirem veículos transitando no trecho da estrada em questão. Um sistema de segurança utilizará as informações como quantidade de veículos em um trecho da estrada para determinar possíveis acidentes, ao suspeitar de um acidente a informação será enviada a uma central, possibilitando que ações sejam tomadas imediatamente. Palavras-chave: Desenvolvimento, Iluminação, Segurança. GLOSSÁRIO DE SIGLAS HTTP Hypertext Transfer Protocol MDF Medium Density Filterboard NC NO PCI TCP Normally Closed Normally Open Transmission Control Protocol Protocolo de Transferência de Hipertexto Placa de fibra de madeira de média densidade Normalmente fechado Normalmente aberto Placa de Circuito Impresso Protocolo de controle de transmissão GLOSSÁRIO DE PALAVRAS Arduíno Byte Header MySQL Set Software Table Micro controlador programável Octeto binário na computação Cabeçalho de um pacote Software utilizado para banco de dados Alterar um conteúdo para o especificado Sequência de instruções para o computador Tabela INDICE DE IMAGENS Figura 1 - PCI do projeto Figura 2 - Demonstração dos trechos controlados e seus respectivos sensores. Figura 3 - Demonstração da conexão dos cabos Ethernet Figura 4 - Demonstração dos cabos da maquete, estes devem ser ligados ao Arduíno Figura 5 - Demonstração da ligação de todos os cabos do Arduíno, locais e suas respectivas ligações. METODOLOGIA Para o desenvolvimento do projeto foi aplicada a metodologia de separar um grande problema em várias partes, para a execução desse projeto foi utilizado o seguinte modelo de separação: Software: Módulo onde a comunicação e gerenciamento de informações fora desenvolvido; Elétrica: Projeto dos circuitos e seus testes; Maquete: Simulação de uma autoestrada de duas faixas com uma curva; Integração: Instalação dos LEDs, sensores, fiação e PCI na maquete. Após a separação cada etapa foi desenvolvida separadamente. Para o desenvolvimento do software foi feita novamente uma separação, a parte de comunicação, banco de dados, comunicação com o arduíno Desenvolvemos o projeto separando por setores, iniciando-se na parte de software, onde desenvolvemos toda a lógica e executamos os testes dos sistemas. Após concluir está etapa passamos a desenvolver a parte de hardware, onde criamos um placa de circuito impresso exclusivamente para o melhor funcionamento do sistema. Após executadas estas tarefas passamos a montar a maquete e a integrar todo o setor de software com o setor de hardware. O projeto foi desenvolvido na forma de uma maquete para o melhor entendimento do funcionamento. Cada parte foi projetada, desenvolvida e testada separadamente. Terminando a integração das partes do projeto, realizamos os testes finais do funcionamento do projeto. OBJETIVOS GERAL Com base nos programas de aprendizagem das disciplinas do curso de engenharia da computação, construir um sistema inteligente de iluminação e emergências para rodovias. ESPECÍFICOS Confeccionar um sistema de iluminação inovador para estradas. Integrar o sistema de iluminação com um sistema de emergência. Criar algo inovador. CD do projeto com imagens, vídeos e documentação sobre o projeto. MATERIAIS UTILIZADOS Placa fenolite Compensado MDF ; resistor de resistores de resistores de receptores infravermelho- ; emissores infravermelho – ; ; LED’s auto brilho – ; de fiação; Cola Quente; Arduino Duemilanove c/ ATmega328; Ethernet Shield Arduino - Enc28j60; Tintas Spray – Preto, Branco, Verde; Estanho com fluxo de solda; 4 Reles NC – 5V; 4 Transistores NPN; EQUIPAMENTOS UTILIZADOS Furadeira; Broca de ; Ferro de Solda; Pistola de cola quente; Multímetro; Computador; SOFTWARES UTILIZADOS SolidWorks 2012 – Student Edition; Eagle 6.1; NetBeans IDE 7.1.1; Eclipse HELIOS; Microsoft Office 2010 - Project; Microsoft Office 2010 - Word; Microsoft Office 2010 - Excel; Microsoft Office 2010 - Visio ; MySQL Server 5.5; MySQL GUI Tools; Arduino 1.0; PROBLEMA APRESENTADOS PROBLEMAS ENCONTRADOS Interferência dos sensores infravermelho com os demais sensores. Ruído na entrada do arduino. Falta de Alimentação para o funcionamento dos sensores estabelecidos na maquete. Problema no código do banco de dados. Problemas no código do processador de pacotes. SOLUÇÕES Foi utilizado um pequeno tubo de madeira para direcionar o feixe do sensor. Foi necessário a utilização de resistores Pull-Down. Utilizou-se uma nova fonte de alimentação, utilizando um cabo USB ligado ao computador. Reestruturação do código. Reestruturação do código. INTERFACE A interface assim como todo código do projeto foi criada na linguagem Java, esta possui quatro campos distintos, nos quais exibiram as informações dos sensores e de seus trechos. Os campos recebem o nome de acordo com suas funções especificas sendo de: Console: Este recebe a função de imprimir as informações de conexão, possíveis erros de sistemas e avisos do programa; Estatísticas: Este campo recebe a função de mostrar as informações de um determinado trecho, imprimindo o valor da quantidade de carros no trecho. Sensores: Este campo demostra a instalação e desinstalação dos sensores na rodovia, mostrando também a localização do sensor no trecho em que foi instalado. Emergências: Este por sua vez mostra os avisos de possíveis acidentes, utilizando as estatísticas do local, emitindo assim para o operador o alerta. PROCESSADOR DE PACOTES O processador de pacotes é um módulo do projeto que foi criado para realizar determinar operações dependendo do conteúdo de um pacote recebido. Antes de o software iniciar o seu papel é inicialmente estabelecida uma conexão com o software responsável por adquirir as informações do servidor HTTP do Arduíno, uma vez conectado ele irá receber os pacotes TCP enviados a fim de interpretá-los. Para a interpretação dos pacotes o primeiro passo é verificador se o tamanho em bytes do pacote é consistente com os parâmetros esperados. Após isso é necessário ler o seu header que consiste em um único byte e verificar se o seu valor é consistente com os códigos operacionais do programa. O código operacional levará a uma das operações a seguir: Gravação de um novo sensor no banco de dados; Apagar um sensor do banco de dados; Incrementar o contador de um sensor em particular; Decrementar o contador de um sensor em particular; Set o valor de um sensor em particular. Uma vez interpretado o header do pacote a operação solicitada será executada se possível, verificando ao longo de sua execução se ocorreu algum erro, os possíveis erros tratados são: Número de bytes do pacote inconsistente com o esperado; Gravação de um sensor que já existe; Remoção de um sensor que não existe; Incrementar ou decrementar sensor que não existe; Decrementar sensores com nenhum veículo circulando; Set valor de um sensor que não existe. BANCO DE DADOS O banco de dados foi projetado para receber e armazenar as informações adquiridas a partir das estatísticas de tráfeg , a escolha de utilizar o MySQL foi devido a sua facilidade na manipulação dos dados. Inicialmente seu código foi projetado de forma separada, mas tarde sendo incorporado ao código final do projeto. O código foi criado na linguagem Java, possuindo um driver para executar a conexão com o MySQL, para iniciar a conexão é necessário ser definido o local, login e senha no código fonte. O banco possui uma table com cinco colunas, cada coluna deve armazenar um determinado valor correspondente ao seu campo. Os campos foram estabelecidos de acordo com seus nomes mantendo assim a organização dos dados armazenados, os valores serão guardados e separados nestes campos sendo eles de: Identificador: Este armazena o valor de identificação dos sensores, onde cada sensor terá um numero exclusivo, facilitando assim a identificação de possíveis erros; TotalCarrosOntem: Este armazena o valor das estatísticas de veículos que circularam num determinado trecho no dia anterior, este valor para demonstração será atualizado manualmente; TotalCarrosHoje: Este armazena o valor das estatísticas de veículos que circularam num determinado trecho no dia atual; MaiorQuantidadeDeCarros: Este armazena o valor das estatísticas de veículos que circularam no trecho no determinado período, sendo atualizado constantemente; LimiteTipico: Este armazena o valor das estatísticas da média de veículos no trecho, sendo emitido o estado de alerta quando ultrapassado. CÓDIGO INICIAL CÓDIGO DE CONEXÃO DO BANCO DE DADOS Este é uma das partes mais importantes para o banco de dados, já que este conecta o sistema com o MySQL, através do driver próprio para isso. Está parte do código fica responsável por pegar o usuário e a senha e testa-la para verificar se este tem autoridade para acessar o banco. Lembrando que este código é apenas demonstrativo, já que este é o código antigo do banco de dados. Este código também possui as funções de gravação dos sensores. public class ConectaBanco { private String url; private String login; private String senha; public ConectaBanco(String url, String login, String senha) { setUrl(url); setLogin(login); setSenha(senha); } public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getSenha() { return senha; } public void setSenha(String senha) { this.senha = senha; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public void insere(String s, String msg) { try { Class.forName("com.mysql.jdbc.Driver").newInstance(); //System.out.println("\n Salvando URL: ...\n"); try { Connection conn = DriverManager.getConnection(getUrl(),getLogin(), getSenha()); try { String sql = s; Statement stm = conn.createStatement(); try { stm.executeUpdate(sql); System.out.println(msg); } catch (Exception ex) { System.out.println("\nErro no resultset!\n" + ex); } } catch (Exception ex) { System.out.println("\nErro no statement!"); } } catch (Exception ex) { System.out.println("\nErro no connection!"); } } catch (Exception ex) { System.out.println("\nDriver nao pode ser carregado!"); } } public ArrayList busca(String s) { ArrayList Sensores = new ArrayList(); Sensores a = new Sensores(); try { Class.forName("com.mysql.jdbc.Driver").newInstance(); //System.out.println("\n Salvando URL: ...\n"); try { Connection conn = DriverManager.getConnection(getUrl(),getLogin(), getSenha()); try { String sql = s; Statement stm = conn.createStatement(); try { ResultSet rs = stm.executeQuery(sql); while (rs.next()) { a.setCod(rs.getInt(1)); a.setIdentificador(rs.getString(2)); a.setTotalCarrosOntem(rs.getString(3)); a.setTotalCarrosHoje(rs.getString(4)); a.setMaiorQuantidadeDeCarros(rs.getString(5)); a.setLimiteTipico(rs.getString(6)); Sensores.add(a); } System.out.println("Sensor Encontrado com Sucesso!!!\n"); System.out.println("Identificador: "+a.getIdentificador() +"\nTotalCarrosOntem: " + a.getTotalCarrosOntem()+ "\nTotalCarrosHoje: "+ a.getTotalCarrosHoje()+ "\nMaiorQuantidadeDeCarros: "+a.getMaiorQuantidadeDeCarros() + "\nLimiteTipico: "+a.getLimiteTipico() +"\n"); //System.out.println(rs.getInt(1)); } catch (Exception ex) { System.out.println(ex); } } catch (Exception ex) { System.out.println("\nErro no statement!"); } } catch (Exception ex) { System.out.println("\nErro no connection! " + ex); } } catch (Exception ex) { System.out.println("\nDriver nao pode ser carregado!"); } return Sensores; } } CÓDIGO DA CLASSE SENSORES public class Sensores { private int cod; private String Identificador; private String TotalCarrosOntem; private String TotalCarrosHoje; private String MaiorQuantidadeDeCarros; private String LimiteTipico; public int getCod() { return cod; } public void setCod(int cod) { this.cod = cod; } public String getIdentificador(){ return Identificador; } public void setIdentificador(String Identificador) { this.Identificador = Identificador; } public String getTotalCarrosOntem() { return TotalCarrosOntem; } public void setTotalCarrosOntem(String TotalCarrosOntem) { this.TotalCarrosOntem = TotalCarrosOntem; } public String getTotalCarrosHoje() { return TotalCarrosHoje; } public void setTotalCarrosHoje(String TotalCarrosHoje) { this.TotalCarrosHoje = TotalCarrosHoje; } public String getMaiorQuantidadeDeCarros() { return MaiorQuantidadeDeCarros; } public void setMaiorQuantidadeDeCarros(String MaiorQuantidadeDeCarros) { this.MaiorQuantidadeDeCarros = MaiorQuantidadeDeCarros; } public String getLimiteTipico() { return LimiteTipico; } public void setLimiteTipico(String LimiteTipico) { this.LimiteTipico = LimiteTipico; } } CÓDIGO DA CLASSE PRINCIPAL public class MainClass { private static String private static String private static String private static String MaiorQuantidadeDeCarros; LimiteTipico; TotalCarrosHoje; TotalCarrosOntem; public static void main(String[] args) { Scanner ler = new Scanner(System.in); ConectaBanco cb = new ConectaBanco("jdbc:mysql://URL", "LOGIN", "SENHA"); int x=-1; while (x != 0) { System.out.println("Escolha uma opcao"); System.out.println("1 - Cadastrar novo Sensor"); System.out.println("2 - Buscar Sensor cadastrado"); System.out.println("3 - Sair"); x = Integer.parseInt(ler.nextLine()); switch (x) { case 1: { Sensores sensor = new Sensores(); System.out.println("Digite o Identificador do sensor:"); sensor.setIdentificador(ler.nextLine()); System.out.println("Digite a estatistica de carros ontem:"); sensor.setTotalCarrosOntem(ler.nextLine()); System.out.println("Digite a estatistica de carros hoje:"); sensor.setTotalCarrosHoje(ler.nextLine()); System.out.println("Qual foi a maior quantidade de carros:"); sensor.setMaiorQuantidadeDeCarros(ler.nextLine()); System.out.println("Qual o limite tipico de veiculos transitando no local:"); sensor.setLimiteTipico(ler.nextLine()); cb.insere("INSERT INTO estatisticas.cadastro VALUES (NULL , '" + sensor.getIdentificador() + "', '" + sensor.getTotalCarrosOntem() + "', '" + sensor.getTotalCarrosHoje() + "', '" + sensor.getMaiorQuantidadeDeCarros() + "', '" +sensor.getLimiteTipico() + "' );", "Sensor gravado corretamente..."); break; } case 2: { ArrayList a = new ArrayList(); System.out.println("Digite o Sensor para procura:"); String Identificador = ler.nextLine(); a = cb.busca("SELECT * FROM estatisticas.cadastro WHERE Identificador LIKE '" + Identificador+ "%';"); if (a.size()>0){ } else{ System.out.println("nao achamos o sensor. "); } break; } case 3: { x=0; } } } } } MAQUETE A maquete foi criada a partir de MDF, possuindo as dimensões de Foram utilizadas tintas spray para a pintura, sendo: . Preto: Para o asfalto da rodovia; Branco: Para as faixas laterais de centrais da rodovia; Verde: Para pintura lateral ao acostamento, representando assim a vegetação. Os furos são passantes e possuem dimensões de para a maquete. , que é o tamanho dos LEDs, INTEGRAÇÃO Para concluir o projeto foi necessário juntar os módulos que foram desenvolvidos separadamente. também utilizamos sensores infravermelho de , sendo um emissor e um receptor, possuindo uma distancia de entre eles. Foi utilizado cola quente para fixação na maquete das peças utilizadas, também foi colocado. PLACA DE CIRCUITOS Para controlar a alimentação dos LEDs em cada um dos trechos da rodovia, estão sendo utilizados relés, para isso foi necessário criar uma placa de circuito impresso (Figura 1). A PCI consiste nos seguintes materiais: transistores NPN; relés NF; CÓDIGO FINAL DO PROJETO INTEGRAÇÃO DOS CÓDIGOS Aqui se concentra o código final do projeto, tendo toda sua integração concluída. jFInterface Este é o código para criação da interface, esta está dividida em quatro setores, onde estes devem corresponder a uma parte do programa, senso um para o console, estatísticas, emergências e sensores. public class jFInterface extends javax.swing.JFrame { public jFInterface() { initComponents(); } @SuppressWarnings("unchecked") private void initComponents() { jPanel1 = textArea4 jPanel2 = textArea2 jPanel3 = textArea3 jPanel4 = textArea1 new javax.swing.JPanel(); = new java.awt.TextArea(); new javax.swing.JPanel(); = new java.awt.TextArea(); new javax.swing.JPanel(); = new java.awt.TextArea(); new javax.swing.JPanel(); = new java.awt.TextArea(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Console", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Arial", 0, 18))); textArea4.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); textArea4.setEditable(false); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea4, javax.swing.GroupLayout.DEFAULT_SIZE, 361, Short.MAX_VALUE) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Estatisticas", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Arial", 0, 18))); textArea2.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); textArea2.setEditable(false); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea2, javax.swing.GroupLayout.DEFAULT_SIZE, 495, Short.MAX_VALUE) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea2, javax.swing.GroupLayout.DEFAULT_SIZE, 242, Short.MAX_VALUE) ); jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Sensores", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Arial", 0, 18))); // NOI18N textArea3.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); textArea3.setEditable(false); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea3, javax.swing.GroupLayout.DEFAULT_SIZE, 221, Short.MAX_VALUE) ); jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Emergencias", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Arial", 0, 18))); // NOI18N textArea1.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); textArea1.setEditable(false); javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); jPanel4.setLayout(jPanel4Layout); jPanel4Layout.setHorizontalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); jPanel4Layout.setVerticalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(textArea1, javax.swing.GroupLayout.DEFAULT_SIZE, 239, Short.MAX_VALUE) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); pack(); } public void setTextEmergencias (String s, boolean append) { if (append) this.textArea1.appendText(s); else this.textArea1.setText(s); } public void setTextEstatisticas (String s, boolean append) { if (append) this.textArea2.appendText(s); else this.textArea2.setText(s); } public void setTextSensores (String s, boolean append) { if (append) this.textArea3.appendText(s); else this.textArea3.setText(s); } public void setTextConsole(String s, boolean append) { if (append) this.textArea4.appendText(s); else this.textArea4.setText(s); } private private private private private private private private } javax.swing.JPanel jPanel1; javax.swing.JPanel jPanel2; javax.swing.JPanel jPanel3; javax.swing.JPanel jPanel4; java.awt.TextArea textArea1; java.awt.TextArea textArea2; java.awt.TextArea textArea3; java.awt.TextArea textArea4; MainClass A função deste código é executar todas as threads do programa, executando a interface, o processador de pacotes e o banco de dados. import MainCls.jFInterface; import ProcessadorDePacotes.ProcessadorPacotes; public class MainClass { public static jFInterface inter = new jFInterface(); public static void main(String args[]) { ProcessadorPacotes p = new ProcessadorPacotes(); Thread thread = new Thread (p); thread.start(); java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { inter.setVisible(true); } }); } BytesArray Classe usada para efetuar operações com arrays de bytes. package Bytes; public class BytesArray { Convertendo um inteiro para um array de bytes. public static byte[] intToByteArray(int value) { return new byte[] { (byte)(value >>> 24), (byte)(value >>> 16), (byte)(value >>> 8), (byte)value}; } Aqui faremos o inverso, convertendo um array de bytes para um inteiro. public static int byteArrayToInt(byte[] b) { return byteArrayToInt(b, 0); } Convertendo um array de bytes para um inteiro utilizando a posição offset. public static int byteArrayToInt(byte[] b, int offset) { int value = 0; for (int i = 0; i < 4; i++) { int shift = (4 - 1 - i) * 8; value += (b[i + offset] & 0x000000FF) << shift; } return value; } } ProcessadorPacotes O processador de pacotes é um módulo do projeto que foi criado para realizar determinar operações dependendo do conteúdo de um pacote recebido. Antes de o software iniciar o seu papel é inicialmente estabelecida uma conexão com o software responsável por adquirir as informações do servidor HTTP do Arduíno, uma vez conectado ele irá receber os pacotes TCP enviados a fim de interpretá-los. import import import import import import import MainCls.MainClass; TCP.Connection; java.io.IOException; java.net.ServerSocket; java.net.Socket; java.util.logging.Level; java.util.logging.Logger; public class ProcessadorPacotes implements Runnable { private static final int port = 7000; @Override public void run (){ ServerSocket server = null; try { server = new ServerSocket(port); } catch (IOException ex) { Logger.getLogger(ProcessadorPacotes.class.getName()).log(Level.SEVERE, null, ex); } MainClass.inter.setTextConsole("Servidor online!\n", false); MainClass.inter.setTextConsole("Aguardando coneccoes na porta " + port+"\n", true); System.out.println("[Info.] Servidor online!"); System.out.println("[Info.] Aguardando conecções na porta " + port); while (true) { Socket client = null; try { client = server.accept(); } catch (IOException ex) { Logger.getLogger(ProcessadorPacotes.class.getName()).log(Level.SEVERE, null, ex); } Connection connection = new Connection (client); Thread thread = new Thread (connection); thread.start(); } } } Sensor Este é responsável pelo contador, executando também as operações do banco de dados. O contador deve acrescentar ou decrementar o numero de veículos no trecho do sensor, passando essas informações para as estatísticas. package Sensor; public class Sensor { private static Sensor sensores[] = new Sensor[1]; private static int contador = 0; private int id; private int veiculos; Este é o construtor da classe, onde se cria uma nova instancia da classe, ou seja, um novo sensor, em seguida envia seu identificador a um vetor. private Sensor (int id) { this.id = id; this.veiculos = 0; } Método usado para criar um novo sensor dinamicamente, onde o array ajuda seu tamanho de acordo com a necessidade. public static Sensor novoSensor (int id) { if (idExiste(id)) return null; Sensor s = new Sensor (id); sensores[contador++] = s; Sensor copy[] = new Sensor[contador + 1]; System.arraycopy(sensores, 0, copy, 0, sensores.length); sensores = copy; return s; } Aqui incrementamos o contador de veículos que estão deste sensor até o próximo. public void incrementarContador (int id) { this.veiculos++; } Aqui decrementamos o contador de veículos que estão deste sensor até o próximo. public void decrementarContador (int id) { this.veiculos--; if (this.veiculos < 0) veiculos = 0; } Aqui verificamos se o sensor com o identificador especificado existe. public static boolean idExiste (int id) { for (int k = 0; k < (sensores.length - 1); k++) { if (sensores[k].id == id) return true; } return false; } Método que busca o sensor pelo identificador e retorna o mesmo, caso este seja encontrado. public static Sensor getSensor (int id) { for (int k = 0; k < (sensores.length - 1); k++) { if (sensores[k].id == id) return sensores[k]; } return null; } } Connection Esta classe será utilizada para conversar com os clientes conectados, utilizandose threads. import import import import import import MainCls.MainClass; java.io.IOException; java.io.InputStream; java.net.Socket; java.util.logging.Level; java.util.logging.Logger; public class Connection implements Runnable { private Socket client; private static int contador = 0; private int identificador; Construtor da classe, esse inicializa os campos do Socket do cliente conectado e incrementa o contador. public Connection (Socket client) { this.client = client; this.identificador = contador++; } @Override public void run () { MainClass.inter.setTextConsole("[Debug] -- Conexão aberta com " + this.getClient().getInetAddress()+ ":" +this.getClient().getPort()+"\n", true); System.out.println("[Debug] -- Conexão aberta com " + this.getClient().getInetAddress()+ ":" + this.getClient().getPort()); int size; byte[] buffer = new byte[255]; try { InputStream in = this.getClient().getInputStream(); while (true) { size = in.read(buffer); if (size == -1) continue; MainClass.inter.setTextConsole("[Debug] Recebi um pacote de " + size + " bytes de " + this.getClient().getInetAddress()+"\n", true); System.out.println("[Debug] Recebi um pacote de " + size + " bytes de " + this.getClient().getInetAddress()); MainClass.inter.setTextConsole("[Debug] Conteudo : \n", true); System.out.print("[Debug] Conteudo : "); for (int k = 0;; k++) { if ((k + 1) == size) { System.out.println(buffer[k]); break; } System.out.print(buffer[k] + "-"); } byte[] data = new byte[size+1]; System.arraycopy(buffer, 0, data, 0, size); if (!OpcodeHandler.handlePacket(data)) MainClass.inter.setTextConsole("[Debug] Ocorreu um erro processando um pacote enviado por " + this.getClient().getInetAddress()+"\n", true); System.out.println("[Debug] Ocorreu um erro processando um pacote enviado por " + this.getClient().getInetAddress()); } } catch (IOException ex) { Logger.getLogger(Connection.class.getName()).log(Level.SEVERE, null, ex); } } public Socket getClient() { return client; } public int getIdentificador() { return identificador; } } OpcodeHandlerlor. Classe usada para fazer a chamada de cada opcode de acordo com o seu v import Bytes.BytesArray; import MainCls.MainClass; import Sensor.Sensor; public class OpcodeHandler { Método usado para decidir se o tamanho de bytes é consistente com o esperado, caso o tamanho do resultado da operação for inconsistente será retornado falso, caso contrário retornaremos verdadeiro. private static boolean verifySize (int i) { if (i == 6) return true; return false; } Este método será usado para adicionar um novo sensor, e escolher um identificador para o mesmo. private static Sensor addSensor (int id) { Sensor s = Sensor.novoSensor(id); if (s != null) { MainClass.inter.setTextSensores("[Debug] -- Sensor com o identificador " + id + " adicionado!\n", true); System.out.println ("[Debug] -- Sensor com o identificador " + id + " adicionado!"); return s; } MainClass.inter.setTextSensores("[Debug] -- Sensor com o identificador " + id + " não pode ser adicionado!\n", true); System.out.println ("[Debug] -- Sensor com o identificador " + id + " não pode ser adicionado!"); return null; } Método usado para se remover um novo sensor que tenha seu identificador escolhido private static boolean removeSensor (int id) { MainClass.inter.setTextSensores("Operação não tratada: remover sensor\n", true); System.out.println("Operação não tratada: remover sensor"); return true; } Método usado para incrementar o contador do sensor que tenha seu identificador escolhido. private static boolean incrementCounter (int id) { Sensor s = Sensor.getSensor(id); if (s == null) { MainClass.inter.setTextSensores("[Debug] -- Sensor de identificador " + id + " não existe!\n", true); System.out.println ("[Debug] -- Sensor de identificador " + id + " não existe!"); return false; } s.incrementarContador(id); MainClass.inter.setTextSensores("[Debug] -- Sensor " + id + " incrementado!\n", true); System.out.println ("[Debug] -- Sensor " + id + " incrementado!"); return true; } Método usado para decrementar o contador de um sensor que tenha seu identificador escolhido. private static boolean decrementCounter (int id) { Sensor s = Sensor.getSensor(id); if (s == null) { MainClass.inter.setTextSensores("[Debug] -- Sensor de identificador " + id + " não existe!\n", true); System.out.println ("[Debug] -- Sensor de identificador " + id + " não existe!"); return false; } s.decrementarContador(id); MainClass.inter.setTextSensores("[Debug] -- Sensor " + id + " decrementado!\n", true); System.out.println ("[Debug] -- Sensor " + id + " decrementado!"); return true; } Método usado para interpretar os bytes recebidos pela conexão aberta. public static boolean handlePacket (byte[] packet) { int i = packet.length; // Verificando o tamanho do pacote recebido para evitar inconsistências, se o array de bytes tiver um tamanho menor que um devemos retornar falso if (!verifySize(i)) return false; // Recebe o primeiro byte do pacote, ou seja o seu código operacional byte header = packet[0]; // Os 4 bytes a partir do segundo byte são convertidos em um inteiro que é o identificador do sensor int id = BytesArray.byteArrayToInt(packet, 1); // Executando operações distintas para cada opcode switch (header) { case 0xA: // Adicionar sensor novo if (addSensor(id) == null) return false; return true; case 0xB: // Deletar sensor existente return removeSensor(id); case 0xC: // Incrementar contador return incrementCounter(id); case 0xD: // Decrementar contador return decrementCounter(id); default: return false; } } } MANUAL DO USUÁRIO A maquete é dividida em quatro sensores, onde cada um destes controla um determinado trecho, conforme mostrado na figura 2. Para a montagem de todo equipamento é necessário que primeiramente conecte os cabos ethernet no modem, demonstrado na Figura 3, após concluir esta etapa é necessário conectar um dos cabos no computador a ser utilizado e outro no Arduíno, isso é extremamente importante para o recebimento e envio de informações. Agora é necessário ligar todos os cabos da maquete (Figura 4) no Arduíno para o acionamento da PCI (embutida no interior da maquete), os fios devem ser conectados seguindo a ordenação do software do Arduíno, estes devem ser conectados conforme demonstrado na Figura 5. Após executar essas atividade, ligamos o cabo de energia da maquete em uma tomada 110V e o cabo USB, também embutido na maquete no próprio computador, este será responsável pela energia dos sensores. Após tudo estiver ligado de forma adequada, executa-se o software, onde abrirá uma interface de controle. Se tudo estiver funcional, o projeto funcionará perfeitamente. HISTÓRICO DE DESENVOLVIMENTO 11/03/2012 12/03/2012 15/03/2012 20/03/2012 23/03/2012 30/03/2012 04/04/2012 11/04/2012 18/04/2012 25/04/2012 02/05/2012 06/05/2012 09/05/2012 18/05/2012 23/05/2012 28/05/2012 06/06/2012 12/06/2012 Criação do Blog – Este deve conter todas as informações do andamento do projeto. Neste dia ocorreu a apresentação da defesa do projeto, no qual este foi aprovado, e assim iniciamos as atividades oficiais. Fomos apresentados ao Arduíno, como programa-lo e suas funcionalidades de um componente importante para o desenvolvimento. Chegou o shield Ethernet, no qual foi embutido ao Arduíno para ser utilizado na comunicação TCP/IP entre a central e os sensores. O Arduíno chegou após nossa encomenda, logo após iniciamos uma fase de testes, para aprender mais sobre suas funções e suas possibilidades de funcionamento. Esta semana iniciou-se o desenvolvimento dos fluxogramas para o software de comunicação através da programação do Arduíno e o shield Ethernet, também começamos a desenvolver o desenho da maquete no SolidWorks. Concluímos o projeto da maquete no SolidWorks, também concluímos o projeto do software da central e do Arduíno. Concluímos a interface gráfica da central. Foi concluído o processador de pacotes que irá interpretar os bytes recebidos do Arduíno e irá fazer as devidas entradas no banco de dados, este também governará o que será mostrado na interface gráfica da central. Aguardamos a chegada de alguns componentes. Iniciamos a procura de possíveis bugs no software. Iniciamos a montagem da maquete e iniciamos testes com os sensores infra-vermelho. Foi concluída a maquete Concluímos a PCI e instalamos os componentes na maquete Iniciamos o relatório e terminamos de implementar os sensores na maquete. Após todas as implementações concluímos todas as atividades relacionadas a criação, manutenção ou procura de possíveis erros. Pré-apresentação do projeto e demonstração da prévia da documentação. Apresentação oficial aos professores e termino da documentação.