Gráficos de status de sensores conectados à Internet das Coisas IoT
Uma das vantagens de conectar uma rede de sensores à Internet das Coisas é poder analisar os dados obtidos. Ao representar graficamente esta informação, uma pessoa (ao contrário de um programa) pode compreender de forma mais intuitiva o significado das quantidades monitorizadas, por exemplo, comparando-as entre si ou acompanhando a sua evolução ao longo do tempo.
Este artigo inicia uma série, composta por quatro partes, que explica uma proposta simples de representação gráfica de dados obtidos por sensores conectados à IoT. Com a mesma filosofia de outros artigos, o método sugerido é perfeitamente funcional embora o objetivo principal seja didático. Conforme o perfil técnico do público ao qual o blog polaridad.es, e este texto é sobre eletrônica e não sobre desenvolvimento web, cada uma das seções serve como uma introdução às linguagens ou tecnologia utilizadas: HTML, APF, SVG y JavaScript.
Os artigos da série anterior sobre como armazenar dados obtidos por dispositivos conectados à Internet das Coisas (IoT) Terminaram explicando como acessar as informações armazenadas nos bancos de dados. Nos exemplos da série, para facilitar o processo, foi utilizado como intermediário um servidor web que era responsável por receber os dados através de solicitações POST do protocolo HTTP, armazená-los em um banco de dados e exibi-los em uma página web.
Embora a principal desvantagem deste sistema seja o desempenho (que poderia ser amenizado com alternativas como Node.js e MongoDB, que serão explicadas em artigos futuros), em troca oferece duas grandes vantagens: sua implementação é muito simples (incluindo a disponibilidade de serviços públicos) e pode exibir os dados em um navegador, ou seja, não necessita de aplicativos específicos (como um aplicativo para dispositivo móvel) para apresentar as informações armazenadas que representariam o status histórico dos dispositivos conectados à Internet do Coisas.
Explorando a vantagem de poder apresentar facilmente numa página web a informação que foi armazenada com este sistema sobre o estado dos dispositivos ligados à IoT, este artigo explica como apresentar graficamente esta informação utilizando o formato SVG de JavaScript para gerar dinamicamente uma página da web em HTML.
Existem muitas livrarias JavaScript com o qual resolver a apresentação gráfica dos dados. Estes artigos não pretendem desenvolver outro; O objetivo deste texto é entender o processo e poder desenvolver suas próprias implementações; objetivo didático e também produtivo. Se você estiver interessado em usar um produto em vez de desenvolvê-lo sozinho, recomendo que dê uma olhada em algumas das excelentes bibliotecas para geração de gráficos com JavaScript com licenças gratuitas como Gráficos.js, Highcharts, Ferramentas de gráficos do Google, Época, Raphaël, gráfico (baseado Raphaël), dc.js, Cartista.js, D3.js (minha recomendação), C3.js (baseado D3.js), NVD3 (gráficos reutilizáveis para D3.js) ...
Estrutura de documento HTML com gráficos SVG
Na proposta deste artigo de apresentar graficamente os dados dos sensores, a página web na qual eles são exibidos é composta por:
- o documento que serve de contêiner é escrito em HTML,
- a aparência da página é definida com código APF,
- o desenho do gráfico é feito utilizando a linguagem SVG y
- A leitura dos dados do servidor e a exibição dos gráficos são programadas em JavaScript
Todos os elementos, especialmente o código HTML da página, pode ser gerado no servidor com PHP conforme explicado no artigo sobre o Linguagem de programação PHP da série sobre armazenamento de dados de dispositivos conectados à Internet das Coisas.
O código APF y JavaScript pode ser carregado (importado) em código HTML em vez de ser escrito diretamente como parte do documento HTML. Isto tem a vantagem de poder reutilizar os mesmos documentos em várias páginas e poder editá-los com mais comodidade; mas talvez o inconveniente de demorar um pouco mais para carregar dependendo se você pode usar o código contido no cache (carregado no uso anterior) ou até mesmo um CDN. Na fase de produção é trivial integrar todo o código do PHP, gerando um único documento em HTML com todas as informações se você escolher esta alternativa. Ao longo desta série de artigos, para maior clareza, considera-se que estamos trabalhando com documentos separados.
Para os fins que nos interessam, utilizá-lo como contentor gráfico e, de forma muito aproximada, o conteúdo do primeiro nível da estrutura de um documento HTML seria:
1
2
3
4
5
6
7
|
<!DOCTYPE html>
<html lang=“es”> <!– El código del documento HTML está escrito en español –>
<head>
</head>
<body onload=“funcion();”>
</body>
</html>
|
A primeira linha serve para indicar ao navegador que o documento que está lendo está escrito em HTML, especificamente na versão 5 (conhecida como HTML5). Versões anteriores de HTML, baseado em SGML (Standard Generalized Markup Language), incluiu uma definição de tipo de documento (DTD) em que foi declarado o tipo de regras utilizadas na linguagem para descrever o documento.
A segunda e última linhas contêm o código HTML entre as diretrizes <html>
y </html>
que funcionam como abertura e fechamento respectivamente. As diretivas HTML Eles colocam o nome e os atributos entre os sinais “menor que” e “maior que” formando uma espécie de sinais de “parênteses agudos”. Os elementos HTML que incluem conteúdo têm uma diretiva de fechamento que inclui a barra na frente do nome, como em </html>
.
As propriedades ou atributos dos elementos são separados por espaços do nome e entre si e são expressos como texto simples ou, mais frequentemente, como texto (o nome da propriedade) seguido de um sinal de igual e um valor entre aspas. No caso da diretiva de abertura de código HTML propriedade foi usada lang
com a coragem es
, lang="es"
para indicar que o texto do documento HTML usa a língua espanhola.
Um comentário foi incluído após a diretiva de abertura do código HTML. Os comentários em HTML Podem ocupar várias linhas e usar o código como sinal de abertura <!--
e como fechamento -->
O código HTML É composto por dois blocos: o cabeçalho <head>
e o corpo <body>
. A primeira visa informar sobre o documento em si, incluindo informações sobre ele (meta-informação) e a segunda é dar suporte ao conteúdo do documento.
Na diretiva <body>
um evento foi incluído onload
com o qual executar automaticamente uma função JavaScript assim que o conteúdo for carregado. Este recurso permite iniciar a execução do código que irá definir os objetos gráficos e atualizá-los à medida que são carregadas informações do servidor sobre o estado dos sensores que representam esses gráficos.
De todas as metainformações que podem ser incluídas no cabeçalho do documento HTML, estamos especialmente interessados em conhecer aquele descrito pelas seguintes diretivas:
-
<title>
que serve para dar um título ao documento. Normalmente aparecerá na janela do navegador ou na aba correspondente e nos ajudará a identificar os gráficos que contém. -
<charset>
declara o conjunto de caracteres usado para codificar o documento. É especialmente importante para sinais “especiais”, como eñes ou acentos. -
<link>
permite estabelecer uma relação entre o documento HTML atuais e outros externos. Isso nos ajudará a carregar a folha de estilos no formato APF com a aparência do documento. -
<script>
contém um script com código executável. Usando esta diretiva carregaremos as funções JavaScript com o qual gerar ou modificar gráficos SVG.
1
2
3
4
5
6
7
8
9
10
11
|
<!DOCTYPE html>
<html lang=“es”> <!– El código del documento HTML está escrito en español… –>
<head>
<meta charset=“utf-8”> <!– …y codificado en el juego de caracteres UTF-8 –>
<title>Gáfico SVG de sensores conectados a la IoT</title>
<link href=“https://polaridad.es/grafica-sensor-internet-de-las-cosas-iot/aspecto.css” type=“text/css” rel=“stylesheet” media=“all”>
<script src=“graficos.js” type=“text/javascript”></script>
</head>
<body onload=“funcion();”>
</body>
</html>
|
Como pode ser visto no exemplo de HTML acima, o nome (e caminho, se aplicável) do documento com o estilo APF é indicado com o atributo href
, enquanto no caso do código JavaScript veja um src
. Ambos compartilham propriedade type
com a coragem text/css
y text/javascript
respectivamente.
Com relação ao conteúdo do documento, a parte que corresponde ao elemento <body>
, HTML5 Permite criar estruturas específicas para os componentes mais frequentes de uma página web como rodapé, seção lateral ou barra de navegação, mas o que nos interessa é utilizar o documento como contêiner gráfico. SVG são os elementos <div>
que funcionam como blocos independentes que permitem definir uma estrutura hierárquica aninhando alguns <div>
dentro de outros.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!DOCTYPE html>
<html lang=“es”> <!– El código del documento HTML está escrito en español… –>
<head>
<meta charset=“utf-8”> <!– …y codificado en el juego de caracteres UTF-8 –>
<title>Gáfico SVG de sensores conectados a la IoT</title>
<link href=“https://polaridad.es/grafica-sensor-internet-de-las-cosas-iot/aspecto.css” type=“text/css” rel=“stylesheet” media=“all”>
<script src=“graficos.js” type=“text/javascript”></script>
</head>
<body onload=“funcion();”>
<div id=“padre” class=“aspecto_de_padre”>
<div id=“primer_hijo” class=“aspecto_de_hijo”>
</div>
<div id=“segundo_hijo” class=“aspecto_de_hijo”>
</div>
</div>
</body>
</html>
|
No exemplo anterior, um elemento é usado <div>
que contém outros dois. Este exemplo introduz duas propriedades muito importantes para o uso que queremos fazer do código. HTML: id
que é usado para atribuir um identificador exclusivo a um elemento HTML (A <div>
, neste caso) e class
com o qual é atribuída uma categoria que utilizaremos para estabelecer a aparência. A categoria, a classe, não tem de ser única, aliás, grande parte da sua eficácia reside em vários elementos que partilham o mesmo aspecto.
O elemento (ou tag) <p>
serve para definir um parágrafo que normalmente conterá texto (embora em HTML não há limitação a esse respeito). Para fazer agrupamentos dentro de um parágrafo (ou uma <div>
, também não há limitações) a tag é usada <span>
. Com este elemento é possível, por exemplo, incluir texto dentro de um parágrafo para dar-lhe uma aparência diferente, como sublinhado ou negrito.
A definição das características gráficas e em geral, o comportamento que está associado a um elemento HTML A atribuição de uma classe é feita no código APF; no caso do exemplo anterior no documento aspecto.css
.
Para otimizar a atribuição de características APF é possível que o mesmo elemento HTML pertence a diversas classes e portanto tem a aparência ou comportamento definido por elas. Para fazer esta atribuição, escreva os nomes das diferentes classes, separando-as por vírgulas à direita da propriedade. class
9
10
11
12
13
14
15
16
|
<body onload=“funcion();”>
<div id=“padre” class=“aspecto_de_padre”>
<div id=“primer_hijo” class=“aspecto_de_hijo aspecto_raro tipografia_grande”>
</div>
<div id=“segundo_hijo” class=“aspecto_de_hijo”>
</div>
</div>
</body>
|
No exemplo anterior, o elemento <div>
que foi identificado como primer_hijo
Três classes foram atribuídas: aspecto_de_hijo
, aspecto_raro
y tipografia_grande
, que juntos devem definir a aparência e o comportamento do elemento. Como explicado no seguinte artigo sobre o Definindo a aparência da Web dos gráficos do sensor IoT com CSS, ao utilizar múltiplas classes, se alguma das propriedades que definem o aspecto estiver definida em ambas, prevalece a última referenciada.
Como foi visto, os elementos <div>
Podem conter outros elementos, incluindo outros <div>
. Um caso mais simples seria <div>
que continha texto. O visual que define o estilo APF também afetaria o texto contido no elemento.
Para otimizar a atribuição de características APF é possível que o mesmo elemento HTML pertence a diversas classes e portanto tem a aparência ou comportamento definido por elas. Para fazer esta atribuição, escreva os nomes das diferentes classes, separando-as por vírgulas à direita da propriedade. class
9
10
11
12
13
14
15
16
17
|
<body onload=“funcion();”>
<div id=“padre” class=“aspecto_de_padre”>
<div id=“primer_hijo” class=“aspecto_de_hijo aspecto_raro tipografia_grande”>
Este hijo de aspecto raro tiene la tipografía grande
</div>
<div id=“segundo_hijo” class=“aspecto_de_hijo”>
</div>
</div>
</body>
|
No exemplo anterior, as três classes associadas ao <div>
primer_hijo
Eles definiriam a aparência do elemento e do texto que o contém, por exemplo, tornando a fonte em que está escrito grande (se a finalidade indicada pelo seu nome na última classe for verdadeira)
Desde a versão 5 (HTML5) é possível incluir o código gráfico no formato SVG dentro do próprio código HTML como mais um elemento. Do ponto de vista do código HTML, o conteúdo SVG é um elemento <svg>
que contém os diferentes elementos gráficos (linhas, círculos, retângulos...
9
10
11
12
13
14
15
16
17
18
19
20
|
<body onload=“funcion();”>
<div id=“padre” class=“aspecto_de_padre”>
<div id=“primer_hijo” class=“aspecto_de_hijo aspecto_raro tipografia_grande”>
Este hijo de aspecto raro tiene la tipografía grande
</div>
<div id=“segundo_hijo” class=“aspecto_de_hijo”>
<svg id=“dibujo” class=“grafico” width=“100%” height=“100%” viewBox=“0 0 100 100” preserveAspectRatio=“none”>
<circle cx=“100” cy=“200” r=“50”>
</svg>
</div>
</div>
</body>
|
Embora tenha sido dito que as características gráficas dos elementos HTML são definidos em um estilo APF e estão associados a ele através de uma classe, também é possível atribuir alguns deles diretamente aos elementos de duas maneiras. Por um lado, você pode usar a propriedade style
e atribuir as diferentes características gráficas do objeto como seu valor. Logicamente é preferível utilizar a técnica citada de atribuir o aspecto a uma classe, mas com esta possibilidade você pode adicionar uma pequena correção a um elemento (uma exceção muito particular) sem ter que criar uma nova classe.
Por outro lado, alguns elementos HTML Eles permitem usar propriedades específicas que definem sua aparência. Em geral, mesmo que existam estas propriedades, é preferível utilizar classes mas, infelizmente, nem todos os elementos oferecem esta alternativa, alguns esperam que um determinado valor seja indicado diretamente com essas propriedades específicas em vez de se referir à classe associada. Um dos elementos que possuem esse tipo de comportamento é justamente o código SVG, ao qual devemos atribuir o valor percentual da largura e altura nas propriedades width
y height
, respectivamente, em vez da classe.
Como será visto com mais detalhes no artigo que fala sobre código SVG, para utilizar o método simples proposto, é aconselhável considerar as dimensões do gráfico como porcentagens. No caso do tamanho total do objeto, ao indicar 100% no valor da largura e altura, será o container que define as dimensões finais (o <div>
com id="dibujo"
, no exemplo anterior)
No caso dos diferentes componentes do gráfico SVG (linhas, círculos, retângulos...), são incluídos em uma área que mede 100×100 (qualquer unidade) e se expandem em formato retangular sem preservar a proporção. As propriedades viewBox
y preserveAspectRatio
do elemento SVG Eles são responsáveis por estabelecer esses valores. no primeiro caso com uma vista retangular que vai do ponto coordenado (0,0) ao ponto coordenado (100,100) e é expressa como "0 0 100 100"
e na segunda com o valor none
.
14
15
16
17
18
|
<div id=“segundo_hijo” class=“aspecto_de_hijo”>
<svg viewBox=“0 0 100 100” preserveAspectRatio=“none” width=“100%” height=“100%” id=“dibujo” class=“grafico”>
<circle cx=“100” cy=“200” r=“50”>
</svg>
</div>
|
Com tudo isso, agora você pode definir um código completo que serviria como um contêiner gráfico. SVG gerado ou modificado a partir de JavaScript. O exemplo abaixo contém quatro blocos gráficos que utilizam o formato HTML da proposta de representação que vamos utilizar.
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
40
41
42
43
44
45
46
47
48
49
50
51
|
<!DOCTYPE html>
<html lang=“es”> <!– Inicio del documento HTML con el idioma –>
<head> <!– Cabecera del documento HTML –>
<meta charset=“utf-8”> <!– Se utiliza el juego de caracteres UTF8 –>
<title>Temperaturas Nave E1</title> <!– Título del documento y seguramente de la ventana del navegador –>
<link rel=“stylesheet” href=“https://polaridad.es/grafica-sensor-internet-de-las-cosas-iot/estilo.css” type=“text/css” media=“all”> <!– Cargar el estilo “https://polaridad.es/grafica-sensor-internet-de-las-cosas-iot/estilo.css” guardado en la misma carpeta que este documento HTML –>
<script type=“text/javascript” src=“graficos.js”></script> <!– Cargar el código JavaScript del documento “graficos.js” guardado en la misma carpeta que este documento HTML –>
</head> <!– Final de la cabecera del documento HTML –>
<body onload=“iniciar_graficos();”> <!– Cuerpo del documento HTML. Al cargar el contenido llama a la función JavaScript iniciar_graficos() –>
<div id=“temperatura_frigorifico_a” class=“bloque_sensor”> <!– Bloque de datos del primer sensor –>
<div id=“titulo_temperatura_frigorifico_a” class=“bloque_titulo”>Temperatura frigorífico 01A</div> <!– Título del bloque de datos del sensor –>
<div id=“descripcion_temperatura_frigorifico_a” class=“bloque_descripcion”>Media de las sondas de temperatura del frigorífico 01A</div> <!– Descripción del bloque de datos del sensor –>
<div id=“fecha_temperatura_frigorifico_a” class=“bloque_fecha”>Cargando emperaturas</div> <!– Fecha de la última lectura de datos del sensor. Por ahora vacío, luego se rellenará con la aplicación JavaScript –>
<div id=“bloque_temperatura_frigorifico_a” class=“bloque_grafico”> <!– Bloque con el gráfico –>
<svg id=“grafico_temperatura_frigorifico_a” class=“grafico” width=“100%” height=“100%” viewBox=“0 0 100 100” preserveAspectRatio=“none”>
<path id=“linea_temperatura_frigorifico_a” d=“” style=“fill:none;stroke:#205587;stroke-width:4;stroke-opacity:1;” vector-effect=“non-scaling-stroke” />
</svg> <!– Gráfico de los datos –>
</div> <!– Final del bloque que contiene el gráfico –>
</div> <!– Final del bloque de datos del primer sensor –>
<div id=“temperatura_frigorifico_b” class=“bloque_sensor”>
<div id=“titulo_temperatura_frigorifico_b” class=“bloque_titulo”>Temperatura frigorífico 01B</div>
<div id=“descripcion_temperatura_frigorifico_b” class=“bloque_descripcion”>Media de las sondas de temperatura del frigorífico 01B</div>
<div id=“fecha_temperatura_frigorifico_b” class=“bloque_fecha”>Cargando emperaturas</div>
<div id=“bloque_grafico_temperatura_frigorifico_b” class=“bloque_grafico”>
<svg id=“grafico_temperatura_frigorifico_b” class=“grafico” width=“100%” height=“100%” viewBox=“0 0 100 100” preserveAspectRatio=“none”>
<path id=“linea_temperatura_frigorifico_b” d=“” style=“fill:none;stroke:#205587;stroke-width:4;stroke-opacity:1;” vector-effect=“non-scaling-stroke” />
</svg>
</div>
</div>
<div id=“temperatura_frigorifico_c” class=“bloque_sensor”>
<div id=“titulo_temperatura_frigorifico_c” class=“bloque_titulo”>Temperatura frigorífico 01C</div>
<div id=“descripcion_temperatura_frigorifico_c” class=“bloque_descripcion”>Media de las sondas de temperatura del frigorífico 01C</div>
<div id=“fecha_temperatura_frigorifico_c” class=“bloque_fecha”>Cargando emperaturas</div>
<div id=“bloque_grafico_frigorifico_c” class=“bloque_grafico”>
<svg id=“grafico_temperatura_frigorifico_c” class=“grafico” width=“100%” height=“100%” viewBox=“0 0 100 100” preserveAspectRatio=“none”>
<path id=“linea_temperatura_frigorifico_c” d=“” style=“fill:none;stroke:#205587;stroke-width:4;stroke-opacity:1;” vector-effect=“non-scaling-stroke” />
</svg>
</div>
</div>
<div id=“temperatura_frigorifico_d” class=“bloque_sensor”>
<div id=“titulo_temperatura_frigorifico_d” class=“bloque_titulo”>Temperatura frigorífico 01D</div>
<div id=“descripcion_temperatura_frigorifico_d” class=“bloque_descripcion”>Media de las sondas de temperatura del frigorífico 01D</div>
<div id=“fecha_temperatura_frigorifico_d” class=“bloque_fecha”>Cargando emperaturas</div>
<div id=“bloque_grafico_frigorifico_d” class=“bloque_grafico”>
<svg id=“grafico_temperatura_frigorifico_d” class=“grafico” width=“100%” height=“100%” viewBox=“0 0 100 100” preserveAspectRatio=“none”>
<path id=“linea_temperatura_frigorifico_d” d=“” style=“fill:none;stroke:#205587;stroke-width:4;stroke-opacity:1;” vector-effect=“non-scaling-stroke” />
</svg>
</div>
</div>
</body> <!– Final del cuerpo del documento HTML –>
</html> <!– Final del documento HTML –>
|
Abaixo você pode ver como ficaria o código anterior, formatado com o estilo APF correspondente, gerando com JavaScript os gráficos SVG com leituras de servidores de dados armazenados por sensores conectados à IoT. Só que os dados não estão sendo carregados do servidor, mas sim gerados aleatoriamente no cliente (seu navegador), o restante do código é o que será utilizado na proposta definida nesta série de artigos.
O próximo artigo desta série explica como definir estilos CSS para dar aparência ao código HTML que atua como um contêiner para os gráficos SVG com o qual representar o estado dos sensores conectados à Internet das Coisas (IoT).
comentário 1