Beruflich Dokumente
Kultur Dokumente
Abstract: Este trabalho apresenta projeto prático que aborda a tecnologia de Internet
das Coisas (Internet of Things - Iot) através da plataforma Intel Galileo Gen 1 e tem como
objetivo o monitoramento remoto de telemetria a partir da implementação de um servidor
web que mostre dados relativos a sensores de temperatura de luminosidade em uma página
HTML com uma determinada frequência, além de mostrar hora e contagem numérica da
leitura.
1 Introdução 1
3 O Yocto Project 3
4 Sensores 4
4.1 Sensor de Luminosidade LDR 4
4.2 Sensor de temperatura 5
5 Fase 1 5
5.1 O Servidor Web 5
5.1.1 O Socket 6
5.1.2 Outras Funções Primitivas 6
5.1.3 O Código do Servidor Web 7
6 Fase 2 7
6.1 Comunicação TCP/IP 7
6.2 Funções Extras Utilizadas 8
6.3 O Código para Comunicação TCP/IP 8
7 Fase 3 8
A Apêndice 9
1 Introdução
–1–
tanto para estudantes, quanto para profissionais, para que sejam criadas novas possibilida-
des e soluções para movimentação desse mercado, como por exemplo, a Intel
R que com o
desenvolvimento da Plataforma Intel Galileo Gen 1 vem sendo visionária nesta tecnologia.
Neste trabalho busca-se desenvolver de maneira prática esse tipo de tecnologia a partir
de um projeto que será dividido em três fases, utilizando a Plataforma supracitada.
Na Fase 1, se busca fazer com que O Galileo monitore a temperatura e a luminosidade
do ambiente, além de se criar um servidor Web no Galileo, que fique aguardando conexões
na porta 80, que possa ser acessada por um Cliente Web de qualquer lugar na Internet,
onde as leituras dos valores são continuamente atualizadas em uma página que indique o
horário da leitura e o número da leitura em relação às leituras anteriores.
Na Fase 2, busca-se que os valores lidos de temperatura e luminosidade sejam enviados
para um servidor, que irá armazena-los em um arquivo texto. Para isso, busca-se desenvolver
um programa cliente TCP que irá enviar o arquivo ao servidor, esse que com um programa
servidor desenvolvido utilizando a biblioteca Sockets, recebe e armazena os dados em um
arquivo texto, esse que possui uma linha para cada leitura, sendo a primeira coluna para
hora, a segunda para a temperatura e a terceira para luminosidade. Tudo isso desenvolvido
com um protocolo para transmissão dos dados.
A metodologia empregada para elaboração desse projeto seguiram os seguintes passos:
- Pesquisar e definir sensores que mais se adequam as necessidades do projeto, bem
como verificar a necessidade de circuitos adicionais;
- comprar e testar o funcinamento dos sensores;
- pesquisar através de datasheets e manuais do usuário sobre Intel Galileo Gen 1 e
estudar exemplos para melhor copreensão de seu funcionamento;
- instalar o Yocto no cartão SD;
- pesquisar e desenvolver código de servidor web em C;
- pesquisar e desenvolver código para leitura dos pinos analógicos, bem como bibliotecas
ou fórmulas a serem empregadas para a conversão do sinal dos sensores, além de integrar
com o código servidor;
- desenvolver código HTML;
- pesquisar principais funções e desenvolver Socket Cliente/Servidor em C que atenda
as especificações do projeto.
–2–
o suporte para integração com shields para Arduino Uno que tem por padrão 5V. Além
disso, observa-se também que essa plataforma possui compatibilidade em software com o
ambiente de desenvolvimento Arduino.
Além de compatibilidade em hardware e software com Arduino, a plataforma Galileo
tem compatibilidade com vários padrões de E/S da indústria de PCs e recursos para ex-
pandir o uso e capacidades para ir muito além do "ecossistema"Arduino, possuindo, slots
para mini-PCI Express, para Ethernet e para micro-SD, além de porta serial RS-232, USB
Host, USBClient e uma memória NOR flash de 8MBytes, sendo uma plataforma versátil e
atrativa tanto para estudantes como para profissionais.
O hardware está funcionando com uma versão atualizada do sistema operacional Yocto
criado para a plataforma Intel Galileo instalado em um cartão microSD. Para fazer a comu-
nicação com a placa, optou-se por usar SSH para acessar o usuário root@galileo e controlar
o sistema operacional remotamente. Além disso, os arquivos de código são escritos e envi-
ados para a placa por FTP usando o aplicativo gratuito Filezilla, com isso os códigos são
compilados no próprio sistema operacional embarcado.
3 O Yocto Project
O Yocto Project é um projeto de colaboração open source que provê ferramentas, modelos
e métodos para ajudar a criar sistemas personalizados baseados em Linux embarcado, de
forma idependente da arquitetura de hardware, o que possibilita o uso de processadores de
variadas plataformas, como ARM, MIPS, PowerPC and x86 e x86-64 [2].
Os componentes do projeto Yocto podem ser usados para projetar, desenvolver, cons-
truir, debugar, simular e testar completamente uma pilha de software embarcado composta
pelo Kernel do Linux, o sistema Linux, X Window System, GNOME Mobile-based appli-
cation frameworks, e o Qt frameworks.
Teve sua fundação em 2010 em colaboração com vários fabricantes de hardware, for-
necedores de sistemas operacionais open source e empresas de eletrônicos na tentativa de
organizar o desenvolvimento do Linux embarcado.
No processo de desenvolvimento o Yocto é formado por diversas partes. Essas partes
são nomeadas como projetos dentro do Yocto e incluem ferramentas de criação, metadados
de instruções de criação chamados de receitas, bibliotecas, utilitários e interfaces gráficas
com o usuário [3].
Ele prove um Kernel Linux atual, com um conjunto de comandos de sistemas e bibliote-
cas adaptados para o uso em ambientes embarcados. Disponibiliza componentes de sistema
como X11, GTK+, Qt, Clutter, e SDL de modo a se permitir a construção de interface
gráfica configurável para os hardwares de display. Além de criar um núcleo compatível com
o projeto OpenEmbedded que pode ser extensível e distribuído.O projeto também fornece
um plug-in Eclipse IDE.
–3–
4 Sensores
Para realização desse projeto à priori foram especificados dois sensores, esses que serão
descritos a seguir. (Código 4)
LUX ANALOG
0 350
33 590
70 690
140 750
280 820
520 882
–4–
Figura 1. Gráfico comparando Lux com os sinais analógicos recebidos pela placa
5 Fase 1
–5–
usualmente são páginas web, tais como documentos HTML com objetos embutidos, como
imagens ou podem um computador que executa um programa que provê a funcionalidade
supracitada.
Os servidores web são responsáveis por armazenar e trocar informações com outras
máquinas [6]. Logo, pelo menos dois entes são envolvidos em cada troca de informações,
sendo um o cliente, que solicita informações, e outro, o servidor, que atende a esses pedidos.
Os pedidos http que se referem habitualmente a páginas HTML são normalmente feitos
por meio de browsers. O processo inicializa com a conexão entre o computador onde está
instalado o servidor web e o computador do cliente.
Então, é processado o pedido do cliente, e conforme as restrições de segurança e a
existência da informação solicitada, o servidor devolve os dados, ou po-se dizer tudo o que
se enquadre no conceito de ficheiro pode ser enviado como resultado de um pedido http.
Sendo esse o tipo de servidor utilizado nessa fase, esse que para o desenvolvimento
de seu código necessita-se do conhecimento de algumas das funções primitivas que serão
descritas na sequência.
5.1.1 O Socket
O acesso aos serviços da camada de transporte pode ser feito por primitivas de transporte,
essas primitivas são denominadas SOCKET [7]. Por meio dessas primitivas é possível
acessar vários protocolos da camada de transporte, dentre eles TCP e UDP.
Os Sockets garantem a intercomunicação bidirecional entre processos,esses sendo exe-
cutados localmente ou em máquinas conectadas através de uma LAN/WAN.
Todos os Sockets criados utilizam endereços para fazerem referências entre si. O espaço
de possíveis endereços é chamado domínio.
No caso de sockets, alguns exemplos de domínios podem ser conferidos a seguir:
AF_UNIX - endereço é composto por um caminho dentro do sistema de arquivos.
Utilizado quando os processos rodam em uma mesma máquina;
AF_INET - O endereço é composto pelo endereço de rede da máquina (IP) e o número
de identificação da porta que está sendo utilizada pelo processo.
Os tipos mais comuns são:
SOCK_STREAM - indica que os dados irão trafegar pelo socket na forma de um stream
de caracteres.
SOCK_DGRAM - indica que os dados irão trafegar pelo socket na forma de datagra-
mas.
–6–
Listen - Torna o processo servidor apto a aceitar conexões dos clientes, aloca uma
fila de espera para conexões pendentes. Se a fila já foi alocada mostra o seu tamanho.
Parâmetros: o descritor do socket e o tamanho máximo da fila de conexões pendentes.
Caso seja solicitada conexão e a fila de espera estiver cheia é enviada uma mensagem de
erro ao solicitante.
Accept - Faz com que um processo servidor permaneça bloqueado até que uma soli-
citação de conexão seja feita. Parâmetros: o descritor do socket, um ponteiro para uma
estrutura que endereça o solicitante da conexão e um inteiro que informa o tamanho dessa
estrutura.
Connect - Solicita uma conexão ao servidor, bloqueia o processo até que a conexão seja
estabelecida. Parâmetros: o descritor do socket, ponteiro para estrutura com o endereço
destino e o tamanho da estrutura. Essa primitiva deve ser executada por um processo
cliente para estabelecer comunicação com o servidor.
Send ou Write -Envia dados pela conexão para a entidade destino. Parâmetros: o
descritor do socket, ponteiro para o buffer com os dados a serem enviados, o tamanho do
buffer, códigos de condição especiais (normalmente 0).
Receive ou Read - Recebe dados da conexão. Parâmetros: o descritor do socket, pon-
teiro para uma estrutura onde os dados recebidos podem ser colocados, o tamanho da
estrutura, códigos de condição especiais (normalmente 0).
Close - Termina a conexão. Como o encerramento da conexão é simétrico apenas
quando ambos os processos tiverem executado essa primitiva a conexão será terminada.
Parâmetros: o descritor do socket e códigos de término (normalmente 0).
6 Fase 2
Essa segunda fase tem por objetivo que os valores aferidos de temperatura e luminosidade
sejam enviados para um servidor, esse que irá armazená-los em um arquivo texto. Para
isso, um programa cliente TCP irá enviar o arquivo ao servidor, esse que com um programa
servidor desenvolvido utilizando a biblioteca Sockets, recebe e armazena os dados em um
arquivo texto, esse que possui uma linha para cada leitura, sendo a primeira coluna para
hora, a segunda para a temperatura e a terceira para luminosidade. Tudo isso desenvolvido
com um protocolo para transmissão dos dados.
–7–
Neste projeto, o cliente vai enviar um conjunto de dados contendo horário e valores de
temperatura e luminosidade e o servidor os salvará em um arquivo de texto.
Para o desenvolvimento do código dessa etapa foi necessário a utilização de novas
funções, essas que serão descritas a seguir.
7 Fase 3
–8–
A Apêndice
Código 1 WebServer
1 #include<stdio.h> //Biblioteca Basica #include<string.h> //Biblioteca Basica
2 #include<stdlib.h> //Biblioteca Basica
3 #include<unistd.h> // Biblioteca para constantes simbolicas como NULL
4 #include<netdb.h> //Biblioteca para operacoes de base de dados na internet
5 #include<signal.h> // Biblioteca para receber e manipular sinais
6 #include<fcntl.h> //Biblioteca para controle de opcoes de arquivos - O_RDONLY
7 #include<sys/types.h> //Biblioteca para manipular dados e threads
8 #include<sys/stat.h> //Biblioteca para usar a funcao stat
9 #include<sys/socket.h> //Biblioteca para o uso de sockets
10 #include<arpa/inet.h> //Biblioteca para operacoes na internet
11 #define MAX 5000 // Número máximo de conexões do servidor
12 #define BYTES 1024 // Tamanho máximo da mensagem a ser enviada do servidor para o cliente
13
–9–
43 {
44 addrlen = sizeof(clientaddr);
45 clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);
46
47 if (clients[slot]<0)
48 error ("erro no accept() ");
49 else
50 {
51 //processo de forks para cada cliente conectado, executa a funcao resposta
52 if ( fork()==0 )
53 {
54 resposta(slot);
55 exit(0);
56 }
57 }
58
62 }
63
64 return 0;
65 }
66
67 //inicia servidor
68
– 10 –
83 // funcoes socket e bind
84 for (p = res; p!=NULL; p=p->ai_next)
85 {
86 listenfd = socket (p->ai_family, p->ai_socktype, 0);
87 if (listenfd == -1) continue;
88 if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break;
89 }
90 if (p==NULL)
91 {
92 perror ("erro no socket() ou no bind()");
93 exit(1);
94 }
95
96 freeaddrinfo(res);
97
98 // funcao listen
99 if ( listen (listenfd, 1000000) != 0 )
100 {
101 perror("erro no listen()");
102 exit(1);
103 }
104 }
105
– 11 –
115
116
135 }
136
137 }
138
139
– 12 –
Código 2 Cliente TCP
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <netdb.h>
9 #include <time.h>
10
13
27 segAux=61;
28
29 while(1){
30
31
32 // Definição de variáveis
33 int seg;
34 struct tm *local;
35 time_t t;
36 // Para obter o horário e data atual do sistema
37 t = time(NULL);
38 local=localtime(&t);
– 13 –
40 // dia=local->tm_mday;
41 // mes=local->tm_mon+1;
42 // ano=local->tm_year+1900;
43
46 if(seg!=segAux){
47 segAux = seg;
48 // checkando argumentos passados
49 if (argc != 3) {
50 fprintf(stderr,"uso da %s <hostname> <port>\n", argv[0]);
51 exit(0);
52 }
53 hostname = argv[1];
54 portno = atoi(argv[2]);
55
56 // hostname = "192.168.0.191";
57 // portno = 2000;
58
– 14 –
77
82
83 bzero(buf, BUFSIZE);
84
92 }
93 else{}
94 }
95
96
97
98 }
– 15 –
Código 3 Servidor TCP
1 // * tcpserver.c
2
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <netdb.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12
15 // endereço da Internet
16 struct in_addr {
17 unsigned int s_addr;
18 };
19
30
– 16 –
37 char **h_addr_list; /* list of addresses */
38 }
39 #endif
40
41 // *erro
42
63 if (argc != 2) {
64 fprintf(stderr, "usando: %s <port>\n", argv[0]);
65 exit(1);
66 }
67 portno = atoi(argv[1]);
68
69
– 17 –
77 // que nos permite executar o servidor imediatamente após matá-lo;
78 // Caso contrário, temos que esperar cerca de 20 segundos.
79
80
81 optval = 1;
82 setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR,
83 (const void *)&optval , sizeof(int));
84
85 //
86 // constroi o servidor web
87 //
88 bzero((char *) &serveraddr, sizeof(serveraddr));
89
99 //
100 // bind: associa o socket pai com a porta
101 //
102 if (bind(parentfd, (struct sockaddr *) &serveraddr,
103 sizeof(serveraddr)) < 0)
104 error("ERRO no binding");
105
106 //
107 // listen: prepara o socket para aceitar requisição de conecção
108 //
109 if (listen(parentfd, 5) < 0) /*permite 5 requests para a fila */
110 error("ERRO no listen");
111
112 //
113 // main loop: espera por uma requisição de conecção, da linha de entrada echo,
114 // tentão fecha a conecção.
115 //
116 clientlen = sizeof(clientaddr);
117 int cont = 0;
118 while (1) {
119
120 //
– 18 –
121 // accept: espera por requisição de conecção.
122 //
123 childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen);
124 if (childfd < 0)
125 error("ERRO no accept");
126
127
140
146
147 fprintf(stdout,"%s",buf);
148
– 19 –
163 else {
164 fseek ( pFile , (cont*24)+2*cont , SEEK_SET );// Procura no arquivo na posição
165 fputs ( buf , pFile );// Substitui por
166 fseek ( pFile , (cont*24)+24+2*cont , SEEK_SET );// Procura no arquivo na posição
167 fputs ( ";\n" , pFile );// Substitui por"
168 }
169 fclose ( pFile );// Fecha arquivo
170 cont=cont+1;
171
172 if (n < 0)
173
176 // close(childfd);
177 }
178 }
– 20 –
Código 4 Código dos Sensores
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5 #include "mraa.h"
6 int horario[2];
7
17 // Verificação de conteúdo
18 if (adc_a0 == NULL) {
19 return 1;
20 }
21
22 // Leitura do pino A0
23 luxSensor = mraa_aio_read(adc_a0);
24
– 21 –
39 else if (luxSensor>690 && luxSensor<=750){
40 luxSensor = luxSensor*1.166666667 - 690*1.166666667 + 70;
41 }
42 else if (luxSensor>750 && luxSensor<=830){
43 luxSensor = luxSensor*1.75 - 750*1.75 + 140;
44 }
45 else if (luxSensor>830){
46 luxSensor = luxSensor*4.61538461538461 - 830*4.61538461538461 + 280;
47 }
48
– 22 –
77 FILE * pFile; // Define pFile como arquivo
78 pFile = fopen ( "index.html" , "r+" );
79 // Abre o arquivo index.html com tipo de acesso r+
80 fseek ( pFile , 406 , SEEK_SET ); // Procura no arquivo a posição 406
81 fputs ( luxSensorStr , pFile ); // Substitui por "espaço"
82 fclose ( pFile ); // Fecha arquivo
83
108 // dia=local->tm_mday;
109 // mes=local->tm_mon+1;
110 // ano=local->tm_year+1900;
– 23 –
111
116 horario[0]=hor;
117 horario[1]=min;
118 horario[2]=seg;
119 }
120
121 // Função que envia o Horário atual no tipo String para o index.html
122 void enviaHora(int hor, int min, int seg, int cont){
123 // Definição de variáveis
124 int horPos,minPos,segPos;
125 horPos = 0;
126 minPos = 3;
127 segPos = 6;
128 char diac[5],mesc[5],anoc[8],horc[5],minc[5],segc[5];
129 // Conversão de Integer para String
130 // snprintf(diac, 10, "%d", dia);
131 // snprintf(mesc, 10, "%d", mes);
132 // snprintf(anoc, 10, "%d", ano);
133 snprintf(horc, 10, "%d", hor);
134 snprintf(minc, 10, "%d", min);
135 snprintf(segc, 10, "%d", seg);
136
137 // Para reoganizar as posições de horário caso hora, min, seg esteja entre
138 // 0 e 9, para ser exibido assim 19:05:09 invés de 19:5 :9 .
139 if (hor<10){
140 int i;
141 for(i=4;i>0;i--){
142 horc[i] = horc[i-1];
143 }
144 horc[0] = ’0’;
145 }
146 if (min<10){
147 int i;
148 for(i=4;i>0;i--){
149 minc[i] = minc[i-1];
150 }
151 minc[0] = ’0’;
152 }
– 24 –
153 if (seg<10){
154 int i;
155 for(i=4;i>0;i--){
156 segc[i] = segc[i-1];
157 }
158 segc[0] = ’0’;
159 }
160
189 }
190
– 25 –
191 // Função que le o valor do Sensor de Temperatura do Galileo
192 int leTemp(void){
193 // Define variáveis
194 char scale[4];
195 char raw[4];
196 char offset[4];
197 int raw_i;
198 int scale_i;
199 int offset_i;
200
– 26 –
229 // Conversão de Char para Integer
230 raw_i = atoi(raw);
231 scale_i = atoi(scale);
232 offset_i = atoi(offset);
233
241 }
242
243 // Função que envia o valor de Temperatura no tipo String para o index.html
244 void enviaTemp(int temp, int cont) {
245 // Define variáveis
246 char tempc[5];
247 int tempPos = 14;
248
272 }
– 27 –
273
300 if (cont<10){
301 fseek ( pFile , 465 , SEEK_SET ); // Procura no arquivo a posição
302 fputs ( " " , pFile ); // Substitui por "espaços"
303 }
304 else if (cont<100){
305 fseek ( pFile , 466 , SEEK_SET ); // Procura no arquivo a posição
306 fputs ( " " , pFile ); // Substitui por "espaços"
307 }
308 else if (cont<1000){
309 fseek ( pFile , 467 , SEEK_SET ); // Procura no arquivo a posição
310 fputs ( " " , pFile ); // Substitui por "espaços"
311 }
312 else if (cont<10000){
313 fseek ( pFile , 468 , SEEK_SET ); // Procura no arquivo a posição
314 fputs ( " " , pFile ); // Substitui por "espaços"
315 }
316 fclose ( pFile ); // Fecha arquivo
317 }
– 28 –
319 // Função Principal
320 int main()
321 {
322 // Define variável para Lux
323 int luxSensorInt, tempInt, auxCont, cont;
324 // Contador inicia em zero
325 cont = 0;
326 // Le a hora atual e atualiza a variavel global horario
327 leHora();
328 // Armazena os segundos do horario atual para variavel auxiliar
329 auxCont = horario[2];
330
331
332 // Loop infinito para envio dos valores dos Sensores e Horário atual
333 for (;;) {
334 if (verificaMedicao(auxCont) == 1){
335
359 }
360 else{
361 leHora();
362 // Espera atualizar a variavel global horario para comparação com auxCont
363 }
364 }
365
366 }
– 29 –
Código 5 Código da página HTML
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8"/>
5 <meta http-equiv="refresh" content="1; url=index.html">
6 <p>Servidor WEB Galileo</p>
7 <h1 style="color: #5e9ca0; text-align: center;"><strong>Servidor WEB GALILEO YOCTO
8 </strong></h1>
9 <p> </p><h1 style="color: #5e9ca0; text-align: center;"><strong>Temperatura:
10 __ °
11 C</strong></h1><h1 style="color: #5e9ca0; text-align: center;"><strong>Luminosidade:
12 ___ lux<br />
13 <br />Medição de número:______
14 <br />Horário:__:__:__</strong></h1>
15 <p> </p><p> </p><p><strong>
16 <img style="display: block; margin-left: auto; margin-right: auto;"src=
17 "http://www.embarcados.com.br/wp-content/uploads/2014/03/galileo2.png"
18 alt="" width="229"height="99" />
19 <img style="display: block; margin-left: auto; margin-right: auto;" src=
20 "http://www.ufpr.br/portalufpr/wp-content/uploads/2015/11/ufpr_alta.jpg"
21 alt="" width="172"
22 height="116" />
23 </strong></p><p style="text-align: center;"> </p><p><strong>
24 <img style="display: block; margin-left: auto; margin-right: auto;"src=
25 "http://www.yoctoproject.org/docs/current/yocto-project-qs/figures/
26 yocto-project-transp.png"
27 alt="Yocto" width="208" height="79" /></strong></p>
28 </html>
– 30 –
Referências
[1] F. K. Santoso, Securing IoT for Smart Home System. Singapore: IEEE, 2015.
[2] “Yocto project,” October 2016, https://www.yoctoproject.org/about.
[3] “Introdução do projeto yocto,” Outubro 2016,
http://www.decom.ufop.br/imobilis/projeto-yocto-introducao-ao-m2m/.
[4] “Como funcionam os sensores fotoelétricos,” Outubro 2016,
http://www.newtoncbraga.com.br/index.php/como-funciona/4883-art644.
[5] “Web developer notes,” October 2016, http://www.webdevelopers.com/what-is-web-server.
[6] “Como funciona um servidor web,” Outubro 2016,
http://portaleducacao.com.br/informatica/artigos/17165/como-funciona-um-servidor-web.
[7] “Sockets,” October 2016, http://www.inf.pucrs.br/ fldotti/redes/982/sockets.htm.
– 31 –