De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.


Gráficos usando GNUPlot e PHP

Colaboração: Rogério Acquadro

Data de Publicação: 04 de Janeiro de 2006

Recentemente tive que desenvolver uma pequena aplicação, responsável por capturar dados de leituras de temperatura e umidade relativa de salas climatizadas e fazer um tratamento estatístico dos dados. O software responsável pela captura das leituras (que não foi escrito por mim, é proprietário) gera um arquivo CSV, com atualização de hora em hora, com todos os dados de todos os sensores.

A dificuldade estava em automatizar, de uma maneira prática e simples, a geração dos gráficos e estatísticas para os dados em questão. Decidi que usar uma interface web seria a melhor opção. Não requer nenhum software instalado no cliente (como seria o caso de usar essa ou aquela planilha de cálculo).

Infraestrutura

São, no total, três computadores envolvidos nesta solução, obviamente todos ligados em rede. O primeiro deles é um computador velho, sucateado, que faz apenas a leitura dos dados. Trata-se de um Pentium 200, rodando Windows 95 e com o software proprietário de captura dos dados. Este computador está ligado via RS232 aos sensores e é dessa maneira que são feitas as leituras dos dados.

O segundo é o servidor da aplicação. Sua função é acessar o computador de captura, ler os últimos dados, registrá-los em um banco de dados e abrigar a aplicação web.

O terceiro computador é o cliente, que necessita apenas de um navegador de Internet. A observação é que o cliente pode ter qualquer navegador de internet com qualquer sistema operacional.

Softwares utilizados

Além do software proprietário que faz a captura dos dados, foram utilizados os seguintes softwares:

  • Pequenos scripts em shell script para fazer o tratamento dos dados e a injeção no banco de dados;
  • Samba para fazer a comunicação e transferência dos dados entre a o computador de aquisição de dados e o servidor;
  • MySQL para armazenagem dos dados;
  • PHP para desenvolvimento da aplicação;
  • GNUPlot para geração dos gráficos;
  • Um navegador de Internet no computador cliente.

Passo a Passo

O primeiro passo é fazer a captura dos dados. Para isso, foi escrito um pequeno script ("captura"):

  1  #!/bin/bash
  2
  3  cd /tmp
  4  mount -t smbfs -o username=acervo,password=acervo //terminal/c /mnt/extra
  5  mv /mnt/extra/dados/dado.csv /tmp
  6  umount /mnt/extra
  7  /opt/climatizacao/gera_sql /tmp/dados.csv | mysql climatizacao
  8  rm /tmp/dados
  9  rm /tmp/*.bak

Analizando linha a linha, começamos com a linha 4 que faz a conexão com o computador de aquisição de dados via samba. A linha 5 copia o arquivo de dados para o diretório temporário (ele na verdade move o arquivo. Assim, na próxima vez que o software for escrever novos dados, criará um novo arquivo, sem que aja a duplicação de dados). A linha 7 invoca o segundo script que trata os dados do arquivo CSV e insere dentro do MySQL.

O segundo passo é fazer o tratamento do arquivo CSV e injetar os dados no banco de dados. Isso é feito utilizando o segundo script ("gera_sql"), invocado na linha 7 do script "captura":

  1 #!/bin/bash
  2
  3 dos2unix -a $1
  4 sed -e s/\;//g $1 | sed -e 's|/| |' |  sed -e 's|/| |' |\
    awk {'print "insert into traineis values \
    (\"\"\, \"20"$3"-" $1 "-"$2"\"\, \""$4 "\"\,
    \""$8 "\"\,  \""$9 "\"\,  \""$10 "\"\,  \""$11"\"); \n\
  5 insert into exterior values 
    (\"\"\, \"20"$3"-" $1 "-"$2"\"\, 
    \""$4 "\"\, \""$12 "\"\,  \""$13 "\"\,  
    \""$14 "\"\,  \""$15"\");\n\
  6 insert into climatizada values
    (\"\"\, \"20"$3"-" $1 "-"$2"\"\, 
    \""$4 "\"\, \""$16 "\"\,  \""$17 "\"\,
    \""$18 "\"\,  \""$19"\");\n\
  7 insert into sala_3 values 
    (\"\"\, \"20"$3"-" $1 "-"$2"\"\, \""$4 "\"\,
    \""$20 "\"\,  \""$21 "\"\,  \""$22 "\"\,
    \""$23"\");\n\
  8 insert into audiovisual values
    (\"\"\, \"20"$3"-" $1 "-"$2"\"\, \""$4 "\"\,
    \""$24 "\"\,  \""$25 "\"\,  \""$26 "\"\,  \""$27"\");\n\
  9 insert into armario values
    (\"\"\, \"20"$3"-" $1 "-"$2"\"\, 
    \""$4 "\"\, \""$28 "\"\,  \""$29"\");\n\
  10 insert into arcondicionado values
     (\"\"\, \"20"$3"-" $1 "-"$2"\"\, 
     \""$4 "\"\, \""$30 "\"\,  \""$31 "\"\,
     \""$32 "\"\,  \""$33 "\"\,  \""$34"\");"'}

A linha 3 faz uma pequena conversão de formatos de arquivo texto (necessário dado o comando para quebra de linha ser diferente entre *NIX e Windows). A 4a. linha faz a separação dos dados (separados por vírgula). Mais do que isso, a 4a. linha faz ainda o tratamento da data (que é gerada do tipo dd/mm/aa e o SQL apenas reconhece aaaa-mm-dd). As linhas de 5 a 10 são as linhas de injeção de dados no SQL.

Injetados os dados no banco de dados, cabe ao aplicativo PHP fazer a leitura deles. Graças as funções estatísticas do MySQL, pode-se gerar rapidamente cálculos como média +- desvio padrão, máximos e mínimos, entre outros. A grande dificuldade está na geração do gráfico de umidade e temperatura.

Depois de muito pesquisar bibliotecas prontas para gerar gráficos em PHP (nenhuma me soou muito satisfatória), resolvi enfrentar o desafio de usar o GNUPlot (excelente ferramenta da qual já sou familiar há tempos) junto com o PHP.

Para isso, escrevi o programa graph.php, que passado o nome do sensor e as datas de início e fim, ele é capaz de gerar o gráfico de temperatura e umidade.

  1  $sensor = $_GET['sensor'];
  2  $limite1 = $_GET['limite1'];
  3  $limite2 = $_GET['limite2'];
  4  $size = $_GET['size'];
  
  5  if (($limite1 != NULL) && ($limite2 != NULL))
  6          $limite = "where data >= '$limite1' and data <= '$limite2'";
  
  7  $filename = round(time() / 10 * rand(1,10));
  8  $filename = "/tmp/".$filename;
  
  9  if ($size == "small")
  10          $term = "png size 640,480";
  
  11  if ($size == "big")
  12          $term = "png size 950,712";
  
  13  $query = "select data, hora, temp, ur from $sensor $limite order by data, hora";
  14  $result = mysql_query($query);
  15  $rows = mysql_num_rows($result);
  16  if ($rows > 720)
  17          $passo = 10;
  18  elseif ($rows > 360)
  19          $passo = 5;
  20  else
  21          $passo = 1;
  
  22  for ($i = $rows - 1; $i >= 0; $i = $i - $passo)
  23  {
  24
  25     $x = mysql_result($result, $i, "data") . "-" . mysql_result($result, $i, "hora");
  26     $y1 = mysql_result($result, $i, "temp");
  27     $y2 = mysql_result($result, $i, "ur");
  28     $command = "echo $x $y1 $y2 >> $filename";
  29     exec ($command);
  30  }
  
  31  $command = "echo \"set ylabel \\\"Temperatura (celsius)\\\"; 
      set y2label \\\"Umidade Relativa (%)\\\"; set xlabel \\\"Data\\\";
      set grid; set y2tics; set term $term; set xdata time; 
      set timefmt \\\"%Y-%m-%d-%H:%M\\\"; 
      plot \\\"$filename\\\" using 1:2 axis x1y1 title \\\"Temp\\\" with lines,
      \\\"$filename\\\" using 1:3 axis x1y2 title \\\"UR\\\" with lines \" | gnuplot";
  32  header("Content-type: image/png");
  33  passthru($command);
  34  $command = "rm $filename";
  35  exec ($command);
  

As linhas de 1 a 4 fazem a leitura dos parâmetros. As linhas 7 e 8 geram um nome aleatório para o arquivo temporário de dados que será lido pelo GNUPLot. As linhas de 9 a 12 definem o tamanho do gráfico (em pixels). As linhas 13 e 14 fazem a conexão com o banco de dados. As linhas 16 a 21 fazem a triagem dos dados (dependendo do período que se deseja, o banco de dados possui mais de 3.000 pontos, o que deixava o programa um pouco lento. Como não havia necessidade de tantos pontos, o período foi dividido para que ficasse mais de acordo com o propósito do gráfico). As linhas de 22 a 30 fazem a leitura dos dados e a escrita deles no arquivo temporário. A linha 31 é o comando em sintaxe GNUPlot para que faça a formatação do gráfico, leitura dos dados e desenho dos pontos. A linha 32 envia ao navegador a informação que a saída será um arquivo PNG. A linha 33 faz a geração do gráfico (executa os comandos da linha 31). As linhas 34 e 35 apagam o arquivo texto temporário.

Para chamar o "grap.php", basta colocar em um arquivo HTML a chamada como se fosse um arquivo gráfico:

  <img src=\"graph.php?sensor=$sensor&limite1=$limite1&limite2=$limite2&size=small\"
  title=\"Gráfico de temperatura e umidade relativa para $sensor\" border=\"0\">
  

O resultado deste software é brilhante. Um gráfico gerado em segundos, extremamente leve (o gráfico mais pesado que gerei não passa de 15 kbytes).

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Rogério Acquadro