Telemetria Automotiva via Internet Móvel
Transcrição
Telemetria Automotiva via Internet Móvel
Universidade de Brasília Instituto de Ciências Exatas Departamento de Ciência da Computação Telemetria Automotiva via Internet Móvel Alcides Carlos de Moraes Neto Brasília 2009 Universidade de Brasília Instituto de Ciências Exatas Departamento de Ciência da Computação Telemetria Automotiva via Internet Móvel Alcides Carlos de Moraes Neto Monografia apresentada como requisito parcial para conclusão do Bacharelado em Ciência da Computação Orientador Prof. Ricardo Pezzuol Jacobi Brasília 2009 Universidade de Brasília — UnB Instituto de Ciências Exatas Departamento de Ciência da Computação Bacharelado em Ciência da Computação Coordenador: Prof.a Carla Maria Chagas e Cavalcante Koike Banca examinadora composta por: Prof. Ricardo Pezzuol Jacobi (Orientador) — CIC/UnB Prof. Pedro de Azevedo Berger — CIC/UnB Prof.a Carla Maria Chagas e Cavalcante Koike — CIC/UnB CIP — Catalogação Internacional na Publicação de Moraes Neto, Alcides Carlos. Telemetria Automotiva via Internet Móvel / Alcides Carlos de Moraes Neto. Brasília : UnB, 2009. 111 p. : il. ; 29,5 cm. Monografia (Graduação) — Universidade de Brasília, Brasília, 2009. 1. Sistema embarcado, 2. Sistema automotivo, 3. Telemetria, 4. Internet móvel CDU 004.7 Endereço: Universidade de Brasília Campus Universitário Darcy Ribeiro — Asa Norte CEP 70910-900 Brasília–DF — Brasil Universidade de Brasília Instituto de Ciências Exatas Departamento de Ciência da Computação Telemetria Automotiva via Internet Móvel Alcides Carlos de Moraes Neto Monografia apresentada como requisito parcial para conclusão do Bacharelado em Ciência da Computação Prof. Ricardo Pezzuol Jacobi (Orientador) CIC/UnB Prof. Pedro de Azevedo Berger CIC/UnB Prof.a Carla Maria Chagas e Cavalcante Koike CIC/UnB Prof.a Carla Maria Chagas e Cavalcante Koike Coordenador do Bacharelado em Ciência da Computação Brasília, 7 de dezembro de 2009 À Alda, querida avó. Agradecimentos Agradeço primeiramente ao meu orientador, prof. Ricardo Jacobi por liderar este excelente projeto de pesquisa, me dando a oportunidade de realizar este trabalho que tanto me motivou e satisfez. A toda a equipe envolvida, tanto da UnB quanto da SEA Tecnologia, pelo ambiente de colaboração e discussão, sem o qual este trabalho não seria o mesmo. A todos os professores com quem tive contato durante esta longa jornada pela UnB. Aprendi com todos, não só conteúdo mas como ser uma pessoa melhor. Em especial, aos professores Marcelo Ladeira, Marco Aurélio e Alba Cristina por terem me tirado o medo de aprender C e pelas aulas engrandecedoras. Aos meus colegas de curso, novos e velhos, com os quais também aprendi muito. Ao pessoal do DAA e do DAIA na reitoria, por terem me dado a chance de concluir meu curso. Em especial ao Edson do posto avançado do DAA, por aguentar os telefonemas e sempre fazer o possível para ajudar. Aos meus amigos pelos momentos de diversão e descontração, sem os quais não seria possível manter a sanidade. Vocês me deram bônus no meu will save, IZO! Aos meus pais, minhas irmãs, meu avô xará, e toda minha família, pelo apoio, tanto material quanto motivacional, e paciência durante toda esta jornada. Muito obrigado. A minha linda e amada mulher, Ludmila Araujo. Foi com sua inteligência e sensibilidade que consegui ser o melhor que eu posso, e que tornou este trabalho possível. Muito obrigado, por tudo. Te amo mais que tudo na vida. v Resumo O presente trabalho tem como objetivo estudar a implementação de um sistema embarcado para a telemetria de um automóvel via internet móvel para o projeto Karmonitor. São levantadas as tecnologias disponíveis para monitoramento e diagnóstico em um automóvel, como o padrão OBD (On-board Diagnostics) e os protocolos mais usados para comunicação das diversas unidades eletrônicas de controle (ECUs) presentes no automóvel, como o CAN (Controller Area Network) e o J1850. São também estudadas as tecnologias móveis de conexão à Internet que estão disponíveis hoje e que deverão ser usadas pelo sistema embarcado. É abordado também o ambiente que foi definido pelo projeto Karmonitor onde o sistema será implementado, os softwares disponíveis para apoio e o desenvolvimento dos programas necessários para a execução da telemetria. Testes são feitos em alguns diferentes modelos de carros para averiguar o comportamento do sistema Palavras-chave: Sistema embarcado, Sistema automotivo, Telemetria, Internet móvel vi Abstract This work aims to study the implementation of an embedded automotive telemetry system via mobile Internet services for the Karmonitor project. Research is made on the available technologies for automotive diagnoses, like the OBD (On-board Diagnostics) standard and the most used bus protocols for communications of the many ECUs (Electronic Control Units) inside a car’s system, like CAN (Controller Area Network) and J1850. Also study is made on mobile Internet connection technologies that are available today that can be used in this embedded system. All this will be done before analysing the environment defined for the Karmonitor system, the software available that can support a telemetry system and the development of programs needed to execute it. Tests are made on some car models in order to observe the system’s behaviour. Keywords: Embedded system, Automotive system, Telemetry, Mobile Internet vii Lista de Figuras 1.1 Exemplo de arquitetura para telemetria via Internet . . . . . . . . . 1.2 Diagrama de arquitetura de telemetria móvel . . . . . . . . . . . . . . 2.1 2.2 2.3 2.4 Diagrama de um automóvel com 3 redes distintas: Quadro de dados do protocolo CAN 2.0A . . . . . . Quadro de dados do protocolo CAN 2.0B . . . . . . Ciclo de comunicação do protocolo FlexRay . . . . 4 5 LIN, CAN e MOST 7 . . . . . . . . . . . 15 . . . . . . . . . . . 15 . . . . . . . . . . . 18 3.1 Esquema do conector OBD-II . . . . . . . . . . . . . . . . . . . . . . . 3.2 Interface OBD x USB de Alex Sidorenko . . . . . . . . . . . . . . . . . 3.3 Esquema elétrico da interface OBD x USB de Alex Sidorenko . . . . 22 23 24 4.1 Uma rede GSM com nós SMS e GPRS (Junior, 2005) . . . . . . . . . 4.2 Placa PCMCIA da VIVO para acesso a rede GSM 3G . . . . . . . . . 4.3 Interface USB GSM 3G. . . . . . . . . . . . . . . . . . . . . . . . . . . 30 31 32 5.1 5.2 5.3 5.4 A Beagle Board com seus principais componentes destacados . Fluxograma do programa cliente . . . . . . . . . . . . . . . . . Fluxograma do programa servidor . . . . . . . . . . . . . . . . Diagrama de classes do programa servidor . . . . . . . . . . . . . . . . . . . 34 37 39 40 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 Exemplo de arquivo de configuração do cliente . . . . . . . . . . . . Notebook Dell utilizado para executar o sistema . . . . . . . . . . . Conector USBxOBD . . . . . . . . . . . . . . . . . . . . . . . . . . . . Celular Nokia N95 com cabo USB para uso como modem 3G/GPRS. Automóvel Ford Ka 1.0, ano 2009, exterior. . . . . . . . . . . . . . . Localização do conector OBD no Ford Ka. . . . . . . . . . . . . . . . Automóvel Nissan Livina 1.6, ano 2009, exterior. . . . . . . . . . . . Localização do conector OBD no Nissan Livina. . . . . . . . . . . . . Automóvel Ford Focus 2.0, ano 2009, exterior. . . . . . . . . . . . . . Localização do conector OBD no Ford Focus. . . . . . . . . . . . . . . . . . . . . . . . . 45 53 53 54 54 55 55 56 56 57 viii . . . . . . . . Lista de Tabelas 2.1 Tipos de protocolo J1850 (Riley, 1998) . . . . . . . . . . . . . . . . . . 2.2 Símbolos do protocolo J1850 (Riley, 1998) . . . . . . . . . . . . . . . . 8 9 3.1 Dados OBD-II . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 5.1 Estrutura da tabela de veículos . . . . . . . . . . . . . . . . . . . . . . 5.2 Estrutura parcial da tabela de dados OBD . . . . . . . . . . . . . . . . 5.3 Comandos que o servidor pode enviar ao cliente . . . . . . . . . . . . 41 41 42 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 47 48 48 49 49 50 50 51 51 51 52 52 Dados OBD suportados pelo Ford Ka. . . . . . . . . . . . . . . . Taxas do sistema observadas durante testes no Ford Ka. . . . . Exemplo de dados levantados para o Ford Ka. . . . . . . . . . . Valores médios de parâmetros levantados para o Ford Ka. . . . Dados OBD suportados pelo Nissan Livina. . . . . . . . . . . . . Taxas do sistema observadas durante testes no Nissan Livina. . Exemplo de dados levantados para o Nissan Livina. . . . . . . . Valores médios de parâmetros levantados para o Nissan Livina. Dados OBD suportados pelo Ford Focus. . . . . . . . . . . . . . . Taxas do sistema observadas durante testes no Ford Focus. . . . Exemplo de dados levantados para o Ford Focus. . . . . . . . . . Valores médios de parâmetros levantados para o Ford Focus. . . ix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sumário Lista de Figuras viii Lista de Tabelas ix 1 Introdução 1.1 Projeto Karmonitor . . . . . . 1.2 Problema . . . . . . . . . . . . 1.3 Objetivos . . . . . . . . . . . . 1.4 Motivação . . . . . . . . . . . . 1.5 Metodologia . . . . . . . . . . 1.6 Telemetria . . . . . . . . . . . 1.6.1 Análise da arquitetura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Tecnologias de barramento automotivas 2.1 Classe A . . . . . . . . . . . . . . . . . . 2.1.1 Local Interconnect Network . . . 2.1.2 TTP/A . . . . . . . . . . . . . . . . 2.2 Classe B . . . . . . . . . . . . . . . . . . 2.2.1 J1850 . . . . . . . . . . . . . . . . 2.2.2 ISO 9141-2 . . . . . . . . . . . . . 2.2.3 ISO 14230-4 . . . . . . . . . . . . 2.2.4 Low-speed CAN . . . . . . . . . . 2.3 Classe C . . . . . . . . . . . . . . . . . . 2.3.1 High-speed CAN . . . . . . . . . . 2.3.2 TTP/C . . . . . . . . . . . . . . . . 2.4 Classe D . . . . . . . . . . . . . . . . . . 2.4.1 MOST . . . . . . . . . . . . . . . . 2.4.2 FlexRay . . . . . . . . . . . . . . . 3 Aquisição de dados 3.1 OBD . . . . . . . . . . . . . . . . . . . 3.1.1 História . . . . . . . . . . . . . 3.1.2 Padrões OBDBr-1 e OBDBr-2 3.1.3 Padrão OBD-II . . . . . . . . . x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 2 2 3 3 3 4 . . . . . . . . . . . . . . 6 7 7 8 8 8 10 12 12 16 16 17 17 17 17 . . . . 19 19 19 20 21 4 Telefonia móvel 4.1 GSM . . . . . . . . . . . . . . . . 4.1.1 SMS . . . . . . . . . . . . 4.1.2 GPRS . . . . . . . . . . . 4.1.3 EDGE e UMTS . . . . . 4.1.4 Acesso à Internet Móvel . . . . . 5 Arquitetura do Sistema 5.1 Hardware . . . . . . . . . . . . . . 5.2 Sistema Operacional . . . . . . . 5.2.1 Linux . . . . . . . . . . . . 5.2.2 Angstrom . . . . . . . . . . 5.3 Software . . . . . . . . . . . . . . 5.3.1 Medição . . . . . . . . . . . 5.3.2 Cliente . . . . . . . . . . . 5.3.3 Servidor . . . . . . . . . . 5.3.4 Protocolo de comunicação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 28 29 29 30 31 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 33 33 34 35 35 35 36 38 42 6 Testes e análises 6.1 Plataforma de testes . . . . . . . . . . . 6.2 Procedimentos . . . . . . . . . . . . . . . 6.2.1 Montagem do ambiente cliente . 6.2.2 Montagem do ambiente servidor 6.3 Cálculos . . . . . . . . . . . . . . . . . . . 6.4 Ford Ka 1.0 2009 . . . . . . . . . . . . . 6.4.1 Dados do teste . . . . . . . . . . . 6.4.2 Campos OBD suportados . . . . . 6.4.3 Valores observados . . . . . . . . 6.5 Nissan Livina 1.6 2009 . . . . . . . . . . 6.5.1 Dados do teste . . . . . . . . . . . 6.5.2 Campos OBD suportados . . . . . 6.5.3 Valores observados . . . . . . . . 6.6 Ford Focus 2.0 2009 . . . . . . . . . . . . 6.6.1 Dados do teste . . . . . . . . . . . 6.6.2 Campos OBD suportados . . . . . 6.6.3 Valores observados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 43 44 44 45 46 47 47 47 48 48 48 49 49 50 50 50 51 . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Conclusão e desenvolvimentos futuros 58 Referências 60 I Código-fonte do cliente I.1 clientmain.h . . . . . I.2 clientmain.c . . . . . I.3 database.h . . . . . . I.4 database.c . . . . . . I.5 networking.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 63 64 70 71 73 I.6 networking.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II Código-fonte do servidor II.1 Main.java . . . . . . . . II.2 ServerThread.java . . . II.3 DbConnector.java . . . II.4 ObdDao.java . . . . . . II.5 Vehicle.java . . . . . . . II.6 VehicleDao.java . . . . 75 . . . . . . 79 79 81 87 89 91 93 III Tabelas do banco de dados do servidor III.1 Tabela VEHICLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . III.2 Tabela OBDGPSDATA . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 95 95 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Capítulo 1 Introdução Desde o início dos anos 70, cada vez mais os veículos automotores têm sido equipados com unidades eletrônicas de controle (Electronic Control Units - ECU). Estas ECUs realizam monitoramentos, compartilham informações através de barramentos, fazem ajustes baseados nas informações disponíveis e muitas já são responsáveis por funções vitais para o funcionamento dos veículos (por ex: injeção eletrônica). É fácil ver o porquê desta tendência: Equipamentos eletrônicos oferecem muito mais versatilidade, confiabilidade e performance do que máquinas estritamente mecânicas. As possibilidades que são disponibilizadas pela tecnologia de software permite a implantação de sistemas complexos que melhoram não só o desempenho do veículo, mas como a segurança e o conforto de seu usuário. 1.1 Projeto Karmonitor O projeto Karmonitor propõe o desenvolvimento de uma plataforma em sistema embarcado para telemonitoramento e telecontrole de veículos baseada em FPGA. Um dos objetivos do projeto é permitir que o usuário obtenha informações sobre o estado do veículo e envie comandos para alterá-lo através de aplicação executando em telefone celular. Atualmente os serviços de telefonia celular apresentam uma área de cobertura significativa. Associada a larga difusão dos aparelhos celulares na sociedade, a possibilidade de acessar informações sobre o estado do veículo, incluindo sua localização, e enviar comandos para controlá-lo através do celular caracteriza um nicho de mercado ainda não explorado, e uma oportunidade para desenvolvimento de um produto inovador e com forte apelo comercial. Outro objetivo do projeto é ser um interpretador de comandos vocais emitidos tanto por celular como do interior do veículo. O controle do estado do veículo através de uma interface natural, além de auxiliar o usuário comum, é igualmente de interesse para portadores de necessidades especiais (PNE), pois permite ao motorista realizar tarefas sem a necessidade de retirar as mãos do volante. 1 1.2 Problema Um dos problemas que o projeto Karmonitor aborda é o da medição de dados funcionais de veículos remotamente, de forma automatizada, que será o foco deste projeto. Os veículos automotivos devem ser submetidos a constantes revisões para averiguação do seu funcionamento e performance. Este processo está cada vez mais informatizado, como pode ser visto neste projeto, com o desenvolvimento de protocolos para medição dos dados funcionais do veículo, diminuindo a necessidade de diagnóstico mecânico. Mas ainda assim é necessário que o veículo seja retirado de circulação e seja submetido a técnicos humanos que, mesmo com a crescente informatização do processo, ainda podem cometer erros. Como essas medições são periódicas, e dependem que o proprietário do veículo leve-o até a assistência técnica, nem elas são realizadas pelos veículos estarem funcionando satisfatoriamente, apesar de estarem desregulados. Uma das consequências disso é um maior consumo de combustível pelos veículos desregulados, e também maior quantidade de poluentes gerados. Apesar de existir legislação que estabeleça limites para a emissão de poluentes pelos veículos (Lei 8.723, de 28 de outubro de 1993), ela é praticamente nula, visto que não existe forma fácil para medição deste parâmetro em larga escala. 1.3 Objetivos A proposta deste projeto para a solução do problema é um sistema embarcado a bordo do veículo para aquisição e envio dos dados para uma aplicação servidora via Internet, utilizando uma conexão via rede celular. Este sistema de telemetria levantaria periodicamente os dados disponibilizados pelo automóvel e enviar-los-ia a um ou mais destinatários, que podem ser máquinas servidoras dedicadas a receber e processar estes dados ou mesmo o celular do proprietário. Objetivos específicos: 1. Estudo das tecnologias: (a) Redes digitais intraveiculares e como criar uma interface com elas. (b) Redes celulares e como realizar conexão com a Internet através delas. 2. Desenvolvimento da aplicação: (a) Módulo para aquisição dos dados de um veículo. (b) Módulo para envio dos dados pela Internet, utilizando rede celular. (c) Programa servidor que fará o recebimento e processamento dos dados. 2 1.4 Motivação Um sistema que possibilite monitoramento remoto de automóveis pode ser aplicado para diversos fins, inclusive: • No monitoramento de frota de veículos de uma empresa ou entidade, diminuindo o número de vezes que o veículo deve ser retirado de circulação para manutenção. • Em estudo estatístico por parte da montadora ao utilizar o sistema em todos seus veículos, obtendo assim uma população muito significativa para estudo. • Na verificação do nível de emissão de gases poluentes dos automóveis, possibilitando assim a fiscalização da legislação vigente, melhorando a qualidade do ar e diminuindo o consumo de combustível fóssil. 1.5 Metodologia Para chegar a tais objetivos, pode-se destacar os principais passos: 1. Arquitetura do sistema e ambiente de desenvolvimento: É necessário antes de mais nada conhecer o ambiente de desenvolvimento utilizado e qual será sua arquitetura. 2. Aquisição de dados: É necessário que o sistema consiga acessar os dados funcionais do automóvel. É necessário que seja definido o hardware e/ou software necessário. 3. Processamento dos dados: Depois de recuperar os dados, o sistema deverá tratá-los e decidir o envio deles. Aqui pode ser feita seleção de qual servidores receberão os dados. Por exemplo pode haver um destino para dados de funcionamento e outro para dados de problema ou defeitos. 4. Envio dos dados: Estudar a tecnologia que será usada para o envio, considerando a possibilidade de múltiplos protocolos se for possível e plausível. Por exemplo, dados ao condutor ou proprietário do veículo podem ser feitos via SMS. Dados para um servidor na Internet podem ser enviados por GPRS. 5. Arquitetura de um sistema servidor: Levantar as possibilidades para o recebimento destes dados via Internet: Qual o tipo de protocolo e software usar para receber esses dados. Também as estatísticas que podem ser levantadas por um servidor. 1.6 Telemetria Telemetria é uma forma de tecnologia muito empregada em diversas áreas da ciência, com a medicina (Gutierrez, 2006; Paim, 2005) a biologia (Mantovani and 3 Figura 1.1: Arquitetura para telemetria via Internet proposta em Khan et al. (2007). Santos, 2001), e até mesmos parques temáticos (Walker, 2007). Consiste na medição de dados de interesse de um analisador e consequente envio desses dados para um acumulador para posterior análise. Tais sistemas diferem entre si tanto pela tecnologia empregada quanto pela arquitetura adequada para resolver suas necessidades. Normalmente são implantados em locais de difícil acesso, as vezes inóspitos a seres humanos, possibilitando o monitoramento constante destes sistemas em outro local, possuindo diferentes necessidades de distância e banda de transmissão. Considerando o local de instalação do projeto, um automóvel, e o ambiente urbano em que circula, foi escolhido hardware e interface de comunicação adequados para prover acesso a um acumulador remoto: Acesso à Internet via rede celular, presente na grande maioria de cidades brasileiras. Pela Internet então, é possível acessar um servidor em qualquer lugar do mundo, que servirá de acumulador de dados. 1.6.1 Análise da arquitetura Sistemas de Telemetria via Internet já existem, como visto em Khan et al. (2007), porém, a arquitetura proposta sugere a conexão remota do medidor ao dispositivo sendo medido, configurando uma arquitetura cliente-servidor onde o servidor é quem faz o levantamento dos dados. Esta arquitetura pode ser visualizada na figura 1.1. Analisando esta arquitetura para uma aplicação automotiva, ela não parece a ideal, pelas seguintes razões: • Uma conexão móvel não tem endereçamento estável. Ao movimentar-se, um dispositivo celular troca a central de comunicações com a qual mantém conexão constantemente, mudando assim seu endereçamento. Um endereçamento dinâmico dificulta a conexão remota. 4 Figura 1.2: Diagrama da arquitetura de telemetria móvel proposta em Jenkins (2004). • Conexões móveis são instáveis, podendo ser perdidas em uma troca de central ou mesmo quando o veículo está fora da área de cobertura. Esta arquitetura é plausível para sistemas que têm uma conexão estável e constante com a Internet, o que não é o caso. Uma arquitetura para medição de performance de veículos via Internet é proposta em Jenkins (2004). A arquitetura proposta considera estas dificuldades e estabelece um fluxo contrário, onde a máquina cliente está no veículo, enquanto um servidor remoto recebe os dados enviados pelo veículo constantemente e o armazena em um banco de dados. Máquinas clientes então se conectam a este servidor intermediário para fazer consultas. Um diagrama desta arquitetura pode ser visto na figura 1.2. A arquitetura do sistema será baseada nesta, muito mais plausível em um ambiente automotivo. A medição constante pelo sistema será armazenada localmente antes de acontecer a tentativa de envio, evitando com que dados sejam perdidos. 5 Capítulo 2 Tecnologias de barramento automotivas Com o crescente número e complexidade de ECUs nos veículos, tornou-se necessário que estes componentes trocassem informações entre si. A princípio a comunicação era feita através de ligações diretas entre os componentes. Mas o crescente número destas ECUs tornou esta solução ineficaz, visto que para cada n controladoras, seria necessário n2 conexões para interligar todos. Dada esta situação, a possibilidade de se conectar um número arbitrário de componentes entre si, com protocolo de comunicação pré-definido por uma interface padrão foi o motivador para a criação dos barramentos automotivos. Estudar a tecnologia utilizada no automóvel para transmissão de dados entre os ECUs é fundamental para a arquitetura de um sistema embarcado, pois é através dela que será feita a troca de mensagens entre os componentes do carro e o sistema. Para entender melhor os requisitos do automóvel, suas funções são separadas em domínios (Navet et al., 2005) que correspondem a diferentes recursos e restrições. Estes domínios são: 1. Sistema de força: Responsável pelo controle do motor e transmissão. 2. Chassi: Onde é feito o controle de suspensão, volante e freios. 3. Corpo: Recursos de conforto como inclinação de assento e ar condicionado. 4. Telecomunicação: Comunicações com o mundo externo; sem-fio, sistemas de localização. 5. Multimídia e Interface homem máquina (HMI): Interação com o condutor e passageiros. 6. Segurança: Voltado para a segurança dos ocupantes do veículo. Existem diversas tecnologias usadas para a comunicação dos componentes, cada qual com características específicas para atender os diferentes domínios (como tempo de resposta, banda, redundância, detecção de erros, etc.), e é normal encontrar mais de um barramento implantado em um veículo (Podemos ver um exemplo de implementação na figura 2.1). Em 1994, a Sociedade de Engenheiros Automotivos dos Estados Unidos (SAE - Society for Automotive Engineers) definiu uma 6 classificação para protocolos de comunicação automotivos baseada na velocidade de transmissão de dados e funções que são distribuídas pela rede. Os protocolos foram separados em classes A, B, C e D (Leen and Heffernan, 2002; Leen et al., 1999). Figura 2.1: Diagrama de um automóvel com 3 redes distintas: LIN, CAN e MOST 2.1 Classe A São redes com taxa de transmissão menor que 10kb/s, usadas para transmitir dados de controle simples, utilizando tecnologias de baixo custo. São principalmente utilizadas no domínio "‘corpo"’, que possui somente sistemas não críticos como controle de assento e detector de chuva. Exemplos de redes classe A são LIN e TTP/A. 2.1.1 Local Interconnect Network LIN, ou Local Interconnect Network, é uma evolução do ISO 9141, uma rede de baixa velocidade e custo. Esta rede é normalmente usada para interligar dispositivos simples sem muitas variáveis de controle como assentos, espelhos e janelas. Sua arquitetura é a mestre-escravo que, além de não necessitar de diversos nodos com funcionamento complexo, é também uma medida de segurança, visto que é impossível comprometer outros nodos da rede através de um nodo vulnerável. (Por exemplo, abrir a janela do carro através do sistema de controle dos vidros retrovisores) (Leen and Heffernan, 2002). É um padrão aberto (criado pelas empresas Audi, BMW, DaimlerChrysler, Motorola, Volcano, Volvo e Volkswagen) e foi desenvolvido com o intuito de ser integrado com protocolos de maior velocidade como o CAN. 7 2.1.2 TTP/A Protocolo similar ao LIN, mas de iniciativa acadêmica, criado pela Universidade Técnica de Vienna, Áustria; Universidade Técnica de Munich e Universidade de Stuttgart, Alemanha. Assim como o LIN foi criado para complementar o CAN, o TTP/A foi criado para complementar o TTP/C, de autoria também das faculdades citadas (Kopetz and Grunstidl, 1993). TTP significa Time Triggered Protocol, devido a sua principal característica que é a estratégia de envio de dados em janelas de tempo específicas para cada nodo (TTA Group, 2004). Os dois protocolos são semelhantes, mas o TTP/A foi desenvolvido com maior número de aplicações em mente, não somente a automobilística. Comparações entre o TTP/A e o LIN mostram a superioridade do TTP/A quanto a recursos e performance (Kopetz et al., 2000). 2.2 Classe B Redes dedicadas à conexão de ECUs, de forma a diminuir a necessidade de sensores através da troca de informações. Estas redes operam entre 10 e 125 kb/s. O J1850 e o CAN de baixa velocidade (low-speed CAN) são os principais representantes desta classe. São protocolos desta classe que são usados para diagnóstico a bordo (OBD). 2.2.1 J1850 O barramento J1850, adotado pela SAE em 1994 como o padrão classe B mas já considerado em declínio em favor do CAN, é um barramento usado em aplicações de diagnóstico e compartilhamento de dados em veículos. A GM e a Chrysler adotaram J1850 VPW, denominando-o de Barramento Classe 2 (Class 2 Bus). A Ford utiliza o J1850 PWM, que é definido como o Protocolo Corporativo Padrão (Standard Corporate Protocol). Características O J1850 é usado de duas formas: A 41.6 Kbps via modulação por largura de pulso (PWM) em cabo duplo, ou a 10.4 Kbps via modulação de pulso variável (VPW) em cabo simples. Apesar de não serem compatíveis na camada física, os dois tipos possuem semelhanças na camada de ligação de dados. O protocolo utiliza a estratégia de transmissão CSMA/NDA (Oliver, 2001). A tabela 2.1 mostra as características dos dois tipos. Rede Taxa Transm. Int. Física J1850 VPW 10.4 kbits/s Fio simples (com terra) J1850 PWM 41.6 kbits/s Dois fios, sinal balanceado Tabela 2.1: Tipos de protocolo J1850 (Riley, 1998) 8 O padrão J1850 define um conjunto de símbolos e como eles são usados para construir mensagens no barramento. Um símbolo representa uma unidade de informação. Uma lista dos símbolos definidos pode ser vista na tabela 2.2 Símbolo Descrição SOF Começo do quadro (Start Of Frame) 0 zero lógico 1 um lógico EOD Fim dos dados (End Of Data) NB Bit de Normalização (somente em VPW) EOF Fim do quadro (End Of Frame) IFS Separação de quadros (Inter-Frame Separation) Break Interrupção do barramento Tabela 2.2: Símbolos do protocolo J1850 (Riley, 1998) O barramento J1850 pode estar em dois estados: ativo e passivo. Nenhum destes estados unicamente é usado para passar informações. Mas o estado do barramento é importante para o entendimento da definição dos vários símbolos. O estado ativo é o dominante. No método de transmissão do J1850, que é o CSMA/NDA, a disputa pelo barramento é não-destrutiva. Múltiplos nodos podem começar a transmissão simultaneamente. A rede define que o zero lógico é dominante. Logo, mensagens que tem prioridade são definidas com identificadores menores. Consequentemente, quando vários nodos estão transmitindo ao mesmo tempo, somente o nodo que transmitir um zero final vencerá a disputa e continuará sua transmissão. Os outros nodos verificam que perderam prioridade e interrompem seu envio (Riley, 1998). Meio físico A rede VPW consiste de um único fio, denominado BUS+. Quando o barramento está no modo passivo, BUS+ está próximo de 0 V. Quando está ativo, a linha fica a +7 V. A rede PMW consiste em um par de fios, o BUS+ e o BUS-. No modo passivo, a voltagem é -5 V (medição de BUS+ em relação a BUS-). Quando ativo, a voltagem é +5 V. Com relação ao terra, o barramento passivo tem BUS+ a 0 V e BUS- a 5 V, com as voltagens invertidas no barramento ativo (Riley, 1998). Protocolo Todas as comunicações no barramento J1850, assim como a grande maioria de outros protocolos, é feita atráves de quadros, ou frames. Cada frame é construído de forma semelhante: O frame começa com o símbolo SOF, seguido do bit mais significante do primeiro byte da mensagem. O último byte transmitido deste segmento é um CRC (cyclic redundancy check). Por fim, o símbolo EOD indica o fim do segmento de dados. 9 Após o envio do EOD, um ou mais nodos podem responder a mensagem. Se isto ocorrer, é chamdo de In-Frame Response (IFR). Estas respostas são opcionais. Um símbolo EOF é transmitido após o IFR (se houve algum) para indicar que o frame está completo. Transmissão de um próximo frame só pode ser feita depois de um tempo determinado IFS. 2.2.2 ISO 9141-2 O padrão ISO 9141, também conhecido como padrão CARB 9141 (California Air Resources Board). Este padrão era referenciado pela regulamentação da CARB que foi a precursora da lei que criou o OBD-II. Mais tarde, a CARB adotou uma versão melhorada da ISO 9141, a ISO 9141-2, com o subtítulo de CARB Requirements for Interchange of Digital Information (Riley, 1998). Assim como os outros padrões, este padrão descreve as camadas físicas e de ligação de dados (relativas ao modelo de rede OSI). Características As principais características da rede ISO 9141-2 são: • Meio físico: Fio duplo (sinal não balanceado) • Taxa de transmissão: 10.4 kb/s • Tempo de bit: 96.15 µs A arquitetura da ISO 9141 se distancia do padrão J1850 mencionado anteriormente e, de forma geral, da maioria das estruturas de redes existentes. Uma rede J1850 não possui um nodo central e não há o conceito de direção de sinal ou fluxo. Em uma rede J1850, todos os nodos são semelhantes, pois qualquer um pode transmitir e todos recebem as mensagens. De forma semelhante, símbolos e mensagens são independentes de quem está transmitindo ou recebendo. Em uma rede compatível com ISO 9141-2, direção do fluxo de mensagem é uma característica importante. A especificação foi escrita levando em conta a conexão de aparelhos de medição externos a rede. A direção das mensagens e questões quanto a temporização destas são baseadas em quem está "‘falando"’ e quem está "‘ouvindo"’. Meio físico Um barramento ISO 9141 consiste de dois fios, designados linhas K e L (K-line e L-line). A voltagem define o estado de cada linha, podendo estar em alta (1 lógico) ou baixa voltagem (0 lógico). Diferente do J1850, as linhas K e L não têm estados ativo ou passivo. Quando um nodo está ligado, ambas as linhas são ligadas à alimentação da bateria. Ambas linhas ficam ociosas no estado 1. Para um nodo transmitir um 0, ele desvia a linha desejada para o terra e a mantém assim durante um tempo de bit. 10 A linha K é bidirecional e compartilhada por todos os nodos assim como o equipamento de teste externo. Todos os nodos ouvem esta linha e transmitem nela. A arquitetura da linha K é semelhante a um circuito lógico OU. Isto faz com que o um lógico seja o bit dominante, assim como no J1850. A linha L é unidirecional, e somente o equipamento externo pode transmitir nela. Módulos que suportam diagnóstico externo têm que ouvir esta linha (Riley, 1998). Protocolo Uma rede ISO 9141 é baseada no UART (Universal Asynchronous Receiver/Transmitter), que é encontrado em outros padrões de comunicação como o RS-232. São usados bits de início e parada. A sinalização é de não retorno a zero. Todos os símbolos são transmitidos no tempo de bit fixado. O bit de início é o 0 lógico durante um tempo de bit, enquanto o bit de parada é o 1 lógico. Todas as mensagens são transmitidas em um ou mais bytes. Cada byte é enviado como um pacote de bits, sendo cada byte precedido pelo bit de início. Oito bits de dados são usados, sendo enviados na ordem do menos ao mais significativo. O bit de parada é anexado ao fim. Diferentemente do J1850, não existem símbolos especiais de início ou fim do quadro. O significado de um byte na mensagem em comparação com outro ou se uma mensagem termina e outra começa é estritamente uma função de tempo. A especificação define janelas para todos parâmetros temporais, um para cada situação. Alguns exemplos de janelas são o tempo entre bytes provindos do equipamento externo ou o tempo do fim de uma mensagem do veículo até o início da próxima mensagem do equipamento externo. Os vários tempos são denotados como tempos W e P. Pelo menos um deles é dinamico e dependente de quando o equipamento está enviando uma mensagem. O tempo W se aplica durante a fase de inicialização e o tempo P se aplica durante as outras fases. Quando um computador conecta-se a uma interface J1850 e envia uma mensagem de requisição OBD-II, como por exemplo a pressão do óleo (assumindo que o sistema está operando corretamente), o veículo irá responder com uma mensagem com os dados requisitados. Se isto for feito em uma rede ISO 9141-2, não conseguirá obter uma resposta. Antes de um equipamento externo poder se comunicar com o computador a bordo, de acordo com a ISO 9141-2, a comunicação deve ser iniciada. A sequência de iniciação permite que as duas partes, o equipamento externo e o computador de bordo, se reconheçam um ao outro e o meio com que eles se comunicarão. Em essência, assim acontece o básico da iniciação: 1. O equipamento externo envia o código 51 a 5 bauds em ambas as linhas K e L. Depois, a linha L é desabilitada e fica ociosa. 2. Os componentes do veículo acordam se não estiverem ativos, mas somente o computador responsável pelo diagnóstico responde com o código 85 à taxa de 10.4 kb/s. Este é o byte de sincronização. 11 3. Todas as comunicações agora são feitas a 10.4 kb/s. 4. O computador de bordo envia duas palavras chaves, #1 e #2, ambas valores de um byte. 5. O equipamento externo responde enviando uma inversão bit a bit da palavra #2. 6. O veículo responde enviando a inversa do comando de incialização enviada pelo equipamento no primeiro passo. 7. A partir de então, a comunicação está estabelecida e operacional. Uma vez que a ligação esteja feita, ela deve ser mantida. Se não houver tráfego no barramento por 5 segundos, cada computador assume que as comunicações estão encerradas. A inicialização deve ser repetida para re-estabelecimento das comunicações. O equipamento pode transmitir periodicamente uma mensagem para manter a ligação ativa (Riley, 1998). 2.2.3 ISO 14230-4 O ISO 14230-4, também conhecido como KWP2000 (Keyword Protocol 2000), é uma extensão do ISO 9141-2, compartilhando o mesmo meio físico e outras características, sendo a principal diferença a capacidade de enviar mensagens muito maiores, 260 bytes no máximo ao contrário de 11 bytes do protocolo 9141-2 (Dzhelekarski and Alexiev, 2005b). Assim como o 9141-2, é usado principalmente na Europa e Ásia. 2.2.4 Low-speed CAN (Controller Area Network) O CAN está se tornando o protocolo padrão para comunicação entre os componentes eletrônicos nos veículos, já existindo norma norte-americana tornando obrigatória sua aplicação. História e aplicações O Controller Area Network é um barramento de comunicações serial voltado para aplicações de controle em tempo real; operando a uma taxa de até 1 Mbps, com excelente detecção de erro e recursos de confinamento. O CAN foi originalmente desenvolvido por uma empresa alemã automobilística, a Robert Bosch, com o intuito de prover um barramento de comunicação a um custo efetivo para componentes eletrônicos nos veículos e como uma alternativa aos emaranhados de fios e conectores que eram caros e não confiáveis. A indústria automobilística continua usando o CAN em um crescente número de aplicações, mas pela sua robustez e confiabilidade, CAN está também sendo usado em muitas outras aplicações. Este é um padrão aberto, documentado na ISO 11898 (para aplicações em alta velocidade) e na ISO 11519 (para conexões em baixa velocidade) (Kvaser AB, 2009; Pazul, 1999; Schofield, 1996). 12 Diversos controladores CAN e dispositivos de interface estão disponíveis à venda por muitos dos principais manufaturadores de semicondutores. Existe também uma infinidade de pacotes de desenvolvimento de sistemas baseados em CAN, placas de interface e kits de desenvolvimento de sistemas (SDKs) que provém as ferramentas necessárias para construir, monitorar, testar e analisar sistemas baseados em CAN. Consequentemente, a maioria dos automóveis hoje na Europa, e cada vez mais no resto do mundo, já usam a tecnologia CAN em seus sistemas (Schofield, 1996). Controladores e interfaces CAN são fisicamente pequenos, operando em altas velocidades e em ambientes hostis. Estas propriedades levaram o CAN a ser usado em muitas outras aplicações além da automobilística. Alguns exemplos: • Sistemas de controle e navegação naval • Sistemas de controle de elevadores • Máquinas agrícolas • Equipamentos médicos Meio físico O CAN usa codificação sem retorno a zero (NRZ) e com bit-stuffing (técnica para diferenciar sequência de bits de delimitadores) para transmissão de dados em um barramento diferencial em dois fios. O uso da codificação NRZ garante mensagens compactas e com alta resistência a interferências externas. O barramento em fio duplo é normalmente feito em par trançado. Par simples também pode ser usado mas é mais suscetível a interferência. Uma das características do CAN que reforçam sua confiabilidade é uma recomendação da ISO 11898 que recomenda que os chips de interface do barramento sejam feitos de tal forma que a comunicação possa continuar (mas com uma reduzida relação sinal-ruído) mesmo que: • Qualquer um dos fios do barramento se rompa • Qualquer um dos fios esteja em curto na fonte • Qualquer um dos fios esteja em curto no terra Protocolo Um dos princípios do CAN é que mensagens transmitidas de qualquer nodo no barramento não contém nenhum endereço, nem de remetente e nem de destino. Ao invés disso, o conteúdo da mensagem é identificado por um identificador que é único através da rede. Todos os nodos na rede recebem a mensagem e cada um verifica o identificador único para determinar se o conteúdo da mensagem é de seu interesse. Se a mensagem for de interesse, ela é processada; caso contrário ela é ignorada. 13 Esta orientação a conteúdo das mensagens do CAN tem como consequência um alto grau de flexibilidade na configuração do sistema. Novos nodos que são puramente receptores podem ser adicionados a rede sem necessidade de maiores mudanças ao software e hardware existentes. Para delegação do envio de mensagem, o CAN usa o método conhecido como CSMA/CD, mas com a melhoria de que a detecção de colisão não interrompe o envio da mensagem prioritária. A prioridade da mensagem é determinada pelo valor numérico do seu identificador. Este valor é definido durante a fase inicial do desenvolvimento do sistema. O identificador com o valor numérico mais baixo tem a maior prioridade. Isto acontece pelo comportamento do barramento, que funciona como uma porta lógica AND, ou seja, enquanto algum nodo transmitir o valor lógico zero, o barramento terá este valor. No momento que o canal está disponível, os nodos que querem transmitir começam a transmissão do seu identificador, monitorando o barramento ao mesmo tempo. No momento em que ele envia o valor 1 mas o barramento continua 0, significa que outro nodo está transmitindo uma mensagem prioritária (valor do identificador é menor), logo este nodo interrompe sua transmissão, enquanto o nodo prioritário não precisa interromper sua transmissão. Esta estratégia oferece maior aproveitamento do barramento, baseado na necessidade dos nodos, não havendo interrupções de transmissão por colisão, o que não pode ser conseguido através de protocolos de tempo fixo como o Token Ring e nem com barramentos de alocação destrutiva como o Ethernet. Mas cuidado deve ser tomado no desenvolvimento da rede, pois nodos prioritários em excesso podem tomar a rede e não dar chance aos nodos menos prioritários. Com este comportamento, o CAN permite, por exemplo, que parâmetros que mudam mais frequentemente como as rotações por minuto (RPM) do motor tenham prioridade sobre valores que mudam menos frequentemente, como a temperatura do motor. Em um sistema CAN, assim como em outros procolos de rede, as mensagens são transmitidas em quadros de dados (Message Frames), que contém os dados sendo transmitidos por um nodo, além de dados de controle e checagem de erro. A última especificação do CAN definem duas versões, a versão 2.0A denominada o CAN padrão (Standard CAN) e a versão 2.0B, o CAN estendido (Extended CAN). Um esquema do formato do quadro usado pelo CAN 2.0A pode ser visto na figura 2.2. O quadro de dados do CAN padrão consiste de sete campos de bits: • Start of Frame (SOF): Indica o início do quadro. Único bit de valor zero. • Arbitration field: O identificador único, com 11 bits, mais um bit conhecido como Remote Transmission Request (RTR) bit. Este bit serve para diferenciar entre um quadro de envio de dados e um quadro de requisição. • Control Field: Contém 6 bits, sendo os 2 primeiros bits reservados para uso futuro e os outros 4 bits são o Data Length Code (DLC) que indica o tamanho em bytes do próximo campo, o Data field. • Data field: Os dados sendo enviados, podendo conter de 0 a 8 bytes. 14 Figura 2.2: Quadro de dados do protocolo CAN 2.0A • CRC field: Contém um código de verificação de redundância cíclica em 15 bits para verificação de erros no Data field e mais um bit delimitador. • ACKnowledge field: Campo usado para confirmação de recebimento pelos outros nodos. O primeiro bit é enviado como recessivo no barramento mas é logo sobrescrito por bit dominante pelos outros nodos para confirmar o recebimento. O outro bit é um delimitador recessivo. • End of frame field: Último campo, consistindo de 7 bits recessivos, indica o fim do quadro. O quadro de dados do CAN 2.0B pode ser visto na figura 2.3. O CAN 2.0B foi criado para prover compatibilidade com outras comunicações seriais. Para continuar compatível com o padrão 2.0A, o quadro de dados tomou uma forma estendida do quadro 2.0A. As diferenças estão no Arbitration field: Existem agora 2 identificadores. Um de 11 bits como no 2.0A e outro com 18 bits, formando o total de 29 bits para identificação. Entre estes campos, 2 bits são inseridos. O Substitute Remote Request (SRR) é um bit recessivo de forma que mensagens 2.0A que contenham o mesmo identificador de 11 bits tenham prioridade sobre as mensagens 2.0B. O Identifier Extension (IDE) é o bit que identifica uma mensagem 2.0B. Figura 2.3: Quadro de dados do protocolo CAN 2.0B A maioria dos controladores 2.0A transmitem e recebem somente mensagens de seu formato, mas alguns, conhecidos como 2.0B passivos, recebem mas igno15 ram mensagens 2.0B, possibilitando o funcionamento em conjunto com dispositivos 2.0B. Sincronização e tempo de bit Não existe um sinal de clock para sincronização dos nodos em uma rede CAN. Ainda assim, este é um protocolo que trabalha de forma síncrona. O tempo de transmissão de cada bit é controlado internamente em cada nodo. Cada nodo em uma rede CAN deve possuir um oscilador e uma taxa chamada Baud Rate Prescaler (BRP) que é programada no momento da instalação do nodo. A taxa do oscilador e o BRP multiplicados resultam numa unidade chamada time quanta. O tempo de bit no CAN é dividido em quatro segmentos de tempo, cada qual com seus valores em time quanta: 1. Sync-seg: Segmento para sincronia dos nodos no barramento. (1 time quanta) 2. Prop-Seg: Tempo para compensação de atrasos físicos. (1 a 8 time quantas) 3. Phase-seg1: É um segmento de buffer, que pode ser aumentado para ressincronização para compensar diferenças positivas na fase dos osciladores. (1 a 8 time quantas) 4. Phase-seg2: É um segmento de buffer, que pode ser diminuído para ressincronização para compensar diferenças negativas na fase dos osciladores. (Igual a Phase-seg1) A sincronia dos sinais ocorre durante a transmissão de cada bit, quando é verificado o tempo onde houve a mudança de sinal em Sync-seg. Dependendo do atraso que ocorre, Phase-seg1 e Phase-seg2 são alterados pelos nodos para a sincronia dos sinais. 2.3 Classe C Para aplicações que necessitam de comunicação em tempo-real e alta velocidade. Utilizadas principalmente nos primeiros dois domínios. Redes classe C como o CAN de alta velocidade (high-speed CAN) operam na faixa de 125kb/s a 1Mb/s. 2.3.1 High-speed CAN O protocolo CAN suporta taxas de transmissão entre 40Kbps (Classe B) e 1Mbps (Classe C) dependendo do meio físico e da distância entre os nodos. O protocolo funciona de forma semelhante, mudando somente a taxa de transmissão. Desta forma o protocolo pode ser usado transparentemente em ambas as classes (Pazul, 1999; Schofield, 1996). 16 2.3.2 TTP/C TTP/C é um protocolo determinístico desenvolvido pela Universidade de Vienna, derivado de dois projetos desta univerdade (X-by-write e TTA). Desde a conclusão de tais projetos, a especificação do protocolo foi transferida para a empresa TTTech (controlada por um consórcio de outras empresas com a Volkswagen, Audi e Honeywell) (Kopetz and Grunstidl, 1993). TTP/C é baseado em intervalos de tempo (TDMA), ao contrário do CAN, que é baseado em eventos (CSMA). Cada nodo é sincronizado por um clock comum. Todas transmissões são feitas em pontos específicos de tempo, definidos na fase de especificação do sistema. Como o TTP/C é um protocolo TDMA, a latência é determinística. Nenhum nodo pode monopolizar o meio de comunicação além do seu intervalo de tempo (TTA Group, 2004). 2.4 Classe D Estas redes operam em velocidades acima de 1Mbps e são utilizadas para aplicações multimídia. Exemplos são MOST e FlexRay. 2.4.1 MOST MOST é uma rede orientada a funcionalidades, multimídia e de alta velocidade. O protocolo define mecanismos para envio tanto de dados em pacotes como em fluxos (streaming), além de prover um completo framework de aplicação para controlar a interação entre os componentes da rede de forma estruturada. MOST suporta também diferentes taxas de velocidade e meios físicos (MOST Cooperation, 2008). Uma rede MOST consiste de até 64 nodos. É uma rede síncrona (TDMA), onde há um nodo mestre responsável pela sincronização dos demais. Desta forma, a banda alocada para conexões de streaming está sempre disponível e reservada para que não haja interrupções, colisões ou atrasos no envio dos dados, possibilitando alta qualidade de serviço e eficiente transmissão de áudio e vídeo. Tráfego da Internet ou informação de sistemas de navegação são tipicamente enviados em pacotes assíncronos, e distribuídos para diferentes nodos. Para suportar tais sinais, MOST define eficientes mecanismos para o envio e tratamento de tais pacotes além dos dados de controle e streaming. Porém, o envio destes dados se dá de forma separada dos dados de streaming, de forma que não haja interferência entre eles. Em suma, MOST é uma rede designada para transportar os diversos tipos de dados e sinais que tem origem em sistemas multimídia e de entretenimento. 2.4.2 FlexRay Flexray é um protocolo de comunicação em tempo real composto de partes estáticas e dinâmicas. Baseado em uma forma estendida de TDMA, o ciclo de comunicação deve ser definido juntamente com sua duração quando a rede é configurada. Este 17 elemento fundamental do esquema de acesso à mídia consiste de um segmento estático mandatório, um segmento dinâmico opcional e dois segmentos de protocolo chamados janela de símbolos (symbol window, responsável pelo envio de mensagens de sistema especiais como emphwake-up e emphstartup.), também opcional, seguidos de um tempo de inatividade mandatório que marca o fim do envio de dados (FlexRay Consortium, 2005). Na figura 2.4 podemos ver um esquema do ciclo de comunicação. Figura 2.4: Ciclo de comunicação do protocolo FlexRay No segmento estático, o tempo determinístico de comunicação é responsável por requisitos importantes como a latência, utilizando TDMA com intervalos de tempo de mesmo tamanho, com cada ECU possuindo seu intervalo de tempo exclusivo, certificando-se da transmissão de seus dados sem interrupções. No segmento dinâmico é onde comunicações baseadas em eventos são feitas. A estratégia usada é uma extensão do TDMA, denominada FTDMA (FlexRay timedivision multiple access), criando um padrão de acesso por demanda ainda baseado em tempo para comunicações dinâmicas. A estratégia é baseada em miniintervalos de tempo, que basicamente dão a chance de algum ECU requisitar um envio. Quando há uma requisição, um mini-intervalo é expandido para um intervalo padrão para uso do ECU. Caso contrário, mini-intervalos continuam sendo enviados. 18 Capítulo 3 Aquisição de dados O básico de um sistema de telemetria é a aquisição dos dados. Felizmente os carros hoje possuem diversas ECUs que fazem medições dos parâmetros funcionais do veículo. Estas unidades eletrônicas formam o que se chama de sistema de diagnóstico a bordo (On-board diagnostics, mais conhecido pela sigla OBD). 3.1 OBD A sigla OBD vem sido usada há muito tempo, quando começaram a surgir equipamentos de diagnósticos em veículos. Os primeiros sistemas consistiam somente de uma luz indicadora de problema no motor ou painel (MIL - Malfunction indicator light) quando um problema era detectado. Implementações mais modernas de OBDs usam uma porta padrão de comunicação digital para prover informações em tempo real sobre o funcionamento do veículo. Há também códigos padronizados de diagnóstico de problemas (DTC - diagnostic trouble codes) que permitem que problemas sejam detectados e resolvidos rapidamente. Um outro motivador para a implantação de um sistema OBD padronizado, como será observado a seguir, é a medição de emissão de poluentes do carro. Um sistema de medição padrão torna muito mais fácil e confiável a medição da emissão dos veículos. 3.1.1 História • 1975: Computadores embarcados começam a aparecer nos veículos civis com o Datsun 280z, motivado principalmente pela necessidade de ajuste em tempo real de sistemas de injeção eletrônica. Com isso, começam a aparecer as primeiras implementações de OBD, mas sem um padrão definido do quê e como é feita a monitoração. • 1980: A General Motors implementa um protocolo proprietário chamado ALDL, que se comunica a 160 baud e monitora poucos sistemas do veículo. • 1986: Uma versão melhorada do ALDL é criada, que se comunica a 8192 bauds. O protocolo é definido no padrão GM XDE-5024B. 19 • 1987: A California Air Resources Board - CARB, agência do estado norteamericano que define políticas em prol da preservação da qualidade do ar, ergue uma norma de que todos os veículos vendidos no estado a partir de 1988 tenham um sistema básico OBD implantado. Não foi definido um padrão para conexão nem protocolo de dados. • 1988: A sociedade de engenheiros automotivos SAE (Society of Automotive Engineers) recomenda um padrão para conectores e sinais de diagnóstico (Padrão hoje conhecido como OBD-I). • 1994: A CARB lança a especificação OBD-II e ergue a norma de que deve ser adotado em todos os carros vendidos na Califórnia a partir de 1996. Os conectores e protocolos sugeridos pela SAE são incorporados nesta especificação. • 1996: O OBD-II se torna mandatório em todos os carros vendidos nos Estados Unidos. • 2001: A União Europeia especifica o EOBD (padrão baseado no OBD-II) para todos os veículos vendidos na União Europeia. • 2004: O Conselho Nacional do Meio Ambiente Ű CONAMA, inspirado nas normas internacionais estabelecidas, lança a resolução 354 de 13 de dezembro de 2004, que define o OBDBr-1 e OBDBr-2, sistema OBD a ser implantado nos veículos brasileiros. A resolução se apoia nas normas internacionais já publicadas para o conector e define quais as medições que deverão ser feitas em cada versão. • 2007: 40% dos carros brasileiros devem implantar o OBDBr-1. • 2008: A partir deste ano, todos os carros vendidos nos Estados Unidos devem implentar o padrão de sinalização ISO 15765-4 (baseado no protocolo CAN Controller Area Network). • 2009: 100% dos carros brasileiros devem implantar o OBDBr-1. 3.1.2 Padrões OBDBr-1 e OBDBr-2 A CONAMA, com a resolução 354 de 13 de dezembro de 2004, definiu o padrão de sistemas de diagnose para os veículos brasileiros. O padrão foi baseado no já existente e implantado OBD-II. A principal tarefa da resolução foi definir os parâmetros a serem medidos e prazo para implantação pelas montadoras (CONAMA, 2006). Parâmetros do OBDBr-1, implantando em 40% dos automóveis em 2007, 60% em 2008 e 100% em 2009: • Sensor Pressão Absoluta ou Fluxo de Ar • Sensor Posição da Borboleta • Sensor de Temperatura de Arrefecimento • Sensor Temperatura de Ar 20 • Sensor Oxigênio (somente o sensor pré-catalisador) • Sensor de Velocidade do Veículo • Sensor de Posição do Eixo Comando de Válvulas • Sensor de Posição do Virabrequim • Sistemas de Re-circulação dos Gases de Escape (EGR) • Sensor para Detecção de Detonação • Válvulas Injetoras • Sistema de Ignição • Módulo Controle Eletrônico do motor • Lâmpada Indicadora de Mau Funcionamento (LIM) • Outros componentes que o fabricante julgue relevantes para a correta avaliação do funcionamento do veículo e controle de emissões de poluentes. Complementarmente às funções e características do Sistema OBDBr-1, o sistema OBDBr-2 deve detectar e registrar a existência de falhas de combustão, deterioração do(s) sensor(es) de oxigênio primário(s) e eficiência de conversão do catalisador que acarretem aumento de emissões, também apresentar características mínimas para a detecção de falhas nos seguintes componentes: • Sensores de Oxigênio (pré e pós-catalisador) • Válvula de Controle da Purga do Cânister O sistema OBDBr-2 começará a ser implantando em 2010. 3.1.3 Padrão OBD-II O padrão difundido para quase a totalidade dos veículos para monitoramento e diagnóstico eletrônico é o OBD-II. Este padrão define um conector de diagnóstico padrão e sua pinagem, os protocolos de sinalização disponíveis e o formato das mensagens. Há também a definição de alguns parâmetros que devem ser monitorados e como devem ser codificados, além dos códigos de detecção de problemas, os DTCs. Graças a este padrão, é possível a construção de dispositivos que sejam capazes de diagnosticar qualquer veículo que o implemente. Conector OBD-II A padrão OBD-II especifica uma interface de hardware - o conector fêmea de 16 pinos (2x8) J1962 (Dzhelekarski and Alexiev, 2005a). Este conector deve aparecer no compartimento de passageiros, perto do console central do veículo, do lado do motorista. A especificação do J1962 feita pela SAE define as pinagens do conector como: 21 Figura 3.1: Esquema do conector OBD-II 1. 2. Linha de barramento positiva do SAE-J1850 3. Ford DCL positivo 4. Terra da bateria 5. Terra de sinal 6. CAN alta voltagem (ISO 15765-4, SAE J2284) 7. Linha K dos ISO 9141-2, 14230-4 8. 9. 10. Negativo do SAE J1850 11. Ford DCL negativo 12. 13. 14. CAN baixa voltagem 15. Linha L dos ISO 9141-2, 14230-4 16. Alimentação da bateria A implementação dos pinos não especificados está a critério do fabricante. Protocolos Cinco protocolos são definidos no padrão OBD-II, como pode ser notado pela pinagem. Um veículo normalmente implementa somente um deles. Estes protocolos eram e ainda são os mais usados na época da definição do padrão. Logo, o dispositivo que fizer a leitura dos dados deve estar preparado para lidar com todos os 5 protocolos se deseja ser totalmente compatível com OBD-II (Dzhelekarski and Alexiev, 2005b). • SAE J1850 PWM 22 • SAE J1850 VPW • ISO 9141-2 • ISO 14230 KWP2000 (Keyword Protocol 2000) • ISO 15765 CAN (Controller Area Network) Estes protocolos são abordados com mais detalhes na seção 2.2. Interface OBD x computador Já existem diversas interfaces implementadas para conexão do OBD-II com computadores. Normalmente esta conexão é feita pela porta serial RS-232, ou, mais recentemente, a USB. A empresa ELM electronics criou o que é hoje conhecido como o estado da arte na interface de computadores com o OBD: O chip ELM 327 (ELM Electronics, 2009). Com este chip conectado a uma interface serial, é possível acessar dados OBD de forma padronizada, sem diferenças no protocolo implementado pelo carro. O chip é responsável por interpretar o protocolo utilizado pelo carro e transformar os dados. A comunicação com o ELM 327 é feita através de comandos AT, semelhante a um modem, o que facilita a implementação de sistemas para recuperação dos dados necessários. Hoje já existem versões semelhantes inspiradas no ELM 327, implementando o mesmo padrão, de design aberto e fácil construção. Por isto este será o modelo de conector usado no projeto. Um dos modelos é mostrado abaixo, criado por Alex Sidorenko, que disponibilizou o circuito, as peças e o firmware para o microcontrolador PIC18F2455 em seu website (Sidorenko, 2009). Figura 3.2: Interface OBD x USB de Alex Sidorenko Dados mensurados O padrão OBD definido pela SAE estabelece os dados que podem ser disponibilizados pela porta OBD aos equipamentos de diagnóstico. A tabela 3.1 mostra uma lista dos dados, seus códigos identificadores (PID - Parameter ID) que são utilizados pelas ferramentas de diagnóstico para fazer a consulta, número de bytes e a unidade de medida que representam. 23 Figura 3.3: Esquema elétrico da interface OBD x USB de Alex Sidorenko 24 Tabela 3.1: Dados OBD-II PID 0 1 2 3 4 5 6 7 8 9 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 Bytes 4 4 8 2 1 1 1 1 1 1 1 1 2 1 1 1 2 1 1 1 2 2 2 2 2 2 2 2 1 1 1 2 4 2 2 2 4 4 4 4 4 Descrição Unidade PIDs supported [01 - 20] Monitor status since DTCs cleared. Freeze DTC Fuel system status Calculated engine load value % ◦ Engine coolant temperature C Short term fuel % trim Bank 1 % Long term fuel % trim Bank 1 % Short term fuel % trim Bank 2 % Long term fuel % trim Bank 2 % Fuel pressure kPa (gauge) Intake manifold absolute pressure kPa (absolute) Engine RPM rpm Vehicle speed km/h ◦ Timing advance relative to #1 cylinder ◦ Intake air temperature C MAF air flow rate g/s Throttle position % Commanded secondary air status Oxygen sensors present Bank 1 Sensor 1: Oxygen sensor Volts % Bank 1 Sensor 2: Oxygen sensor Volts % Bank 1 Sensor 3: Oxygen sensor Volts % Bank 1 Sensor 4: Oxygen sensor Volts % Bank 2 Sensor 1: Oxygen sensor Volts % Bank 2 Sensor 2: Oxygen sensor Volts % Bank 2 Sensor 3: Oxygen sensor Volts % Bank 2 Sensor 4: Oxygen sensor Volts % OBD standards this vehicle conforms to Oxygen sensors present Auxiliary input status Run time since engine start seconds PIDs supported 21-40 Distance traveled with MIL on km Fuel Rail Pressure (relative to manifold vacuum) kPa Fuel Rail Pressure (diesel) kPa (gauge) O2S1_WR_lambda(1): Equivalence Ratio Voltage N/A V O2S2_WR_lambda(1): Equivalence Ratio Voltage N/A V O2S3_WR_lambda(1): Equivalence Ratio Voltage N/A V O2S4_WR_lambda(1): Equivalence Ratio Voltage N/A V O2S5_WR_lambda(1): Equivalence Ratio Voltage N/A V Continua na próxima página. . . 25 PID 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 51 52 100 101 Tabela 3.1 – continuação Bytes Descrição Unidade 4 O2S6_WR_lambda(1): Equivalence Ratio Voltage N/A V 4 O2S7_WR_lambda(1): Equivalence Ratio Voltage N/A V 4 O2S8_WR_lambda(1): Equivalence Ratio Voltage N/A V 1 Commanded EGR % 1 EGR Error % 1 Commanded evaporative purge % 1 Fuel Level Input % 1 # of warm-ups since codes cleared N/A 2 Distance traveled since codes cleared km 2 Evap. System Vapor Pressure Pa 1 Barometric pressure kPa (Absolute) 4 O2S1_WR_lambda(1): Equivalence Ratio Current N/A mA 4 O2S2_WR_lambda(1): Equivalence Ratio Current N/A mA 4 O2S3_WR_lambda(1): Equivalence Ratio Current N/A mA 4 O2S4_WR_lambda(1): Equivalence Ratio Current N/A mA 4 O2S5_WR_lambda(1): Equivalence Ratio Current N/A mA 4 O2S6_WR_lambda(1): Equivalence Ratio Current N/A mA 4 O2S7_WR_lambda(1): Equivalence Ratio Current N/A mA 4 O2S8_WR_lambda(1): Equivalence Ratio Current N/A mA ◦ 2 Catalyst Temperature Bank 1 Sensor 1 C ◦ C 2 Catalyst Temperature Bank 2 Sensor 1 ◦ 2 Catalyst Temperature Bank 1 Sensor 2 C ◦ 2 Catalyst Temperature Bank 2 Sensor 2 C 4 PIDs supported 41-60 4 Monitor status this drive cycle 2 Control module voltage V 2 Absolute load value % 2 Command equivalence ratio N/A 1 Relative throttle position % ◦ 1 Ambient air temperature C 1 Absolute throttle position B % 1 Absolute throttle position C % 1 Accelerator pedal position D % 1 Accelerator pedal position E % 1 Accelerator pedal position F % 1 Commanded throttle actuator % 2 Time run with MIL on minutes 2 Time since trouble codes cleared minutes 1 Fuel Type 1 Ethanol fuel% % OBD Monitor IDs supported (01−20) O2 Sensor Monitor Bank 1 Sensor 1 Volts Continua na próxima página. . . 26 Tabela 3.1 – continuação PID Bytes Descrição 102 O2 Sensor Monitor Bank 1 Sensor 2 103 O2 Sensor Monitor Bank 1 Sensor 3 104 O2 Sensor Monitor Bank 1 Sensor 4 105 O2 Sensor Monitor Bank 2 Sensor 1 106 O2 Sensor Monitor Bank 2 Sensor 2 107 O2 Sensor Monitor Bank 2 Sensor 3 108 O2 Sensor Monitor Bank 2 Sensor 4 109 O2 Sensor Monitor Bank 3 Sensor 1 010A O2 Sensor Monitor Bank 3 Sensor 2 010B O2 Sensor Monitor Bank 3 Sensor 3 010C O2 Sensor Monitor Bank 3 Sensor 4 010D O2 Sensor Monitor Bank 4 Sensor 1 010E O2 Sensor Monitor Bank 4 Sensor 2 010F O2 Sensor Monitor Bank 4 Sensor 3 110 O2 Sensor Monitor Bank 4 Sensor 4 201 O2 Sensor Monitor Bank 1 Sensor 1 202 O2 Sensor Monitor Bank 1 Sensor 2 203 O2 Sensor Monitor Bank 1 Sensor 3 204 O2 Sensor Monitor Bank 1 Sensor 4 205 O2 Sensor Monitor Bank 2 Sensor 1 206 O2 Sensor Monitor Bank 2 Sensor 2 207 O2 Sensor Monitor Bank 2 Sensor 3 208 O2 Sensor Monitor Bank 2 Sensor 4 209 O2 Sensor Monitor Bank 3 Sensor 1 020A O2 Sensor Monitor Bank 3 Sensor 2 020B O2 Sensor Monitor Bank 3 Sensor 3 020C O2 Sensor Monitor Bank 3 Sensor 4 020D O2 Sensor Monitor Bank 4 Sensor 1 020E O2 Sensor Monitor Bank 4 Sensor 2 020F O2 Sensor Monitor Bank 4 Sensor 3 210 O2 Sensor Monitor Bank 4 Sensor 4 0 4 mode 9 supported PIDs 01 to 20 2 5x5 Vehicle identification number (VIN) 4 varies calibration ID 27 Unidade Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Volts Capítulo 4 Telefonia móvel Com o avanço da tecnologia de telefonia móvel, cada vez mais os aparelhos portáteis ficam poderosos, portando sistemas computacionais complexos e capacidades de conectividade cada vez mais rápidas e simples, assim como cresce os recursos eletrônicos nos automóveis. Mas ainda existe uma lacuna a ser preenchida que é a integração desses dois mundos, criando recursos e facilidades para o usuário do veículo e de tecnologias móveis. Estudos para a criação de aparelhos de transmissão e recepção por células, os aparelhos celulares, começaram a ser feitos em meados de 1950. Antes, a telefonia dependia de conexão direta cabeada dos aparelhos até uma central de comunicação. Coincidentemente, a ideia inicial do uso desta forma de comunicação era para o uso em automóveis. A primeira rede de telefonia celular era conhecida como AMPS (Advanced Mobile Phone Server) e foi lançada em 1983. Logo em 1987, estas redes começaram a apresentar grande demanda e consequentemente, congestionamento. Para aumentar a eficiência do serviço, novas tecnologias foram implantadas, com o TDMA (Time Division Multiple Access), CDMA (Code Division Multiple Access) e GSM (Global System for Mobile Communications). O fenômeno da tecnologia de telefonia móvel impactou o mundo como poucas tecnologias modernas conseguiram. Hoje, cerca de 81% da população brasileira possui celular (Anatel, 2009). Por já estar profundamente inserida no cotidiano das pessoas, a telefonia celular tem sido uma plataforma constantemente visada para integração de serviços e recursos. Os bancos, por exemplo, disponibilizam mensagens aos clientes com confirmações de movimentações, sistemas para controle da conta por telefone celular, entre outros recursos. Nada mais óbvio para um sistema embarcado automotivo também fazer uso desta tecnologia, utilizando-a tanto como meio de comunicação como meio de interação com seu proprietário. 4.1 GSM Muitos protocolos e padrões surgiram durante a criação da telefonia celular, mas nenhum conseguiu a ampla aceitação que hoje tem o GSM, sendo usado em cerca de 80% das operadoras de telefonia celular do mundo (GSM Association, 2009). 28 O GSM foi criado na Europa em 1990, onde antes cada país tinha o seu próprio sistema analógico de telefonia celular, impedindo a compatibilidade entre as redes e seus aparelhos. A ideia do novo padrão era prover interconexão não só entre as redes de diferentes países, mas prover integração com outros sistemas. Por isso o padrão analógico foi abandonado em favor do padrão digital. Esta característica possibilitou a construção de recursos digitais com o SMS e o GPRS (Scourias, 1997). 4.1.1 SMS Com o SMS (Short Message System), usuários de redes GSM podem trocar mensagens alfanuméricas de até 160 caracteres. As mensagens podem ser trocadas entre redes, em qualquer lugar do mundo, e são recebidas em segundos. A idéia original era ser um simples sistema de notificação a usuários de uso da operadora, como avisos de recados na caixa de mensagens, mas acabou tornando-se extremamente popular e usado pela maioria dos usuário de telefonia móvel (Peersman and Cvetkovic, 2000). A popularidade do SMS se deve ao fato de que pode ser transmitida a qualquer momento, mesmo quando o destinatário está indisponível para a recepção. A operadora espera até o aparelho de destino estiver ligado e em área de cobertura para fazer o envio. Assim como um e-mail, a mensagem quando é enviada fica guardada no destino e pode ser acessada a qualquer momento. Vários sistemas já fazem uso de SMS em seus serviços. Operadoras de cartão de crédito enviam confirmações de compra por SMS, lojas online notificam usuários quando suas compras são enviadas ou quando há algum problema na cobrança, entre muitos outros usos. O SMS é implementado em uma rede GSM através do uso de MSC (Message Service Center). Seu funcionamento é semelhante a uma caixa de correio eletrônico, onde as mensagens são organizadas por destinatário e são remetidas para a rede de destino. Um exemplo de rede GSM com servidores MSC pode ser vista na figura 4.1. 4.1.2 GPRS O GPRS (General packet radio service) é um protocolo que foi incorporado ao GSM para prover serviço de transmissão de pacotes. O GPRS possibilita que aparelhos da rede GSM interajam com outras redes digitais, mais notavelmente a Internet. A taxa de transmissão é entre 56 e 114 kbps (Scourias, 1997). Este serviço aumentou exponencialmente a quantidade de recursos disponíveis nos aparelhos celulares. Telefones agora acessam páginas de Internet, atualizamse e carregam conteúdos como músicas, jogos, vídeos e imagens. A arquitetura GPRS funciona sobre a GSM, adicionando novos nós na rede chamados GSN (GPRS Support Node) que fazem o roteamento dos pacotes de dados entre as redes interna e externa, de forma muito semelhante à arquitetura SMS. Podemos ver esta arquitetura ilustrada, juntamente com a arquitetura SMS, na figura 4.1. Os principais elementos mostrados são: • MS (Mobile Station): O dispositivo móvel sendo conectado. 29 Figura 4.1: Uma rede GSM com nós SMS e GPRS (Junior, 2005) • BTS (Base Transceiver Station): Transceptores e antenas, responsáveis pela transmissão dos sinais de rádio com o MS. • BSC (Base Station Controller): Estação de controle das BTS. • SGSN (Serving GPRS Support Node): Responsável pela localização do dispositivo móvel e roteamento dos pacotes. • GGSN (Gateway GPRS Support Node): Interface com outras redes digitais, como a Internet. 4.1.3 EDGE e UMTS Estas tecnologias são evoluções do GPRS. Foram desenvolvidas com a principal finalidade de prover maior taxa de transmissão de dados. O EDGE (Enhanced Data rates for GSM Evolution) provê taxas de transmissão que variam entre 236,8 e 473,6 kbps, quatro vezes maior que o GPRS. O EDGE, também chamado de EGPRS (Enhanced GPRS), trabalha de forma similar ao GPRS, podendo coexistir em uma mesma rede. Os GSN devem ser atualizados para incorporar as novas tecnologias de transmissão adotadas pelo EDGE, mas as diferenças se encerram aqui. Logo, a rede pode ser atualizada gradualmente, sem impacto no serviço já existente. A tecnologia UMTS (Universal Mobile Telecommunications System), que faz parte das evoluções do GSM denominadas 3G (terceira geração), promete teóricos 21 Mbps, mas por enquanto suas implementações suportam até 7.2 Mbps. A 30 Figura 4.2: Placa PCMCIA da VIVO para acesso a rede GSM 3G migração para este padrão não é tão transparente quanto a EDGE, necessitando a troca de várias camadas de comunicação da rede, mas ainda assim os dois modos de transmissão ainda podem coexistir (Richardson, 2000). 4.1.4 Acesso à Internet Móvel A evolução das tecnologias móveis foi cada vez mais aproximando os aparelhos celulares da Internet. Era só uma questão de tempo até que os aparelhos celulares começassem a ser usados como porta de entrada a Internet por computadores portáteis. No começo era necessário o uso de um telefone celular conectado ao computador para acesso à Internet. Este acesso era complicado, dependendo de drivers específicos para o telefone e sistema operacional em uso (Junior, 2005). Hoje já estão difundidos aparelhos específicos para esta ligação, os chamados Modens 3G. São aparelho celulares simplificados, com baixo consumo de energia, podendo ser energizados pela porta USB ou interface PCMCIA. Notebooks já estão sendo construídos com esta interface embutida, facilitando ainda mais o acesso. Nas figuras 4.2 e 4.3 temos exemplos de equipamentos voltados para este acesso. Este tipo de acesso permite, além de conexão à Internet, também o envio de SMS. Estas características satisfazem as exigências do sistema de telemetria quanto a telecomunicações. Considerando a disponibilidade de conexão USB na Beagle Board (Seção 2.2) , esta será a interface usada para o projeto. 31 Figura 4.3: Interface USB GSM 3G. 32 Capítulo 5 Arquitetura do Sistema Para o desenvolvimento do sistema, é necessário definir sua arquitetura. O projeto Karmonitor define a plataforma para desenvolvimento dos sistemas embarcados. 5.1 Hardware Por se tratar de um sistema embarcado de alta complexidade, um hardware poderoso e ao mesmo tempo portátil deve ser usado. A proposta do projeto Karmonitor é especificar e construir um hardware customizado que será o computador a bordo do veículo. Mas como protótipo, a equipe do projeto Karmonitor definiu como plataforma inicial de desenvolvimento do sistema uma placa de design aberto, expansível, de alta performance e baixo custo que está acolhendo uma crescente comunidade de desenvolvedores interessados, a Beagle Board. A Beagle Board possui um processador ARM da Texas Instrument, o OMAP3530, capaz de rodar a 600MHz com um cache L2 de 256kb e memória RAM de 256Mb. Possui somente funcionalidades de áudio e vídeo integrados. O poder da Beagle Board está justamente na sua falta de componentes integrados, que é compensada pela sua alta expansibilidade. Possui interface USB, MMC+/SD/SDIO, RS-232 e J-TAG. Já existem diversos periféricos testados para expandir as funcionalidades da Beagle Board. Outra característica importante é o baixo consumo de energia, podendo ser alimentada pela porta USB ou por uma fonte DC de 5v, o que facilita sua instalação em um veículo. 5.2 Sistema Operacional O sistema operacional que será usado na Beagle Board será uma distribuição de Linux para sistemas embarcados. A escolha deve-se a diversos motivos. Um é o fato de ser o sistema operacional mais utilizado em conjunto com a Beagle Board. Logo, já possui amplo suporte e documentação provido pela comunidade. Por ser um sistema de código aberto, possibilita customizações de acordo com a necessidade do projeto. 33 Figura 5.1: A Beagle Board com seus principais componentes destacados Outras características do Linux que justificam a escolha é sua modularização, que é importante para sistemas embarcados, permitindo que somente os módulos necessários sejam carregados no kernel, economizando recursos, e o fato de ser um sistema amplamente usado e divulgado, logo já existe muito software disponível para o sistema. A distribuição escolhida pela equipe é a distribuição Angstrom, especialmente voltada para sistemas embarcados. 5.2.1 Linux Kernel de código aberto escrito por Linus Torvalds em meados de 1991. A princípio foi desenvolvido somente como um hobby, para ser uma alternativa ao MINIX, escrito por Andrew Tanenbaum em 1987 como projeto acadêmico, pois tinha uma licença muito restritiva. 34 O Linux foi desenvolvido como um kernel monolítico, que controla a execução dos processos, acesso a rede, sistema de arquivos e periféricos. Os drivers dos dispositivos da máquina são integrados ao kernel através de módulos. Acabou se tornado muito popular pela comunidade e com uma equipe constante de desenvolvedores acabou se tornando um kernel muito abrangente, suportando diversas arquiteturas, como laptops e desktops até celulares e supercomputadores. Vários sistemas operacionais baseados no Linux surgem a cada dia, cada qual com suas características específicas para atender necessidades diferentes. Estes sistemas são chamados de distribuições Linux, ou distros. 5.2.2 Angstrom O Angstrom nasceu da colaboração de integrantes de outras distribuições de Linux voltadas para sistemas embarcados, os OpenEmbedded, OpenZaurus e OpenSIMPad. O objetivo desta comunidade é criar uma distribuição Linux especialmente voltada para sistemas embarcados baseados em processadores ARM. Sua principal característica é a escalabilidade, podendo ocupar meros 4Mb, ou gigas de armazenamento. A escalabilidade é alcançada através de pacotes de software que permitem que os desenvolvedores acrescentem as funcionalidades a medida que são necessárias. O gerenciador de pacotes utilizado no Angstrom é o ipkg (Itsy Package Management System), especialmente voltado para sistemas embarcados por ocupar pouco espaço de armazenamento. É baseado no gerenciador de pacotes do Debian, o dpkg. 5.3 Software Para a realização da telemetria, serão desenvolvidos e/ou empregados softwares para realizar cada etapa do processo. 5.3.1 Medição A primeira etapa do processo de telemetria, a medição dos dados, deve ser realizada por um software que seja capaz de utilizar a interface serial criada pelo conector USB x OBD, levantar os dados e armazená-los localmente. Já existem softwares desenvolvidos com este fim, mas a maioria é composta de software proprietário, de código fechado, e dependente de plataforma. Porém, existe um programa que não se encaixa nesta maioria, chamado obdgpslogger, desenvolvido por Gary Briggs (Briggs, 2009). A proposta do obdgpslogger é ser um gravador de logs de dados funcionais de automóveis juntamente com coordenadas GPS, sendo assim possível reconstruir o trajeto de um veículo e monitorar seus dados funcionais durante o percurso. O obdgpslogger foi escrito na linguagem C sob a licença GPL, tendo seu código fonte disponibilizado. Foi totalmente escrito para ser compatível com sistemas POSIX, e desenvolvido em módulos, separados por funcionalidades. Os seguintes módulos são os principais para o objetivo deste projeto, entre outros desenvolvidos. 35 • obdgpslogger: O módulo principal, responsável pela comunicação serial e gravação dos dados. • obdsim: Simulador OBD, que possibilita testes longe de um automóvel, simulando uma porta serial ligada ao sistema OBD. • obd2csv: Conversor dos dados gravados pelo logger para o formato CSV. O obdgpslogger já foi implementado em diversos sistemas e arquiteturas diferentes, inclusive testes foram feitos no hardware e sistema operacional definidos neste projeto, executando normalmente. Por atender as necessidades do projeto, este software será usado na medição dos dados OBD do automóvel. 5.3.2 Cliente A parte do cliente será um software que executará a bordo do veículo, no sistema embarcado. Logo deverá ser executado em um ambiente com poucos recursos, devendo acessar os dados gerados pelo obdgpslogger, convertê-los e enviá-los pela conexão com a Internet móvel. Considerando a arquitetura do sistema, o sucesso da execução do obdgpslogger e a necessidade de ambos executarem simultaneamente, a parte do cliente será desenvolvida de forma semelhante, na linguagem C, fazendo chamadas aos módulos do obdgpslogger quando necessário. As tarefas do cliente resumem-se a: • Verificar e estabelecer a conexão com o servidor. • Utilizar o módulo obd2csv para fazer a conversão dos dados e salvá-los em arquivos em local apropriado. • Envio dos dados ao servidor. • Limpeza dos dados medidos anteriormente após a conversão, considerando que este é um sistema embarcado com pouco espaço para armazenamento. Para o acesso aos dados gerados pelo obdgpslogger, será usada a mesma API de código aberto, o SQLite, uma API que permite a criação de bancos de dados simples e compactos. Como parte do processo de desenvolvimento, foi desenhado um fluxograma para facilitar a visualização do processo de execução do cliente (Figura 5.2). O intervalo de cinco minutos entre cada envio foi definido arbitrariamente, sendo necessários testes para verificar se o acumulo de dados neste intervalo não será grande demais para fazer o envio, considerando a largura de banda limitada das conexões celulares, ou se esse intervalo de tempo não é curto demais, sobrecarregando o servidor com conexões desnecessárias. Estes dados são avaliados no capítulo 6. O sistema prevê a indisponibilidade de conexão com o servidor, considerando a natureza de sua conexão. O sistema somente fará a conversão dos dados quando o servidor for contatado. Sendo assim, é possível que haja acúmulo excessivo de dados em caso de um período muito longo de ausência de conexão (por exemplo, em 36 Figura 5.2: Fluxograma do programa cliente 37 percursos intermunicipais, longe do serviço das redes celulares). Para isso, foi feito cálculo, considerando a taxa de medição de dados pelo obdgpslogger, sendo possível prever o tamanho de armazenamento necessário para armazenar a quantidade de dados gerados enquanto não se obtém uma conexão com o servidor. Estes dados são levantados no capítulo 6. 5.3.3 Servidor O processo servidor será um programa executando em alguma máquina conectada a Internet, esperando pela conexão de processos clientes rodando nos veículos monitorados. Este servidor não tem limitações como o processo cliente, logo pode ser implementado em qualquer tipo de sistema que suporte a tarefa. Considerando a possibilidade de alto número de veículos sendo monitorados, um computador de alta capacidade de processamento e armazenamento é recomendado. Para obter portabilidade, usou-se a linguagem Java para o desenvolvimento do servidor, e um banco de dados PostgreSQL para o armazenamento dos dados. Programa As tarefas do programa servidor: • Receber conexões de um cliente. • Validar se o veículo está registrado. • Enviar parâmetros de conexão/comandos. • Receber arquivos CSV compactados e descompactá-los. • Ler os arquivos e armazenar os dados no banco de dados. A figura 5.3 é um fluxograma do funcionamento do servidor. Como mostrado, este é um programa multithread, ou seja que cria várias threads que são executadas paralelamente. Isto se deve ao fato de que ele deve ser capaz de tratar diversas conexões simultaneamente. Para o desenvolvimento do servidor foi utilizada, além das bibliotecas básicas do Java, a biblioteca OpenCSV (Smith et al., 2009), biblioteca Java de código aberto para manipulação de arquivos CSV. O diagrama de classes para o programa pode ser visto na figura 5.4. No pacote principal estão os processos Main, que somente realiza, a cada conexão, a criação de thread representada pela classe ServerThread, que faz o trabalho de comunicação com o cliente através de sockets. No pacote db estão as classes responsáveis pelo acesso ao banco de dados, os DAO (Data Access Objects), e no pacote beans está o objeto que representa um veículo. Não foi criado objeto para representar os dados OBD pois os dados são transferidos diretamente do arquivo CSV para o procedimento de gravação do banco na classe ObdDao. 38 Figura 5.3: Fluxograma do programa servidor 39 Figura 5.4: Diagrama de classes do programa servidor 40 Coluna id license description Tipo integer character(7) text Obs. Campo sequencial, chave primária Placa do carro, chave única Descrição, texto livre Tabela 5.1: Estrutura da tabela de veículos Coluna id_vehicle time gps_lat gps_lon gps_alt dtcfrzf fuelsys load_pct temp Tipo integer numeric numeric numeric numeric integer integer numeric(9,6) integer Obs. Chave estrangeira da tabela de veículos, e chave primária. Timestamp do momento da medição, chave primária. Latitude GPS Longitude GPS Altitude GPS ... Tabela 5.2: Estrutura parcial da tabela de dados OBD Banco de dados O banco de dados utilizado para o desenvolvimento é o PostgreSQL, mas nada impede que outros bancos que suportem drivers Java JDBC sejam utilizados. O banco é composto somente de duas tabelas, dispensando um diagrama entidade relacionamento. As tabelas são a tabela de cadastro de veículos e a tabela de dados OBD. Suas estruturas são mostradas respectivamente nas tabelas 5.1 e 5.2. O script SQL de criação delas pode ser visto no anexo III. A tabela de dados OBD possui campos para descrição de todos os dados possíveis de serem monitorados pelo padrão OBD, como descrito na tabela 3.1, já convertidos para o valor numérico correspondente. Mas raramente os veículos suportam todos os campos, deixando os campos que não suporta com o valor nulo. Isto acarreta um certo desperdício de armazenamento, que poderia ser evitado pela criação de tabelas relacionais separadas por cada campo, e uma tabela de registro de campos suportados por cada veículo. Isto, porém, acarretaria em uma maior necessidade de processamento por parte do processo servidor ao receber os dados, e muito mais acessos ao banco de dados, além de uma quantidade muito maior de tabelas no banco de dados. Considerando a gravação de 300 registros no banco de dados com 10 colunas, ao invés de 300 comandos SQL para gravar as linhas, seriam necessários 300 ∗ 10 = 3000 comandos para gravação dos dados. Considerando o custo cada vez menor para armazenamento, a economia em processamento e acesso ao banco tem impacto muito maior do que o desperdício de armazenamento. 41 Comando CMD_SEND_LICENSE Objetivo Requisita do cliente o envio da placa do carro CMD_RECV_BUFFERSZ Avisa para o cliente receber inteiro que representa o tamanho do buffer para troca de arquivos (B) CMD_SEND_NUMFILES Requisita do cliente o número de arquivos que serão enviados (N ) CMD_SEND_FILES Requisita do cliente o envio dos arquivos CMD_RECV_SLEEPTM CMD_BYE Altera tempo de espera do cliente entre as conexões. Informa ao cliente o fim da transmissão Resposta Cliente envia string de 7 caracteres Cliente recebe inteiro Cliente envia inteiro Para cada arquivo, é enviado seu tamanho (T ), e em seguida T /B pacotes de B bytes Cliente recebe inteiro Conexão fechada Tabela 5.3: Comandos que o servidor pode enviar ao cliente 5.3.4 Protocolo de comunicação A conexão estabelecida entre o cliente o servidor é feita através de Sockets, ou seja, utilizando o protocolo TCP sobre IP, o que significa que as mensagens são recebidas sincronizadamente e com checagem de erro. A comunicação entre os processos se dá na forma de comandos enviados pelo servidor. A conexão é estabelecida pelo cliente, mas este então recebe os comandos que são enviados do servidor. Isto permite que alterações no comportamento do sistema sejam feitos somente pelo servidor, sendo necessário alterar o cliente somente quando se deseja adicionar uma funcionalidade. Os comandos são números inteiros positivos definidos como constantes nos programas. A tabela 5.3 mostra uma lista dos comandos implementados. Quando algum erro ocorre na comunicação, ela é cortada imediatamente. Como a conexão é feita constante e periodicamente, não existe a necessidade para tratamento e recuperação de erros. Os dados não enviados são deixados para serem enviados na tentativa seguinte. 42 Capítulo 6 Testes e análises Para estudar o comportamento do sistema, é necessário executar testes controlados para averiguar as variáveis que o influenciam. Testes foram executados em alguns automóveis de diferentes fabricantes, sendo possível levantar a diferença de dados disponíveis para medição em cada modelo. Os automóveis foram dirigidos durantes os testes por diferentes percursos e horários, com o fim de testar o impacto da qualidade do sinal para o envio dos dados. Porém, considerando o ambiente urbano, onde existe cobertura de sinal em quase toda área livre, pouca diferença foi percebida neste quesito. Outra importante consideração que deve ser feita no sistema é se o meio de envio dos dados permite uma banda suficiente para que não haja acúmulo de dados localmente. Considerando o meio instável de conexão e a alta taxa de medição e a quantidade de dados levantados, esta é uma preocupação que é considerada nos testes a seguir. Antes de divulgar os resultados, é necessário expor os procedimentos realizados para execução do sistema, a plataforma utilizada, que não é a mesma definida como plataforma final de execução do projeto, e os cálculos realizados. 6.1 Plataforma de testes O sistema foi testado utilizando-se plataforma e interfaces diferentes das pretendidas, porém semelhantes, o que não garante um resultado completo, mas é uma boa aproximação para estimar o comportamento do sistema em funcionamento. A plataforma de execução utilizada é um notebook Dell Latitude D520 com processador Intel e sistema operacional Ubuntu Linux versão 9.10 (Figura 6.2). A interface com o automóvel é feita utilizando-se conector OBDxUSB comercial baseado no ELM327 (Figura 6.3). A versão do obdgpslogger utilizada foi a versão 0.10, disponibilizada em outubro de 2009. Para a conexão com a Internet, ao invés de modem 3G dedicado, utilizou-se um telefone celular Nokia N95 com conexão USB. O sistema operacional Ubuntu já possui os drivers necessários para fazê-lo funcionar como um modem 3G/GPRS (Figura 6.4). A operadora de telefonia celular na qual o aparelho é usado é a Claro. 43 6.2 Procedimentos Os procedimentos necessários para a criação do ambiente e realização dos testes foram os seguintes: • Montagem do ambiente cliente – Compilação do obdgpslogger. – Compilação do cliente de telemetria. – Configuração e instalação de drivers necessários para o conector OBD. – Conexão a Internet móvel. • Montagem do ambiente servidor – Compilação do servidor de telemetria. – Instalação e configuração de banco de dados. – Abertura de portas necessárias para comunicação. 6.2.1 Montagem do ambiente cliente Como já dito, o ambiente de execução dos processos cliente foi feito em um notebook rodando o Ubuntu Linux versão 9.10. Compilação do obdgpslogger Para compilar o fonte do programa disponibilizado em sua página da Internet (Briggs, 2009), é necessária a ferramenta CMake, que é uma ferramenta para facilitar a compilação de programas em diferentes ambientes, possibilitando a configuração do executável. Através do comando CCMake é possível customizar a compilação, removendo módulos desnecessários como os módulos de interface que acompanham o obdgpslogger, além de alterar alguns valores padrões para o programa, como caminho de destino do arquivo de log e porta serial padrão do dispositivo OBD. As bibliotecas necessárias para compilação são as pthread e dl, usadas pelo código do SQLite, incluso com o fonte do programa. Para o uso dos recursos GPS do programa, é necessária a instalação do gpsd, aplicativo de interface com dispositivos GPS. Compilação do cliente de telemetria O cliente de telemetria pode ser compilado com o uso do GCC, compilador C padrão nos sistemas GNU/Linux. Além das bibliotecas citadas acima para uso do SQLite, é necessária a biblioteca libconfig para leitura de arquivo de configuração que deve ser gerado em /etc/obdtelemetry.cfg com os parâmetros do cliente. Exemplo de arquivo de configuração pode ser visto na figura 6.1. As variáveis são: • hostname: Nome ou IP do servidor 44 /∗ # Configuration f i l e f o r o b d t e l e m e t r y c l i e n t ∗/ hostname = " hostname . ath . cx " ; v e h i c l e _ i d = "NEW1234 " ; db_path = " / home / a l c i d e s / obdlogs / obd . db " ; Figura 6.1: Exemplo de arquivo de configuração do cliente • vehicle_id: Placa do carro sendo medido • db_path: Caminho do arquivo que está sendo gerado pelo obdgpslogger Instalação de drivers necessários para o conector OBD A comunicação com as interfaces OBD baseadas no ELM327 é feita através de porta serial. Se o adaptador usado for de conexão RS-232, não é necessário nenhum driver. Porém, se for utilizada outra interface, como a USB, é necessário que seja feita a instalação do driver do conversor de sinal USBxRS-232 utilizado no conector. Nos testes o conector utilizado possuía interface USB serial com chip FTDI. Os drivers já estavam instalados no Ubuntu. Depois que o dispositivo é reconhecido pelo sistema, é necessário configurar sua taxa de transmissão (baud rate) para que a comunicação serial ocorra. Esta taxa depende do dispositivo sendo usado e pode não ser detectada automaticamente. No dispositivo usado, a taxa era erroneamente detectada como 9200 bauds sendo que o valor correto era 38400. Conexão a Internet móvel Para conectar o sistema a Internet móvel, é necessário um modem ou telefone com interface para conexão de computadores à rede GSM. O telefone utilizado, o Nokia N95, foi detectado automaticamente pelo Ubuntu e foi possível fazer conexão através de sua interface. 6.2.2 Montagem do ambiente servidor O computador utilizado como servidor nos testes foi um desktop com processador AMD e sistema Windows, mas nada no programa servidor impede que seja usado outra arquitetura, já que ele foi desenvolvido em Java. 45 Compilação do servidor de telemetria Para o desenvolvimento e compilação do programa servidor, foi utilizado o Java SE versão 1.6.0.15. Além das bibliotecas padrões do Java, foi utilizada a biblioteca OpenCSV (Smith et al., 2009) e a biblioteca de conexão com o banco de dados PostgreSQL. Instalação e configuração de banco de dados Para a instalação e configuração do banco de dados foi instalado pacote contendo o banco de dados e ferramentas de administração conhecido como PostgreSQL EnterpriseDB, disponível gratuitamente na Internet. Foram criadas duas tabelas no banco, como mostram os scripts SQL no anexo III. Registros de veículos são adicionados manualmente através de ferramenta de administração do banco. Abertura de portas necessárias para comunicação A porta IP definida para comunicação entre os processos é a 22490. O servidor deve estar conectado a Internet e com esta porta aberta para que a conexão funcione. Se houver roteamento e NAT, o gateway deve ser configurado para direcionar requisições desta porta para a máquina servidora. 6.3 Cálculos Alguns simples cálculos são feitos para averiguar o comportamento e viabilidade do sistema, para assegurar que o acúmulo indefinido de dados não ocorra facilmente. Variáveis medidas durante os testes: • Tt (Taxa de Transmissão média observada, em kb/s) • Tc (Taxa de Crescimento dos dados em kb/s) Tt é medido dividindo o tamanho do arquivo enviado pelo tempo de envio. Tc é calculado observando-se o tamanho dos arquivos gerados pelo sistema. Vamos definir λ como o intervalo de tempo, em segundos, entre uma conexão e outra do sistema. A princípio escolhemos λ = 300. Os arquivos a serem enviados são gerados neste intervalo de tempo. Chamamos de dt o tamanho em kbytes dos dados levantados no intervalo de t segundos. Podemos calcular o valor de Tc através de dλ da seguinte forma: Tc = dλ λ Para verificarmos a viabilidade do sistema, calculamos o tempo necessário para envio dos dados levantados durante t segundos (Tempo de Esvaziamento em t, τt ): τt = dt Tc = ×t Tt Tt 46 Indiscutivelmente, se Tc > Tt , o sistema é inviável já que nunca será possível enviar mais dados do que são gerados. Se Tc = Tt , a cada erro e falha de conexão haverá acúmulo de dados que nunca serão enviados. Logo para o sistema ser viável deve acontecer que Tc < Tt . Mesmo com Tc < Tt , um tempo muito grande sem conexão ou muitas falhas consecutivas poderiam gerar um acúmulo de dados que demoraria muito tempo para ser desfeito. Mesmo havendo conectividade, durante o envio ainda haveria acúmulo. Porém, como vamos observar nos testes a seguir, Tt Tc , logo τt t. Ou seja, qualquer acúmulo é rapidamente desfeito no momento em que ocorre uma conexão devido a grande diferença entre a taxa de transmissão e de acúmulo de dados. 6.4 6.4.1 Ford Ka 1.0 2009 Dados do teste • Data: 23 de Novembro de 2009 • Percurso: SQN 214 até Esplanada dos Ministérios, via Setor de Clubes Norte, Brasília. • Duração: 13:34 às 14:11 (37 minutos) • Quantidade de registros gerados: 2198 6.4.2 Campos OBD suportados De acordo com a tabela 3.1. Campo load_pct temp shrtft13 longft13 map rpm vss sparkadv iat throttlepos obdsup mil_dist Descrição Calculated LOAD Value Engine Coolant Temperature Short Term Fuel Trim - Bank 1,3 Long Term Fuel Trim - Bank 1,3 Intake Manifold Absolute Pressure Engine RPM Vehicle Speed Sensor Ignition Timing Advance for Cylinder 1 Intake Air Temperature Absolute Throttle Position OBD requirements to which vehicle is designed Distance Travelled While MIL is Activated Tabela 6.1: Dados OBD suportados pelo Ford Ka. 47 6.4.3 Valores observados Na tabela 6.2 estão as variáveis funcionais calculadas durante os testes. Na tabela 6.3 estão alguns exemplos dos dados levantados. Com os dados levantados foi possível calcular o valor médio de alguns dos parâmetros, como mostrado na tabela 6.4 Variável Valor Tt 2,44 kb/s Tc 0,28 kb/s τ300 34s τ3600 413s Tabela 6.2: Taxas do sistema observadas durante testes no Ford Ka. temp map 93 84 93 86 93 79 93 77 93 86 94 84 94 85 94 33 94 80 94 77 94 34 94 35 94 36 94 36 94 35 94 38 94 58 94 54 94 52 94 57 94 85 rpm vss iat throttlepos time 1274.00 0 54 24.313726 1258990717.951405 1642.00 8 54 37.647060 1258990718.951953 2285.00 13 54 0.000000 1258990719.952505 1646.00 14 54 25.882353 1258990720.953055 1632.00 16 54 33.333332 1258990721.953610 1934.00 20 54 33.725491 1258990722.954153 2192.00 23 54 37.254902 1258990723.954700 1958.00 25 53 5.882353 1258990724.955245 1555.00 25 54 20.784313 1258990725.955788 1674.00 27 54 1.176471 1258990726.956316 1651.00 27 53 0.000000 1258990727.956830 1571.00 26 53 0.000000 1258990728.957370 1529.00 25 54 0.000000 1258990729.957945 1447.00 24 54 0.000000 1258990730.958516 1326.00 22 54 0.000000 1258990731.959079 1197.00 20 54 0.000000 1258990732.959635 937.00 18 54 0.000000 1258990733.960249 993.00 15 54 0.000000 1258990734.960792 981.00 11 54 0.000000 1258990735.961345 927.00 10 54 8.235294 1258990736.961903 1081.00 11 55 29.411764 1258990737.962447 Tabela 6.3: Exemplo de dados levantados para o Ford Ka. 6.5 6.5.1 Nissan Livina 1.6 2009 Dados do teste • Data: 28 de Novembro de 2009 48 Parâmetro Média temp 91.6 map 59 rpm 1920 vss 39 throttlepos 14.64 Tabela 6.4: Valores médios de parâmetros levantados para o Ford Ka. • Percurso: SQS 316 até CLS 207, via Eixo W, Brasília. • Duração: 20:32 às 20:40 (8 minutos) • Quantidade de registros gerados: 456 6.5.2 Campos OBD suportados De acordo com a tabela 3.1. Campo load_pct temp shrtft13 longft13 map rpm vss sparkadv iat throttlepos o2sloc o2s11 o2s12 obdsup mil_dist Descrição Calculated LOAD Value Engine Coolant Temperature Short Term Fuel Trim - Bank 1,3 Long Term Fuel Trim - Bank 1,3 Intake Manifold Absolute Pressure Engine RPM Vehicle Speed Sensor Ignition Timing Advance for Cylinder 1 Intake Air Temperature Absolute Throttle Position Location of Oxygen Sensors Bank 1 - Sensor 1/Bank 1 - Sensor 1 Oxygen Sensor Output Voltage / Short Term Fuel Trim Bank 1 - Sensor 2/Bank 1 - Sensor 2 Oxygen Sensor Output Voltage / Short Term Fuel Trim OBD requirements to which vehicle is designed Distance Travelled While MIL is Activated Tabela 6.5: Dados OBD suportados pelo Nissan Livina. 6.5.3 Valores observados Na tabela 6.6 estão as variáveis funcionais calculadas durante os testes. Na tabela 6.7 estão alguns exemplos dos dados levantados. Com os dados levantados foi possível calcular o valor médio de alguns dos parâmetros, como mostrado na tabela 6.8 49 Variável Valor Tt 1,86 kb/s Tc 0,28 kb/s τ300 45s τ3600 541s Tabela 6.6: Taxas do sistema observadas durante testes no Nissan Livina. temp map 88 31 88 31 88 30 89 31 89 29 89 31 89 29 89 29 89 29 89 29 89 30 89 31 89 31 90 32 89 32 90 32 90 31 90 46 90 44 rpm vss iat throttlepos time 792.00 8 39 11.764706 1259451323.655444 809.00 8 39 11.764706 1259451324.656021 799.00 3 39 11.764706 1259451325.656564 796.00 0 39 11.764706 1259451326.657070 804.00 0 39 12.549020 1259451327.657567 826.00 0 39 11.764706 1259451328.658065 826.00 0 39 11.764706 1259451329.658566 800.00 0 39 11.764706 1259451330.659066 795.00 0 39 11.764706 1259451331.659568 764.00 0 39 11.764706 1259451332.660063 739.00 0 39 11.764706 1259451333.660566 741.00 0 39 11.764706 1259451334.661068 741.00 0 39 11.764706 1259451335.661571 721.00 0 39 11.764706 1259451336.662092 740.00 0 39 11.764706 1259451337.662575 744.00 0 39 11.764706 1259451338.663067 756.00 0 39 15.294118 1259451339.663568 2376.00 2 39 18.823530 1259451340.664068 2321.00 5 39 18.823530 1259451341.664567 Tabela 6.7: Exemplo de dados levantados para o Nissan Livina. 6.6 6.6.1 Ford Focus 2.0 2009 Dados do teste • Data: 25 de Novembro de 2009 • Percurso: 214 Norte até 506 Norte, ida via W3, volta via Eixo L. • Duração: 22:29 às 23:30 (61 minutos) • Quantidade de registros gerados: 3386 6.6.2 Campos OBD suportados De acordo com a tabela 3.1. 50 Parâmetro Média temp 88 map 36 rpm 1550 vss 42 throttlepos 14.85 Tabela 6.8: Valores médios de parâmetros levantados para o Nissan Livina. Campo load_pct temp rpm vss obdsup mil_dist aat Descrição Calculated LOAD Value Engine Coolant Temperature Engine RPM Vehicle Speed Sensor OBD requirements to which vehicle is designed Distance Travelled While MIL is Activated Ambient Air Temperature Tabela 6.9: Dados OBD suportados pelo Ford Focus. 6.6.3 Valores observados Na tabela 6.10 estão as variáveis funcionais calculadas durante os testes. Na tabela 6.11 estão alguns exemplos dos dados levantados. Com os dados levantados foi possível calcular o valor médio de alguns dos parâmetros, como mostrado na tabela 6.12 Variável Valor Tt 1,71 kb/s Tc 0,14 kb/s τ300 24s τ3600 294s Tabela 6.10: Taxas do sistema observadas durante testes no Ford Focus. 51 temp 92 92 92 93 92 92 92 92 92 92 92 92 92 92 92 92 93 93 93 92 rpm vss time 1537.75 7 1259199063.590389 1886.50 13 1259199064.590835 2245.25 19 1259199065.591290 2437.75 24 1259199066.591753 2109.75 29 1259199067.592208 1979.75 32 1259199068.592670 1767.25 32 1259199069.593141 1167.75 32 1259199070.593585 1141.00 30 1259199071.594017 1071.50 28 1259199072.594504 1001.75 26 1259199073.594989 966.25 24 1259199074.595407 904.50 23 1259199075.595919 941.75 22 1259199076.596382 1695.25 22 1259199077.596854 2178.25 25 1259199078.597337 2197.00 28 1259199079.597804 2215.50 30 1259199080.598287 2117.50 32 1259199081.598769 2047.50 32 1259199082.599231 Tabela 6.11: Exemplo de dados levantados para o Ford Focus. Parâmetro Média temp 94 rpm 855 vss 14 Tabela 6.12: Valores médios de parâmetros levantados para o Ford Focus. 52 Figura 6.2: Notebook Dell utilizado para executar o sistema Figura 6.3: Conector USBxOBD 53 Figura 6.4: Celular Nokia N95 com cabo USB para uso como modem 3G/GPRS. Figura 6.5: Automóvel Ford Ka 1.0, ano 2009, exterior. 54 Figura 6.6: Localização do conector OBD no Ford Ka. Figura 6.7: Automóvel Nissan Livina 1.6, ano 2009, exterior. 55 Figura 6.8: Localização do conector OBD no Nissan Livina. Figura 6.9: Automóvel Ford Focus 2.0, ano 2009, exterior. 56 Figura 6.10: Localização do conector OBD no Ford Focus. 57 Capítulo 7 Conclusão e desenvolvimentos futuros Através deste trabalho foi possível verificar que a tecnologia existente hoje em dia, tanto em questões de software, como hardware e infra-estrutura em telecomunicações, permitiram o desenvolvimento de sistema de telemetria para veículos automotores. Todos os objetivos do projeto foram alcançados, porém sua integração ao sistema Karmonitor ainda necessita de alguns passos. Primeiramente, em questão ao hardware, o conector OBD e os softwares utilizados neste projeto foram testados sob o Angstrom na Beagle Board e funcionaram. Porém não foi possível realizar os testes de uso neste hardware pois não foi feita ainda a instalação da placa em um automóvel. Logo o ambiente de hardware utilizado nos testes foi diferente. Isto pode levar a diferenças com relação a performance do sistema, visto que a Beagle Board é um ambiente mais limitado que o notebook utilizado. Para a integração deste sistema na Beagle Board, é necessário: • Compilação dos programas clientes para execução no Angstrom da Beagle Board (Já comprovado ser possível). • Instalação do driver necessário para a interface USBxSerial utilizada no conector OBD desejado. (O conector utilizado neste projeto já foi testado com sucesso na Beagle). • Instalação de drivers e componentes do sistema para conexão à Internet pela rede celular. • Instalação da Beagle em um automóvel. Com relação ao software, como o programa cliente estará executando em um computador a bordo, é necessário que ele e o obdgpslogger sejam configurados para funcionarem como daemons, executando automaticamente com o boot do sistema operacional. Outro aspecto que não foi abordado e que é fundamental para o uso do sistema em larga escala é a questão da segurança. Os dados devem ser assinados e/ou criptografados para evitar interferências e interceptações por terceiros, considerando 58 que estes dados trafegarão em rede pública, a Internet. Uma simples implementação de criptografia, tanto simétrica como assimétrica, deve ser o suficiente para sanar a vulnerabilidade. Uma capacidade do obdgpslogger que não foi explorada é a de monitoramento da posição através de dispositivo GPS ligado ao computador que executa o cliente. Porém, o cliente já está preparado para enviar os dados, basta que um equipamento compatível com o programa gpsd esteja conectado. Esta funcionalidade só não foi explorada por falta do hardware adequado para testes. Outra possibilidade para o sistema é sua especialização quanto a veículos e fabricantes. Através da porta OBD estão sendo somente levantados dados padrões que são disponibilizados em diversos carros. Porém, através da porta OBD é possível enviar comandos e levantar dados específicos ao modelo de carro e fabricante. Para isso, seria necessário um dispositivo USB x OBD diferenciado, pois o ELM327 somente suporta os comandos padrões. Também seria necessário um patrocínio ou parceria com a fabricante, pois tais comandos e modos de comunicação não são publicados abertamente. 59 Referências Anatel (2009). Total de acessos móveis pré-pago e pós-pago por uf. 28 BRASIL (1993). Lei 8.723, de 28 de outubro de 1993. publicada no diário oficial da união em 29 de outubro de 1993. 2 Briggs, G. (2009). Obd gps logger. http://icculus.org/obdgpslogger/. Acessado em 11/2009. 35, 44 CONAMA (2006). InstruÇÃo normativa nř 126, de 24 outubro de 2006. 20 Dzhelekarski, P. and Alexiev, D. (2005a). Initializing communication to vehicle obdii system. ELECTRONICS’05. 21 Dzhelekarski, P. and Alexiev, D. (2005b). Reading and interpreting diagnostic data from vehicle obdii system. ELECTRONICS’05. 12, 22 ELM Electronics (2009). ELM327 - OBD to RS232 Interpreter. 23 FlexRay Consortium (2005). FlexRay Protocol Especification, 2.1a edition. 18 GSM Association (2009). Market data summary. 28 Gutierrez, E. M. (2006). Telemetria: Aplicação de rede de sensores biomédicos sem fio. Master’s thesis, UnB - Universidade de Brasília. 3 Jenkins, W. (2004). Real-time vehicle performance monitoring using wireless networking. Technical report, Human and Systems Engineering, Center for Advanced Vehicular Systems, Mississippi State University, 200 Research Blvd., Mississippi State, Mississippi 39759, USA. 5 Junior, M. H. (2005). Internet móvel, gprs aplicado ao acesso à internet. Technical report, Universidade Federal de Santa Catarina. viii, 30, 31 Khan, N., Saleem, Z., and Hoong, C. C. (2007). An experiment on internet based telemetry. Proceedings of the 6th WSEAS Int. Conf. on Electronics, Hardware, Wireless and Optical Communications, pages 68–78. 4 Kopetz, H., Elmenreich, W., and Mack, C. (2000). A comparison of lin and ttp/a. Technical report, Institut für Technische Informatik, Technische Universität Wien, Austria. 8 60 Kopetz, H. and Grunstidl, G. (1993). Ttp - a time-triggered protocol for faulttolerant real-timesystems. In Fault-Tolerant Computing 1993, Digest of papers., pages 524–533. 8, 17 Kvaser AB (2009). The can protocol tour: http://www.kvaser.com/can/ protocol/index.htm, acessado em 04/2009. 12 Leen, G. and Heffernan, D. (2002). Expanding automotive electronic systems. Computer, 35(1):88–93. 7 Leen, G., Heffernan, D., and Dunne, A. (1999). Digital networks in the automotive vehicle. Computing and Control Engineering Journal, 10(6):257–266. 7 Mantovani, J. E. and Santos, J. E. (2001). Telemetria convencional e via satélite na determinação da área de vida de três espécies de carnívoros da região nordeste do estado de são paulo. Master’s thesis, Universidade Federal de Santa Catarina - UFSC. 3 MOST Cooperation (2008). MOST Specification, rev 3.0 edition. 17 Navet, N., Song, Y., Simonot-lion, F., and Wilmert, C. (2005). Trends in automotive communication systems. Proceedings of the IEEE, 93(6):1204–1223. 6 Oliver, D. J. (2001). Implementing the J1850 Protocol. Intel Corporation. 8 Paim, F. C. A. (2005). Desenvolvimento de um sistema de telemetria para aquisiÇÃo de sinais fisiolÓgicos com aplicaÇÃo em programas de reabilitaÇÃo cardÍaca. Master’s thesis, Universidade Federal de Santa Catarina - UFSC. 3 Pazul, K. (1999). Controller area network (can) basics. Technical report, Microchip Technology Inc. 12, 16 Peersman, G. and Cvetkovic, S. (2000). The global system for mobile communications short message service. IEEE Personal Communications. 29 Richardson, K. W. (2000). Umts overview. ELECTRONICS & COMMUNICATION ENGINEERING JOURNAL, pages 93–101. 31 Riley, M. (1998). Computer networks take to the road. Evaluation Engineering. ix, 8, 9, 10, 11, 12 Schofield, M. J. (1996). Controller area network (canbus): mjschofield.com/, acessado em 04/2009. 12, 13, 16 http://www. Scourias, J. (1997). Overview of the global system for mobile communications. Technical report, University of Waterloo. 29 Sidorenko, A. (2009). Obd2 elm327 compatible allpro adapter with usb http:// obddiag.net acessado em 06/2009. 23 Smith, G., Sullivan, S., and Conway, S. (2009). Opencsv. http://opencsv. sourceforge.net/. Acessado em 11/2009. 38, 46 61 TTA Group (2004). TTP - Easy to read. 8, 17 Walker, B. (2007). Augmenting amusement rides with telemetry. Advancements in Computer Entertainment Technology, pages 115–122. 4 62 Anexo I Código-fonte do cliente I.1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 clientmain.h /∗ ∗∗ CLIENTMAIN.H ∗ Author : A l c i d e s Carlos de Moraes Neto ∗ This f i l e i s part o f o b d t e l e m e t r y c l i e n t ∗/ #ifndef _CLIENTMAIN_H #define _CLIENTMAIN_H #define CSV_PATH " / tmp / obdlogs / " //Server commands// #define CMD_SEND_LICENSE 1 #define CMD_RECV_BUFFERSZ 2 #define CMD_SEND_NUMFILES 3 #define CMD_SEND_FILES 4 #define CMD_RECV_SLEEPTM 5 #define CMD_BYE 99 #include <sys / d i r . h> // g e t c u r r e n t time from g e t t i m e o f d a y ( ) double get_curr_time ( ) ; // c a l l obd2csv and g e n e r a t e csv f i l e in CSV_PATH // The f i l e name w i l l be obd + curr_time + . csv . gz int gen_obd_csv ( char∗ db_path , double curr_time ) ; // used in scandir c a l l t o g e t . csv . gz f i l e s only . 63 30 int c s v g z _ f i l t e r ( const struct d i r e n t ∗ f i l e ) ; 31 32 #endif /∗ _CLIENTMAIN_H ∗/ I.2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 clientmain.c /∗ ∗∗ CLIENTMAIN.C ∗ Author : A l c i d e s Carlos de Moraes Neto ∗ This f i l e i s part o f o b d t e l e m e t r y c l i e n t ∗/ #include " clientmain . h" #include #include #include #include #include #include #include #include #include #include < s t d i o . h> < s t d l i b . h> <unistd . h> <errno . h> < s t r i n g . h> <sys / types . h> <sys / s t a t . h> <sys / d i r . h> <sys / param . h> < l i b c o n f i g . h> #include " networking . h" #include " database . h" int main ( int argc , char ∗ argv [ ] ) { // l i b c o n f i g s t r u c t s config_t conf ; // I n t e r n e t s o c k e t d e s c r i p t o r int sockfd ; //Hostname char ∗hostname ; //Command r e c e i v e d from s e r v e r char cmd ; // V e h i c l e id char ∗ c a r _ i d ; // l o g g e r s q l i t e db path char ∗ db_path ; 64 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 // Current time o f c o n n e c t i o n double curr_time ; //Number o f csv f i l e s generated and not s e n t int f i l e c o u n t ; // L i s t o f f i l e s t o be s e n t struct d i r e n t ∗∗ f i l e s ; // Full path t o a f i l e char f i l e _ p a t h [MAXPATHLEN] ; //FILE being s e n t FILE ∗ f ; // Size o f b u f f e r t o use f o r sending f i l e s . Received from s e r v e r . int buflen ; // Time in seconds the program s l e e p s b e f o r e c o n n e c t i n g to server . // This can be changed by the s e r v e r . int sleep_time = 300; // Your everyday FOR counter int i ; i f ( mkdir (CSV_PATH, 0700) && errno != EEXIST) { f p r i n t f ( stderr , " Error : Could not c r e a t e d i r e c t o r y %s \n " , CSV_PATH) ; exit (1) ; } errno =0; //Loading values from c o n f i g f i l e / e t c /o b d t e l e m e t r y . c f g c o n f i g _ i n i t (& c o n f ) ; i f ( c o n f i g _ r e a d _ f i l e (& conf , " / e t c / obdtelemetry . c f g " ) == CONFIG_FALSE) { f p r i n t f ( stderr , " Error , could not read c o n f i g f i l e : % s\n" , c o n f i g _ e r r o r _ t e x t (& c o n f ) ) ; exit (1) ; } i f ( c o n f i g _ l o o k u p _ s t r i n g (& conf , " hostname " , &hostname ) == CONFIG_FALSE) { f p r i n t f ( stderr , " Error , could not read hostname : %s\n " , c o n f i g _ e r r o r _ t e x t (& c o n f ) ) ; exit (1) ; } i f ( c o n f i g _ l o o k u p _ s t r i n g (& conf , " v e h i c l e _ i d " , &c a r _ i d ) == CONFIG_FALSE) { 65 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 f p r i n t f ( stderr , " Error , could not read v e h i c l e _ i d : %s \n " , c o n f i g _ e r r o r _ t e x t (& c o n f ) ) ; exit (1) ; } i f ( c o n f i g _ l o o k u p _ s t r i n g (& conf , " db_path " , &db_path ) == CONFIG_FALSE) { f p r i n t f ( stderr , " Error , could not read db_path : %s\n" , c o n f i g _ e r r o r _ t e x t (& c o n f ) ) ; exit (1) ; } do { i f ( ( curr_time = get_curr_time ( ) ) < 0 ) { f p r i n t f ( stderr , " Error : Could not get time o f day . " ) ; c l o s e ( sockfd ) ; exit (1) ; } i f ( gen_obd_csv ( db_path , curr_time ) ) { f p r i n t f ( stderr , " Error : Could not generate csv " ) ; c l o s e ( sockfd ) ; exit (1) ; } i f ( flush_db ( db_path , curr_time ) ) { f p r i n t f ( stderr , " Error : Could not f l u s h database ."); c l o s e ( sockfd ) ; exit (1) ; } f i l e c o u n t = scandir (CSV_PATH, &f i l e s , c s v g z _ f i l t e r , alphasort ) ; i f ( f i l e c o u n t <= 0 ) { f p r i n t f ( stderr , " Error : Could not f i n d csv f i l e ( s) . ") ; c l o s e ( sockfd ) ; continue ; } p r i n t f ( " Connecting t o %s . . . \ n" , hostname ) ; 66 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 i f ( c o n n e c ts o c k e t ( hostname , &sockfd ) < 0 ) { p r i n t f ( " Could not c o n t a c t s e r v e r . . . \ n" ) ; continue ; //return −1; // Could not c o n t a c t server } do { // R e c e i v e command from s e r v e r and e x e c u t e // p r i n t f ( " Receiving command . . . " ) ; i f ( recv_chk ( sockfd , &cmd , sizeof ( char ) , 0 ) < 0 ) { c l o s e ( sockfd ) ; continue ; } //cmd = ntohl (cmd) ; p r i n t f ( " r e c e i v e d : %d\n" , cmd ) ; switch ( cmd ) { case CMD_SEND_LICENSE: //send car l i c e n s e i f ( send_chk ( sockfd , car_id , s t r l e n ( car_id ) , 0) < 0) { c l o s e ( sockfd ) ; continue ; } break ; case CMD_RECV_BUFFERSZ: // r e c e i v e b u f f e r s i z e p r i n t f ( " r e c e i v i n g buflen . . . " ) ; i f ( recv_chk ( sockfd , &buflen , sizeof ( int ) , 0) < 0) { c l o s e ( sockfd ) ; continue ; } buflen = ntohl ( buflen ) ; p r i n t f ( " r e c e i v e d : %d\n" , buflen ) ; break ; case CMD_SEND_NUMFILES: //send number o f f i l e s f i l e c o u n t = htonl ( f i l e c o u n t ) ; i f ( send_chk ( sockfd , &f i l e c o u n t , sizeof ( int ) , 0 ) < 0 ) { c l o s e ( sockfd ) ; continue ; 67 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 } f i l e c o u n t = ntohl ( f i l e c o u n t ) ; break ; case CMD_SEND_FILES: for ( i = f i l e c o u n t −1; i >= 0 ; i −−) { // Going from newest t o o l d e s t // Newer data i s more important s t r c p y ( f i l e _ p a t h , CSV_PATH) ; s t r c a t ( f i l e _ p a t h , f i l e s [ i ]−>d_name ) ; f = fopen ( f i l e _ p a t h , " rb " ) ; i f ( f == NULL) { f p r i n t f ( stderr , " Error : Could not open f i l e %s " , f i l e _ p a t h ) ; c l o s e ( sockfd ) ; exit (1) ; } p r i n t f ( " Sending f i l e %s . . . \ n" , file_path ) ; i f ( s e n d _ f i l e ( f , sockfd , buflen ) ) { // F i l e not s e n t . . . g i v e up and try later fclose ( f ) ; break ; } fclose ( f ) ; i f ( remove ( f i l e _ p a t h ) ) { f p r i n t f ( stderr , " Error : Could not remove f i l e %s " , file_path ) ; c l o s e ( sockfd ) ; exit (1) ; } } break ; case CMD_RECV_SLEEPTM: // r e c e i v e s l e e p _ t i m e p r i n t f ( " r e c e i v i n g sleep_time . . . " ) ; i f ( recv_chk ( sockfd , &sleep_time , sizeof ( int ) , 0 ) < 0 ) { c l o s e ( sockfd ) ; continue ; } sleep_time = ntohl ( sleep_time ) ; 68 184 p r i n t f ( " r e c e i v e d : %d\n" , sleep_time ) ; 185 break ; 186 case CMD_BYE: 187 default : 188 cmd=−1; 189 c l o s e ( sockfd ) ; 190 break ; 191 } 192 } while ( cmd > 0 ) ; 193 } while ( ! s l e e p ( sleep_time ) ) ; 194 195 return 0 ; 196 } 197 198 double get_curr_time ( ) { 199 struct timeval currtime ; 200 201 i f ( 0 != gettimeofday (&currtime ,NULL) ) { 202 perror ( " Error on gettimeofday " ) ; 203 return −1; 204 } 205 return ( double ) currtime . t v _ s e c +(double ) currtime . tv_usec /1000000.0 f ; 206 } 207 208 int gen_obd_csv ( char∗ db_path , double curr_time ) { 209 // obd2csv c a l l s t r i n g 210 char o b d 2 c s v _ c a l l [ 5 1 2 ] ; 211 // f i l e name 212 char csv_filename [ 2 8 ] ; 213 214 // F i l e name 215 s p r i n t f ( csv_filename , " obd%−11.5 f . csv . gz " , curr_time ) ; 216 //obd2csv c a l l 217 s p r i n t f ( o b d 2 c s v _ c a l l , " obd2csv −d %s −z −o %s%s −e %−11.5 f " , db_path , CSV_PATH, csv_filename , curr_time ) ; 218 p r i n t f ( " obd2csv c a l l : %s\n" , o b d 2 c s v _ c a l l ) ; 219 220 i f ( system ( o b d 2 c s v _ c a l l ) ) { 221 perror ( " Error on obd2csv c a l l . " ) ; 222 return 1 ; 223 } 224 return 0 ; 69 225 } 226 227 int c s v g z _ f i l t e r ( const struct d i r e n t ∗ f i l e ) { 228 return s t r s t r ( f i l e −>d_name , " . csv . gz " ) ; 229 } ; I.3 database.h 1 /∗ Copyright 2009 Gary Briggs 2 3 This f i l e i s part o f obdgpslogger . 4 5 obdgpslogger i s f r e e s o f t w a r e : you can r e d i s t r i b u t e i t and/ or modify 6 i t under the terms o f the GNU General Public L i c e n s e as published by 7 the Free Software Foundation , e i t h e r v e r s i o n 2 o f the License , or 8 ( at your o p t i o n ) any l a t e r v e r s i o n . 9 10 obdgpslogger i s d i s t r i b u t e d in the hope t h a t i t w i l l be useful , 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public L i c e n s e f o r more d e t a i l s . 14 15 You should have r e c e i v e d a copy o f the GNU General Public License 16 along with obdgpslogger . I f not , s e e <h t t p ://www. gnu . org/ l i c e n s e s / >. 17 ∗/ 18 19 20 /∗∗ \ f i l e 21 \ b r i e f Database open and c l o s e f u n c t i o n s 22 ∗/ 23 #ifndef __DATABASE_H 24 #define __DATABASE_H 25 26 #include " s q l i t e 3 . h" 70 27 28 29 30 31 32 33 34 /// Open the s q l i t e database s q l i t e 3 ∗opendb ( const char ∗ dbfilename ) ; /// Close the s q l i t e database void c l o s e d b ( s q l i t e 3 ∗db ) ; /// D e l e t e a l l rows in obd , gps and t r i p t a b l e s s t o r e d b e f o r e endtime . 35 int flush_db ( char∗ db_path , const double endtime ) ; 36 37 #endif //__DATABASE_H I.4 database.c 1 /∗ Copyright 2009 Gary Briggs 2 3 This f i l e i s part o f obdgpslogger . 4 5 obdgpslogger i s f r e e s o f t w a r e : you can r e d i s t r i b u t e i t and/ or modify 6 i t under the terms o f the GNU General Public L i c e n s e as published by 7 the Free Software Foundation , e i t h e r v e r s i o n 2 o f the License , or 8 ( at your o p t i o n ) any l a t e r v e r s i o n . 9 10 obdgpslogger i s d i s t r i b u t e d in the hope t h a t i t w i l l be useful , 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public L i c e n s e f o r more d e t a i l s . 14 15 You should have r e c e i v e d a copy o f the GNU General Public License 16 along with obdgpslogger . I f not , s e e <h t t p ://www. gnu . org/ l i c e n s e s / >. 17 ∗/ 18 19 71 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 /∗∗ \ f i l e \ b r i e f database s t u f f ∗/ #include " database . h" #include " s q l i t e 3 . h" #include < s t d i o . h> #include < s t d l i b . h> #include < s t r i n g . h> s q l i t e 3 ∗opendb ( const char ∗ dbfilename ) { // s q l i t e database s q l i t e 3 ∗db ; // s q l i t e return s t a t u s int r c ; r c = s q l i t e 3 _ o p e n ( dbfilename , &db ) ; i f ( SQLITE_OK != r c ) { f p r i n t f ( stderr , " Error : Cannot open database %s : %s\n" , dbfilename , s q l i t e 3 _ e r r m s g ( db )); s q l i t e 3 _ c l o s e ( db ) ; return NULL; } 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 // Just a l i t t l e timeout t o g i v e s q l i t e a chance // t o f i x t h i n g s i f someone ’ s scraping the database s q l i t e 3 _ b u s y _ t i m e o u t ( db , 1 ) ; return db ; } void c l o s e d b ( s q l i t e 3 ∗db ) { s q l i t e 3 _ c l o s e ( db ) ; } int flush_db ( char∗ db_path , const double endtime ) { s q l i t e 3 ∗db ; const char c o n s t s q l [ ] = "BEGIN TRANSACTION; " "DELETE FROM obd WHERE time < %−11.5 f ; " "DELETE FROM gps WHERE time < %−11.5 f ; " 72 61 62 63 64 65 66 67 68 69 70 71 72 73 74 "DELETE FROM t r i p WHERE end < %−11.5 f AND end > 0 ; " "END TRANSACTION; " ; char s q l [ 1 8 7 ] ; char ∗ s q l e r r o r ; i f ( ( db = opendb ( db_path ) ) == NULL) { perror ( " Error opening database " ) ; return 1 ; } s p r i n t f ( sql , c o n s t s q l , endtime , endtime , endtime ) ; // p r i n t f ( "SQL: %s\n " , s q l ) ; 75 76 77 78 79 80 81 82 } I.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 i f ( s q l i t e 3 _ e x e c ( db , sql , NULL, NULL, &s q l e r r o r ) != SQLITE_OK) { perror ( s q l e r r o r ) ; sqlite3_free ( sqlerror ) ; return 1 ; } c l o s e d b ( db ) ; return 0 ; networking.h /∗ ∗∗ NETWORKING.H ∗ Author : A l c i d e s Carlos de Moraes Neto ∗ This f i l e i s part o f o b d t e l e m e t r y c l i e n t ∗/ #ifndef _NETWORKING_H #define _NETWORKING_H #include #include #include #include #include #include #include < s t d i o . h> < s t d l i b . h> <unistd . h> <errno . h> < s t r i n g . h> <netdb . h> <sys / types . h> 73 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include < n e t i n e t / in . h> #include <sys / s o c k e t . h> #include <arpa / i n e t . h> #define PORT " 22490 " #ifdef __cplusplus extern "C" { #endif // g e t s o c k e t address void ∗ get_in_addr ( struct sockaddr ∗ sa ) ; // c onnect a new s o c k e t in s o c k f d t o hostname int c o n ne c t s o c ke t ( char ∗hostname , int ∗ sockfd ) ; // r e c e i v e data and check i f a l l b y t e s were r e c e i v e d int recv_chk ( int sockfd , void ∗ b u f f e r , s s i z e _ t len , int flags ) ; 35 36 // send data and check i f a l l b y t e s were s e n t 37 int send_chk ( int sockfd , const void ∗ data , s s i z e _ t len , int flags ) ; 38 39 /∗ send FILE f through s o c k e t sock , in p i e c e s o f s i z e buflen , by t h e s e s t e p s : 40 ∗ 1− Send f i l e s i z e as i n t 41 ∗ 2− Send b u f l e n b y t e s o f FILE f 42 ∗ 3− Recv ACK in the form o f i n t 43 ∗ − I f i t ’ s the number o f the p i e c e , send the next one 44 ∗ − I f i t ’ s d i f f e r e n t , i t means t h e r e was an e r r o r . Send the l a s t p i e c e again . 45 ∗/ 46 int s e n d _ f i l e ( FILE∗ f , int sock , s i z e _ t buflen ) ; 47 48 # i f d e f _ _ c p l u s p l u s 49 } 50 #endif 51 52 #endif /∗ _NETWORKING_H ∗/ 74 I.6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 networking.c /∗ ∗∗ NETWORKING.C ∗ Author : A l c i d e s Carlos de Moraes Neto ∗ This f i l e i s part o f o b d t e l e m e t r y c l i e n t ∗/ #include " networking . h" void ∗ get_in_addr ( struct sockaddr ∗ sa ) { i f ( sa−>sa_family == AF_INET) { return & ( ( ( struct sockaddr_in ∗ ) sa )−>sin_addr ) ; } return & ( ( ( struct sockaddr_in6 ∗ ) sa )−>sin6_addr ) ; } int c o n ne c t s o c k et ( char ∗hostname , int ∗ sockfd ) { struct addrinfo hints , ∗ s e r v i n f o , ∗p ; int rv ; char s [INET6_ADDRSTRLEN ] ; memset(& hints , 0 , sizeof h i n t s ) ; h i n t s . a i _ f a m i l y = AF_UNSPEC; h i n t s . a i _ s o c k t y p e = SOCK_STREAM; i f ( ( rv = g e t a d d r i n f o ( hostname , PORT, &hints , &s e r v i n f o ) ) != 0 ) { f p r i n t f ( stderr , " g e t a d d r i n f o : %s\n" , g a i _ s t r e r r o r ( rv )); return −1; } // loop through a l l the r e s u l t s and connect t o the f i r s t we can for ( p = s e r v i n f o ; p != NULL; p = p−>ai_next ) { i f ( ( ∗ sockfd = s o c k e t ( p−>ai_family , p−>ai_socktype , p−>a i _ p r o t o c o l ) ) == −1) { perror ( " c l i e n t : s o c k e t " ) ; continue ; } 75 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 i f ( connect ( ∗ sockfd , p−>ai_addr , p−>ai_addrlen ) == −1) { c l o s e ( ∗ sockfd ) ; perror ( " c l i e n t : connect " ) ; continue ; } break ; } i f ( p == NULL) { f p r i n t f ( stderr , " c l i e n t : f a i l e d t o connect\n" ) ; return −1; } i n e t _ n t o p ( p−>ai_family , get_in_addr ( ( struct sockaddr ∗ ) p −>ai_addr ) , s , sizeof s ) ; p r i n t f ( " c l i e n t : connecting t o %s\n" , s ) ; 56 57 58 59 f r e e a d d r i n f o ( s e r v i n f o ) ; // a l l done with t h i s s t r u c t u r e 60 return 0 ; 61 } 62 63 64 int recv_chk ( int sockfd , void ∗ b u f f e r , s s i z e _ t len , int flags ) { 65 s s i z e _ t recvd =0; 66 recvd = recv ( sockfd , b u f f e r , len , f l a g s ) ; 67 i f ( recvd < len ) { 68 perror ( " recv returned l e s s than expected " ) ; 69 return −1; 70 } 71 return 0 ; 72 } 73 74 int send_chk ( int sockfd , const void ∗ b u f f e r , s s i z e _ t len , int f l a g s ) { 75 s s i z e _ t sent =0; 76 sent = send ( sockfd , b u f f e r , len , f l a g s ) ; 77 i f ( sent < len ) { 78 perror ( " send returned l e s s than expected " ) ; 79 return −1; 76 80 81 82 } 83 84 int 85 { 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 } return 0 ; s e n d _ f i l e ( FILE∗ f , int sock , s i z e _ t buflen ) char buf [ buflen ] ; s s i z e _ t len ; long int f i l e l e n ; int ack =0 , i =0; // f i n d i n g out f i l e s i z e f s e e k ( f , 0 , SEEK_END) ; p r i n t f ( " Sending f i l e s i z e : %d . \n" , f t e l l ( f ) ) ; f i l e l e n = htonl ( f t e l l ( f ) ) ; f s e e k ( f , 0 , SEEK_SET) ; // f i r s t thing s e n t i s f i l e s i z e i f ( send_chk ( sock , &f i l e l e n , sizeof ( long int ) , 0 ) < 0 ) { perror ( " Error sending f i l e s i z e . " ) ; return ( 1 ) ; } p r i n t f ( " F i l e s i z e sent . Sending f i l e . . . \ n" ) ; while ( ( len = fread ( buf , sizeof ( char ) , buflen , f ) ) > 0 ) { do { i f ( send ( sock , buf , len , 0 ) < 0 ) { perror ( " Error sending data . " ) ; return ( 1 ) ; } // r e c e i v i n g ACK. I f ack == p i e c e number ( i ) , then proceed . // I f i t ’ s not , send again . recv_chk ( sock , &ack , sizeof ( int ) , 0 ) ; } while ( ntohl ( ack ) != i ) ; i ++; } if ( ferror ( f ) ) { perror ( " Error reading f i l e . " ) ; return ( 1 ) ; } return ( 0 ) ; 77 123 } 78 Anexo II Código-fonte do servidor II.1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Main.java /∗ ∗ Main . java ∗ Author : A l c i d e s Carlos de Moraes Neto ∗ This f i l e i s part o f OBD Telemetry Server ∗/ package obdTelemetryServer ; import import import import import import import java . i o . F i l e ; java . i o . FileReader ; java . i o . IOException ; java . net . ServerSocket ; java . u t i l . P r o p e r t i e s ; java . u t i l . l o g g i n g . Level ; java . u t i l . l o g g i n g . Logger ; /∗∗ ∗ ∗ @author A l c i d e s Carlos de Moraes Neto ∗/ public class Main { /∗∗ ∗ @param args the command l i n e arguments ∗/ public s t a t i c void main ( String [ ] args ) { ServerSocket srvSock = null ; // −− Configuration −− // 79 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 // d e f a u l t s int b u f f e r = 1024; int port = 22490; String logsPath = "C:\\ obdlogs\\ " ; // f i l e F i l e f = new F i l e ( " obdtelemetryserver . c f g " ) ; i f ( f . canRead ( ) ) { P r o p e r t i e s c o n f i g = new P r o p e r t i e s ( ) ; try { c o n f i g . load (new FileReader ( f ) ) ; } catch ( IOException ex ) { System . e r r . p r i n t l n ( " Error reading c o n f i g u r a t i o n f i l e : " + ex . getLocalizedMessage ( ) ) ; System . e x i t ( 1 ) ; } String cfgValue = c o n f i g . getProperty ( " b u f f e r " ) ; i f ( cfgValue != null ) { try { b u f f e r = I n t e g e r . parseInt ( cfgValue ) ; } catch ( Exception e ) { System . e r r . p r i n t l n ( " Error reading configuration f i l e : Invalid ’ buffer ’ attribute . " ) ; System . e x i t ( 1 ) ; } } cfgValue = c o n f i g . getProperty ( " port " ) ; i f ( cfgValue != null ) { try { port = I n t e g e r . parseInt ( cfgValue ) ; } catch ( Exception e ) { System . e r r . p r i n t l n ( " Error reading c o n f i g u r a t i o n f i l e : I n v a l i d ’ port ’ attribute . " ) ; System . e x i t ( 1 ) ; } } cfgValue = c o n f i g . getProperty ( " logsPath " ) ; i f ( cfgValue != null ) logsPath = cfgValue ; } try { srvSock = new ServerSocket ( port ) ; 80 68 69 } catch ( IOException ex ) { System . e r r . p r i n t l n ( " Error l i s t e n i n g on port 22490. " ) ; System . e x i t ( 1 ) ; } 70 71 72 73 74 75 76 System . out . p r i n t l n ( " Waiting f o r c o n n e c t i o n s . . . " ) ; while ( ! srvSock . i s C l o s e d ( ) ) { try { new ServerThread ( srvSock . accept ( ) , b u f f e r , logsPath ) . s t a r t ( ) ; } catch ( IOException ex ) { System . e r r . p r i n t l n ( " Error a c c e p t i n g connection : " + ex . getLocalizedMessage ( ) ) ; continue ; } } 77 78 79 80 81 82 83 84 } II.2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 } ServerThread.java /∗ ∗ ServerThread . java ∗ Author : A l c i d e s Carlos de Moraes Neto ∗ This f i l e i s part o f OBD Telemetry Server ∗/ package obdTelemetryServer ; import import import import import import import import import import au . com . bytecode . opencsv . CSVReader ; java . i o . DataInputStream ; java . i o . F i l e ; java . i o . FileInputStream ; java . i o . FileOutputStream ; java . i o . FileReader ; java . i o . IOException ; java . i o . OutputStream ; java . net . Socket ; java . u t i l . ArrayList ; 81 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 import import import import import java . u t i l . Date ; java . u t i l . z i p . GZIPInputStream ; obdTelemetryServer . beans . Vehicle ; obdTelemetryServer . db . ObdDao ; obdTelemetryServer . db . VehicleDao ; /∗∗ ∗ ∗ @author A l c i d e s Carlos de Moraes Neto ∗/ public class ServerThread extends Thread { // CLIENT COMMANDS // private s t a t i c final int private s t a t i c final int private s t a t i c final int private s t a t i c final int private s t a t i c final int private s t a t i c final int CMD_SEND_LICENSE = 1 ; CMD_RECV_BUFFERSZ = 2 ; CMD_SEND_NUMFILES = 3 ; CMD_SEND_FILES = 4 ; CMD_RECV_SLEEPTM = 5 ; CMD_BYE = 9 9 ; private final Socket sock ; private final int b u f f e r ; private final String logsPath ; ServerThread ( Socket sock , int b u f f e r , String logsPath ) { this . sock = sock ; this . b u f f e r = b u f f e r ; this . logsPath = logsPath ; } @Override public void run ( ) { i f ( this . sock == null ) { throw new NullPointerException ( " Socket i s n u l l " ) ; } Date now = new Date ( ) ; OutputStream sockOut = null ; DataInputStream sockDataIn = null ; try { System . out . p r i n t l n ( "New connection from " + this . sock . getInetAddress ( ) . getHostAddress ( ) ) ; 82 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 //sockOut = new BufferedOutputStream ( t h i s . sock . getOutputStream ( ) ) ; sockOut = this . sock . getOutputStream ( ) ; sockDataIn = new DataInputStream ( this . sock . getInputStream ( ) ) ; //sockStrIn = new BufferedReader ( new InputStreamReader ( t h i s . sock . getInputStream ( ) ) ); System . out . p r i n t ( " Receiving v e h i c l e l i c e n s e . . . " ) ; sockOut . write (CMD_SEND_LICENSE) ; byte l i c e n s e B y t e s [ ] = new byte [ 8 ] ; sockDataIn . read ( l i c e n s e B y t e s ) ; String l i c e n s e = new String ( l i c e n s e B y t e s ) . trim ( ) ; System . out . p r i n t l n ( " done . Value : " + l i c e n s e ) ; Vehicle v = new VehicleDao ( ) . g e t V e h i c l e ( l i c e n s e ) ; i f ( v == null ) { System . out . p r i n t l n ( " Vehicle not r e g i s t e r e d , c l o s i n g connection . " ) ; this . sock . c l o s e ( ) ; return ; } System . out . p r i n t l n ( " Vehicle : " + v . g e t D e s c r i p t i o n ( ) + " ( i d = " + v . getId ( ) + " ) " ) ; System . out . p r i n t ( " Sending b u f f e r s i z e . . . " ) ; sockOut . write (CMD_RECV_BUFFERSZ) ; sockOut . write ( intToByteArray ( b u f f e r ) ) ; System . out . p r i n t l n ( " done . " ) ; System . out . p r i n t ( " Receiving number o f f i l e s . . . " ) ; sockOut . write (CMD_SEND_NUMFILES) ; int f i l e s Q t = sockDataIn . readInt ( ) ; System . out . p r i n t l n ( " done . Value : " + f i l e s Q t ) ; System . out . p r i n t l n ( " Receiving f i l e s . . . " ) ; 83 94 95 96 97 98 ArrayList <Fi le > f i l e s = new ArrayList <F il e > ( ) ; sockOut . write (CMD_SEND_FILES) ; for ( int i =0; i < f i l e s Q t ; i ++) { //R e c e i v e gz ’ ed f i l e , uncompress and d e l e t e it 99 F i l e gz = new F i l e ( logsPath + " obd_ " + l i c e n s e + " _ " + now . getTime ( ) + " _ " + i + " . csv . gz " ) ; 100 System . out . p r i n t l n ( "New gz f i l e : " + gz . getCanonicalPath ( ) ) ; 101 r e c e i v e F i l e ( sockDataIn , sockOut , gz ) ; 102 F i l e f = uncompressFile ( gz ) ; 103 // i f ( ! gz . d e l e t e ( ) ) { 104 // throw new IOException ( " Could not d e l e t e f i l e " + gz . getCanonicalPath ( ) ) ; 105 // } 106 // Add f i l e s t o a l i s t t o be p r o c e s s e d a f t e r sending bye message t o c l i e n t , 107 // because i t can take a while . 108 f i l e s . add ( f ) ; 109 } 110 111 sockOut . write (CMD_BYE) ; 112 113 for ( F i l e f : f i l e s ) { 114 //Save CSV data do DB and d e l e t e the f i l e 115 storeData ( v , f ) ; 116 if ( ! f . delete ( ) ) { 117 throw new IOException ( " Could not d e l e t e f i l e " + f . getCanonicalPath ( ) ) ; 118 } 119 } 120 121 } catch ( IOException ex ) { 122 System . e r r . p r i n t l n ( " Error during s o c k e t or f i l e IO o p e r a t i o n : " + ex . getLocalizedMessage ( ) ) ; 123 ex . printStackTrace ( ) ; 124 return ; 125 } finally { 126 try { 127 i f ( sockOut != null ) sockOut . c l o s e ( ) ; 128 i f ( sockDataIn != null ) sockDataIn . c l o s e ( ) ; 129 this . sock . c l o s e ( ) ; 84 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 } catch ( Exception ex ) { } } } private byte [ ] intToByteArray ( int value ) { return new byte [ ] { ( byte ) ( value >>> 24) , ( byte ) ( value >> 16 & 0 x f f ) , ( byte ) ( value >> 8 & 0 x f f ) , ( byte ) ( value & 0 x f f ) }; } private void r e c e i v e F i l e ( DataInputStream sockIn , OutputStream sockOut , F i l e f ) throws IOException { FileOutputStream fOut = null ; try { System . out . p r i n t ( " Receiving f i l e s i z e . . . " ) ; int f i l e S i z e = sockIn . readInt ( ) ; System . out . p r i n t l n ( " done . Value : " + f i l e S i z e ) ; // Calculating f i l e p i e c e s int p i e c e s ; int l a s t P i e c e S i z e ; pieces = f i l e S i z e / buffer ; lastPieceSize = f i l e S i z e % buffer ; fOut = new FileOutputStream ( f ) ; Date s t a r t = new Date ( ) ; for ( int i = 0 ; i < p i e c e s ; i ++) { r e c e i v e F i l e P i e c e ( sockIn , sockOut , fOut , i , buffer ) ; } i f ( lastPieceSize > 0) { r e c e i v e F i l e P i e c e ( sockIn , sockOut , fOut , pi ec es , l a s t P i e c e S i z e ) ; } long time = new Date ( ) . getTime ( ) − s t a r t . getTime () ; fOut . c l o s e ( ) ; System . out . p r i n t l n ( " Finished f i l e . Time taken : " + time + "ms" ) ; 85 168 System . out . p r i n t l n ( " Transfer r a t e : " + ( ( ( f l o a t ) f i l e S i z e ) / time ) + " b / ms ( kb / s ) " ) ; } catch ( IOException ex ) { i f ( fOut != null ) { fOut . c l o s e ( ) ; f . delete ( ) ; } throw new IOException ( " F i l e or Socket stream IO Error while r e c e i v i n g f i l e . " , ex ) ; } 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 } private void r e c e i v e F i l e P i e c e ( DataInputStream sockIn , OutputStream sockOut , FileOutputStream fOut , int number , int length ) throws IOException { byte [ ] inBuf = new byte [ length ] ; int bytesRead = 0 ; while ( ( bytesRead = sockIn . read ( inBuf ) ) < length ) { i f ( bytesRead == −1) { throw new IOException ( " Unexpected EOF in s o c k e t input stream . " ) ; } sockOut . write ( intToByteArray ( −1) ) ; } fOut . write ( inBuf ) ; sockOut . write ( intToByteArray ( number ) ) ; } private F i l e uncompressFile ( F i l e gz ) throws IOException { GZIPInputStream gzin = new GZIPInputStream (new FileInputStream ( gz ) ) ; // F i l e f = new F i l e ( gz . getCanonicalPath ( ) . r e p l a c e F i r s t ( " . gz " , " " ) ) ; //Remove . gz e x t e n s i o n F i l e f = new F i l e ( gz . getCanonicalPath ( ) . s u b s t r i n g ( 0 , gz . getCanonicalPath ( ) . length ( ) −3) ) ; FileOutputStream f o u t = new FileOutputStream ( f ) ; int data = gzin . read ( ) ; while ( data != −1) { f o u t . write ( data ) ; data = gzin . read ( ) ; } gzin . c l o s e ( ) ; 86 203 204 205 206 207 fout . close ( ) ; return f ; } private void storeData ( Vehicle v , F i l e f ) throws IOException { CSVReader c s v r = new CSVReader (new FileReader ( f ) ) ; ObdDao obddao = new ObdDao ( getCsvObdColumns ( c s v r . readNext ( ) ) ) ; String [ ] l i n e = c s v r . readNext ( ) ; while ( l i n e != null ) { i f ( ! obddao . storeCsvLine ( v . getId ( ) , l i n e ) ) { System . e r r . p r i n t l n ( " Error s t o r i n g csv l i n e . " ); } l i n e = c s v r . readNext ( ) ; } csvr . close ( ) ; } 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 } II.3 // Get obd column names from csv , without the " obd . " prefix . private String [ ] getCsvObdColumns ( String [ ] csvcolumns ) { int len =0; //Counting " obd . " columns while ( len < csvcolumns . length && csvcolumns [ len ] . startsWith ( " obd . " ) ) len ++; String [ ] toReturn = new String [ len ] ; for ( int i = 0 ; i < toReturn . length ; i ++) { toReturn [ i ] = csvcolumns [ i ] . r e p l a c e F i r s t ( " obd . " , "") ; } return toReturn ; } DbConnector.java 1 /∗ 2 ∗ DbConnector . java 3 ∗ Author : A l c i d e s Carlos de Moraes Neto 87 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 ∗ This f i l e i s part o f OBD Telemetry Server ∗/ package obdTelemetryServer . db ; import import import import import java . s q l . Connection ; java . s q l . DriverManager ; java . s q l . PreparedStatement ; java . s q l . SQLException ; java . s q l . Statement ; /∗∗ ∗ ∗ @author A l c i d e s Carlos de Moraes Neto ∗/ public class DbConnector { private s t a t i c final String Driver " ; private s t a t i c final String l o c a l h o s t / karmonitor " ; private s t a t i c final String private s t a t i c final String DB_DRV = " org . p o s t g r e s q l . DB_URL = " j d b c : p o s t g r e s q l : / / DB_USR = " karmonitor " ; DB_PWD = " karmonitor " ; private Connection conn ; public DbConnector ( ) throws SQLException { this (DB_DRV, DB_URL, DB_USR, DB_PWD) ; } public DbConnector ( String driver , String url , String user , String passwd ) throws SQLException { try { Class . forName ( d r i v e r ) ; conn = DriverManager . getConnection ( url , user , passwd ) ; conn . setAutoCommit ( false ) ; } catch ( ClassNotFoundException ex ) { throw new RuntimeException ( " Could not load DB d r i v e r " + driver , ex ) ; } } @Override protected void f i n a l i z e ( ) throws Throwable { 88 43 44 45 46 47 48 49 50 51 52 53 54 55 conn . r o l l b a c k ( ) ; conn . c l o s e ( ) ; } public void commit ( ) throws SQLException { conn . commit ( ) ; } public Statement createStatement ( ) throws SQLException { return conn . createStatement ( ) ; } public PreparedStatement prepareStatement ( String s q l ) throws SQLException { return conn . prepareStatement ( s q l ) ; } 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 } II.4 /∗∗ ∗ Execute prepared statement t h a t i s an update . ∗ @param s t Prepared statement with a l l f i e l d s s e t ∗ @return t r u e i f the statement e x e c u t i o n r e t u r n s an update ∗ @throws SQLException ∗/ public boolean executePreparedStatementUpdate ( PreparedStatement s t ) throws SQLException { i f ( s t == null ) { throw new NullPointerException ( " PreparedStatement s t i s n u l l . " ) ; } boolean r e s u l t = ! s t . execute ( ) ; st . close ( ) ; return r e s u l t ; } ObdDao.java 1 /∗ 2 ∗ ObdDao . java 3 ∗ Author : A l c i d e s Carlos de Moraes Neto 89 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ∗ This f i l e i s part o f OBD Telemetry Server ∗/ package obdTelemetryServer . db ; import java . math . BigDecimal ; import java . s q l . PreparedStatement ; /∗∗ ∗ ∗ @author A l c i d e s Carlos de Moraes Neto ∗/ public class ObdDao { private String i n s e r t S q l ; private int numObdColumns ; public ObdDao ( String [ ] obdColumns ) { i n s e r t S q l = "INSERT INTO \"OBDGPSDATA\" ( \ " id_vehicle \" , " ; //obd columns from csv i n t o s q l for ( int i = 0 ; i < obdColumns . length ; i ++) { i n s e r t S q l += " \" " + obdColumns [ i ] + " \ " , " ; } i n s e r t S q l += " \" gps_lon \ " , \ " g p s _ l a t \ " , \ " g p s _ a l t \ " ) VALUES ( ? , " ; for ( int i = 0 ; i < obdColumns . length ; i ++) { i n s e r t S q l += " ? , " ; } i n s e r t S q l += " ? , ? , ? ) " ; numObdColumns = obdColumns . length ; System . out . p r i n t l n ( "ObdDao . i n s e r t S q l : " + i n s e r t S q l ) ; } public boolean storeCsvLine ( int v e h i c l e I d , String [ ] l i n e ) { DbConnector db=null ; PreparedStatement s t =null ; try { db = new DbConnector ( ) ; s t = db . prepareStatement ( i n s e r t S q l ) ; st . setInt (1 , vehicleId ) ; // Obd columns are f i r s t in CSV 90 44 45 for ( int i = 0 ; i < numObdColumns ; i ++) { // s t . s e t F l o a t ( i +2 , Float . parseFloat ( l i n e [ i ] ) ); BigDecimal bd = new BigDecimal ( l i n e [ i ] ) ; s t . setBigDecimal ( i +2 , bd ) ; } //gps and t r i p are the l a s t ones s t . s e t F l o a t ( numObdColumns+2 , Float . parseFloat ( l i n e [ l i n e . length −4]) ) ; //gps . lon s t . s e t F l o a t ( numObdColumns+3 , Float . parseFloat ( l i n e [ l i n e . length −3]) ) ; //gps . l a t s t . s e t F l o a t ( numObdColumns+4 , Float . parseFloat ( l i n e [ l i n e . length −2]) ) ; //gps . a l t 46 47 48 49 50 51 52 53 54 boolean r e s u l t = db . executePreparedStatementUpdate ( s t ) ; i f ( r e s u l t ) db . commit ( ) ; return r e s u l t ; } catch ( Exception ex ) { System . e r r . p r i n t l n ( " Error s t o r i n g csv l i n e : " + ex . getLocalizedMessage ( ) ) ; ex . printStackTrace ( ) ; return false ; } 55 56 57 58 59 60 61 62 63 64 } II.5 } Vehicle.java 1 /∗ 2 ∗ V e h i c l e . java 3 ∗ Author : A l c i d e s Carlos de Moraes Neto 4 ∗ This f i l e i s part o f OBD Telemetry Server 5 ∗/ 6 7 package obdTelemetryServer . beans ; 8 9 /∗∗ 10 ∗ 11 ∗ @author A l c i d e s Carlos de Moraes Neto 12 ∗/ 91 13 public class Vehicle { 14 15 private int i d ; 16 private String l i c e n s e ; 17 private String d e s c r i p t i o n ; 18 19 /∗∗ 20 ∗ @return the id 21 ∗/ 22 public int getId ( ) { 23 return i d ; 24 } 25 26 /∗∗ 27 ∗ @param id the id t o s e t 28 ∗/ 29 public void s e t I d ( int i d ) { 30 this . i d = i d ; 31 } 32 33 /∗∗ 34 ∗ @return the l i c e n s e 35 ∗/ 36 public String getLicense ( ) { 37 return l i c e n s e ; 38 } 39 40 /∗∗ 41 ∗ @param l i c e n s e the l i c e n s e t o s e t 42 ∗/ 43 public void s e t L i c e n s e ( String l i c e n s e ) { 44 this . l i c e n s e = l i c e n s e ; 45 } 46 47 /∗∗ 48 ∗ @return the d e s c r i p t i o n 49 ∗/ 50 public String g e t D e s c r i p t i o n ( ) { 51 return d e s c r i p t i o n ; 52 } 53 54 /∗∗ 55 ∗ @param d e s c r i p t i o n the d e s c r i p t i o n t o s e t 56 ∗/ 92 57 58 59 60 61 } II.6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void s e t D e s c r i p t i o n ( String d e s c r i p t i o n ) { this . d e s c r i p t i o n = d e s c r i p t i o n ; } VehicleDao.java /∗ ∗ VehicleDao . java ∗ Author : A l c i d e s Carlos de Moraes Neto ∗ This f i l e i s part o f OBD Telemetry Server ∗/ package obdTelemetryServer . db ; import import import import java . s q l . PreparedStatement ; java . s q l . ResultSet ; java . s q l . SQLException ; obdTelemetryServer . beans . Vehicle ; /∗∗ ∗ ∗ @author A l c i d e s Carlos de Moraes Neto ∗/ public class VehicleDao { public Vehicle g e t V e h i c l e ( String l i c e n s e ) { try { String s q l = "SELECT id , d e s c r i p t i o n FROM \" VEHICLE\" " + " WHERE l i c e n s e = ? " ; DbConnector db = new DbConnector ( ) ; PreparedStatement s t = db . prepareStatement ( s q l ) ; st . setString (1 , license ) ; ResultSet rs = s t . executeQuery ( ) ; Vehicle v = null ; i f ( rs . next ( ) ) { v = new Vehicle ( ) ; v . s e t I d ( rs . g e t I n t ( " i d " ) ) ; v . setLicense ( license ) ; 93 33 v . s e t D e s c r i p t i o n ( rs . g e t S t r i n g ( " d e s c r i p t i o n " ) ); 34 35 36 37 38 39 40 41 42 43 44 } } rs . c l o s e ( ) ; st . close ( ) ; return v ; } catch ( SQLException ex ) { System . out . p r i n t l n ( "SQL EXCEPTION: " + ex . getLocalizedMessage ( ) ) ; throw new RuntimeException ( ex ) ; } } 94 Anexo III Tabelas do banco de dados do servidor Tabelas criadas no banco PostgreSQL, para armazenamento de dados OBD pelo servidor. III.1 1 2 3 4 5 6 7 8 9 10 11 12 Tabela VEHICLE CREATE TABLE "VEHICLE" ( i d s e r i a l NOT NULL, l i c e n s e character ( 7 ) NOT NULL, d e s c r i p t i o n text , CONSTRAINT "VEHICLE_pkey" PRIMARY KEY ( i d ) , CONSTRAINT " VEHICLE_license_key " UNIQUE ( l i c e n s e ) ) WITH ( OIDS=FALSE ); III.2 Tabela OBDGPSDATA 1 2 3 CREATE TABLE "OBDGPSDATA" 4 ( 5 i d _ v e h i c l e integer NOT NULL, 6 g p s _ l a t numeric NOT NULL, 95 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 gps_lon numeric NOT NULL, g p s _ a l t numeric NOT NULL, d t c f r z f integer , −− DTC t h a t caused r e q u i r e d f r e e z e frame data s t o r a g e f u e l s y s integer , −− Fuel system 1 and 2 s t a t u s l o a d _ p c t numeric ( 9 , 6 ) , −− Calculated LOAD Value " temp " integer , −− Engine Coolant Temperature s h r t f t 1 3 numeric ( 9 , 6 ) , −− Short Term Fuel Trim − Bank 1 ,3 l o n g f t 1 3 numeric ( 9 , 6 ) , −− Long Term Fuel Trim − Bank 1 ,3 s h r t f t 2 4 numeric ( 9 , 6 ) , −− Short Term Fuel Trim − Bank 2 ,4 l o n g f t 2 4 numeric ( 9 , 6 ) , −− Long Term Fuel Trim − Bank 2 ,4 f r p integer , −− Fuel Rail Pressure ( gauge ) map integer , −− Intake Manifold Absolute Pressure rpm numeric ( 7 , 2 ) , −− Engine RPM vss integer , −− V e h i c l e Speed Sensor sparkadv numeric ( 3 , 1 ) , −− I g n i t i o n Timing Advance f o r #1 Cylinder i a t integer , −− Intake Air Temperature maf numeric ( 9 , 6 ) , −− Air Flow Rate from Mass Air Flow Sensor t h r o t t l e p o s numeric ( 9 , 6 ) , −− Absolute T h r o t t l e P o s i t i o n a i r _ s t a t integer , −− Commanded Secondary Air Status o 2 s l o c integer , −− Location o f Oxygen Sensors o2s11 numeric ( 6 , 3 ) , −− Bank 1 − Sensor 1/Bank 1 − Sensor 1 Oxygen Sensor Output Voltage / Short Term Fuel Trim o2s12 numeric ( 6 , 3 ) , −− Bank 1 − Sensor 2/Bank 1 − Sensor 2 Oxygen Sensor Output Voltage / Short Term Fuel Trim o2s13 numeric ( 6 , 3 ) , −− Bank 1 − Sensor 3/Bank 2 − Sensor 1 Oxygen Sensor Output Voltage / Short Term Fuel Trim o2s14 numeric ( 6 , 3 ) , −− Bank 1 − Sensor 4/Bank 2 − Sensor 2 Oxygen Sensor Output Voltage / Short Term Fuel Trim o2s21 numeric ( 6 , 3 ) , −− Bank 2 − Sensor 1/Bank 3 − Sensor 1 Oxygen Sensor Output Voltage / Short Term Fuel Trim o2s22 numeric ( 6 , 3 ) , −− Bank 2 − Sensor 2/Bank 3 − Sensor 2 Oxygen Sensor Output Voltage / Short Term Fuel Trim o2s23 numeric ( 6 , 3 ) , −− Bank 2 − Sensor 3/Bank 4 − Sensor 1 Oxygen Sensor Output Voltage / Short Term Fuel Trim o2s24 numeric ( 6 , 3 ) , −− Bank 2 − Sensor 4/Bank 4 − Sensor 2 Oxygen Sensor Output Voltage / Short Term Fuel Trim obdsup integer , −− OBD requirements t o which v e h i c l e i s designed o 2 s l o c 2 integer , −− Location o f oxygen s e n s o r s p t o _ s t a t integer , −− A u x i l i a r y Input Status runtm integer , −− Time Since Engine S t a r t 96 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 m i l _ d i s t integer , −− Distance T r a v e l l e d While MIL i s Activated f r p r numeric ( 7 , 3 ) , −− Fuel Rail Pressure r e l a t i v e t o manifold vacuum frpd integer , −− Fuel Rail Pressure ( d i e s e l ) lambda11 numeric ( 8 , 7 ) , −− Bank 1 − Sensor 1/Bank 1 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage lambda12 numeric ( 8 , 7 ) , −− Bank 1 − Sensor 2/Bank 1 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage lambda13 numeric ( 8 , 7 ) , −− Bank 1 − Sensor 3 /Bank 2 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage lambda14 numeric ( 8 , 7 ) , −− Bank 1 − Sensor 4 /Bank 2 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage lambda21 numeric ( 8 , 7 ) , −− Bank 2 − Sensor 1 /Bank 3 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage lambda22 numeric ( 8 , 7 ) , −− Bank 2 − Sensor 2 /Bank 3 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage lambda23 numeric ( 8 , 7 ) , −− Bank 2 − Sensor 3 /Bank 4 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage lambda24 numeric ( 8 , 7 ) , −− Bank 2 − Sensor 4 /Bank 4 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Voltage e g r _ p c t numeric ( 9 , 6 ) , −− Commanded EGR e g r _ e r r numeric ( 9 , 6 ) , −− EGR Error evap_pct numeric ( 9 , 6 ) , −− Commanded Evaporative Purge f l i numeric ( 9 , 6 ) , −− Fuel Level Input warm_ups smallint , −− Number o f warm−ups s i n c e d i a g n o s t i c t r o u b l e codes c l e a r e d c l r _ d i s t integer , −− Distance s i n c e d i a g n o s t i c t r o u b l e codes c l e a r e d evap_vp numeric ( 6 , 2 ) , −− Evap System Vapour Pressure baro smallint , −− Barometric Pressure lambdac11 numeric ( 1 1 , 8 ) , −− Bank 1 − Sensor 1/Bank 1 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current 97 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 lambdac12 numeric ( 1 1 , 8 ) , −− Bank 1 − Sensor 2/Bank 1 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current lambdac13 numeric ( 1 1 , 8 ) , −− Bank 1 − Sensor 3/Bank 2 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current lambdac14 numeric ( 1 1 , 8 ) , −− Bank 1 − Sensor 4/Bank 2 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current lambdac21 numeric ( 1 1 , 8 ) , −− Bank 2 − Sensor 1/Bank 3 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current lambdac22 numeric ( 1 1 , 8 ) , −− Bank 2 − Sensor 2/Bank 3 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current lambdac23 numeric ( 1 1 , 8 ) , −− Bank 2 − Sensor 3/Bank 4 − Sensor 1 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current lambdac24 numeric ( 1 1 , 8 ) , −− Bank 2 − Sensor 4/Bank 4 − Sensor 2 ( wide range O2S) Oxygen Sensors Equivalence Ratio ( lambda ) / Current catemp11 numeric ( 5 , 1 ) , −− C a t a l y s t Temperature Bank 1 / Sensor 1 catemp21 numeric ( 5 , 1 ) , −− C a t a l y s t Temperature Bank 2 / Sensor 1 catemp12 numeric ( 5 , 1 ) , −− C a t a l y s t Temperature Bank 1 / Sensor 2 catemp22 numeric ( 5 , 1 ) , −− C a t a l y s t Temperature Bank 2 / Sensor 2 vpwr numeric ( 8 , 3 ) , −− Control module v o l t a g e load_abs numeric ( 9 , 6 ) , −− Absolute Load Value lambda numeric ( 8 , 7 ) , −− Fuel/ a i r Commanded Equivalence Ratio tp_r numeric ( 9 , 6 ) , −− R e l a t i v e T h r o t t l e P o s i t i o n aat smallint , −− Ambient a i r temperature tp_b numeric ( 9 , 6 ) , −− Absolute T h r o t t l e P o s i t i o n B tp_c numeric ( 9 , 6 ) , −− Absolute T h r o t t l e P o s i t i o n C app_d numeric ( 9 , 6 ) , −− A c c e l e r a t o r Pedal P o s i t i o n D app_e numeric ( 9 , 6 ) , −− A c c e l e r a t o r Pedal P o s i t i o n E app_f numeric ( 9 , 6 ) , −− A c c e l e r a t o r Pedal P o s i t i o n F t a c _ p c t numeric ( 9 , 6 ) , −− Commanded T h r o t t l e Actuator Control mil_time integer , −− Time run by the engine while MIL activated 98 82 83 84 85 86 87 c l r _ t i m e integer , −− Time s i n c e d i a g n o s t i c t r o u b l e codes cleared f u e l _ t y p e smallint , −− Fuel Type a l c h _ p c t numeric ( 9 , 6 ) , −− Ethanol f u e l % " time " numeric NOT NULL, CONSTRAINT "OBDGPSDATA_pkey" PRIMARY KEY ( i d _ v e h i c l e , " time " ) , CONSTRAINT " OBDGPSDATA_id_vehicle_fkey " FOREIGN KEY ( id_vehicle ) REFERENCES "VEHICLE" ( i d ) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION 88 89 90 ) 91 WITH ( 92 OIDS=FALSE 93 ) ; 99