Tutorial: Configurar e criar uma dashboard no Grafana usando ESP8266 e MQTT

Neste tutorial vou explicar como configurar e instalar os serviços para coletar, armazenar e visualizar os dados de um sensor Arduino/ESP8266

O interessante desse tutorial é que vamos trabalhar com diversos conceitos e softwares, numa visão ampla de como podemos nos comunicar no ambiente IoT.
Vamos abordar os seguintes tópicos:

  • MQTT (Eclipse Mosquitto)
  •  InfluxDB
  • Telegraf
  • Grafana

O que é MQTT?

O protocolo MQTT (MQ Telemetry Transport) é um protocolo extremamente simples e leve desenvolvido para comunicação de dispositivos de baixa banda, grande latência ou pouca confiabilidade.

Eclipse Mosquitto será o servidor escolhido para a comunicação entre nossa aplicação e o sensor, propriamente dito.
Para entender o Mosquitto, vou introduzir basicamente como ele funciona, os conceitos de Broker, Subscribe, Publisher e Topic. Isso é o bastante por hora.

Vamos supor que você tenha dois dispositivos IoT, por exemplo, um ar condicionado e um sensor de temperatura, e você queira conectar os dois.
No ar condicionado você precisa receber as informações da temperatura na casa (ou fora dela). Além disso, precisamos também enviar valores como voltagem interna do ar, a quanto tempo ele está ligado, e termos acesso a isso por meio de um celular, por exemplo.
Já no sensor de temperatura, você não precisa receber nenhum valor, apenas enviar a temperatura, para que estes valores sejam acessados pelo ar condicionado ou qualquer outro dispositivo.

Nesse exemplo, o ar condicionado seria um subscribe (recebe os valores de um determinado tópico, neste caso a temperatura) e publish (envia valor do tempo ligado).
No Mosquitto isso é extremamente simples de ser feito

Instalar o Mosquitto

Vamos instalar o Mosquitto em um Raspberry Pi, porém você pode criar o servidor em windows ou em qualquer outro SO.
Você pode fazer o download no link https://mosquitto.org/download/

Para instalar no Rasbian você entra com os comandos:

wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key

Fazemos agora o repositório disponivel no apt

cd /etc/apt/sources.list.d/

Agora adicionamos as dependências

sudo wget http://repo.mosquitto.org/debian/mosquitto-wheezy.list
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list

Atualizamos as informações e instalamos o pacote

apt-get update
apt-get install mosquitto

Por padrão o mosquitto ja vem pré-configurado. Caso você queira alterear essas configurações, você deve editar o arquivo /etc/mosquitto/mosquitto.conf. Mais detalhes você encontra na documentação https://mosquitto.org/man/mosquitto-conf-5.html

Publish e Subscribe

Vamos criar nosso primeiro teste de Publish e Subscribe.
As mensagens no MQTT são publicadas em tópicos. Não existe necessidade de configurar cada tópico, publicar nele já é o bastante.

A estrutura dos tópicos são divididas numa hieraquia semelhante a diretórios: sensors/COMPUTER_NAME/temperature/HARD_DRIVE_01

Sendo assim, podem existir diversos tópicos, para diferentes sensores e dispositivos. Caso voce queira ouvir todos os tópicos em uma determinada camada, voce pode acionar o caractere # ou +
Subscrever por exemplo no topico: sensors/COMPUTER_NAME/temperature/#
recebe todas a mensagens publicadas na hierarquia
sensors/COMPUTER_NAME/temperature/

Mais informações você pode conferir na documentação do Mosquitto

Para “ouvir” uma mensagem vamos usar o comando mosquitto_sub

mosquitto_sub -h localhost -t "sensor/temperatura"

Os parâmetros usados:
-h: Hostname
-t: Tópico

Até aqui você não vai receber nada no terminal. Vamos então abrir uma nova janela e publicar uma mensagem no tópico sensor/temperatura e ver se a comunicação está mesmo funcionando.

mosquitto_pub -h localhost -t "sensor/temperatura" -m "valor:15.5"

Ótimo! Já temos nosso servidor MQTT funcionando. Caso você queira também pode baixar um aplicativo chamado MQTT Dash e receber os dados pelo celular. Lembre-se que caso você queira habilitar o servidor para acesso externo, você tem que fazer um port forward no seu roteador. A porta padrão do Mosquitto é a porta 1883.

Criando aplicação no ESP8266

Agora vamos criar uma aplicação no ESP8266 que leia os valores de temperatura e pressão de um módulo BMP180 e envie esses valores para o nosso broker.
O código é bem simples e você pode fazer o download aqui. Lembre-se de fazer os downloads das bibliotecas. No comentário do código fonte você encontra os links

// This example uses an ESP8266 Board
// to connect to MQTT and send BMP180 data
// BMP180 wiring:
// SCL -> D1
// SDA -> D2
//
// MQTT library: https://github.com/256dpi/arduino-mqtt
// Adafruit_BMP085: https://github.com/adafruit/Adafruit-BMP085-Library
// by Hugo Rezende

#include <Adafruit_BMP085.h>
#include <ESP8266WiFi.h>
#include <MQTT.h>

#ifndef STASSID
#define STASSID "yourWifiSSID"
#define STAPSK  "yourWifiPassword"
#endif

const char* ssid     = STASSID;
const char* password = STAPSK;
WiFiClient net;
MQTTClient client;
Adafruit_BMP085 bmp;

unsigned long lastMillis = 0;
uint8_t LED_Pin = D4;

void connect() {
  Serial.print("Checking wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    //Blink the led until wifi connects
    digitalWrite(LED_Pin, HIGH); // Turn the LED on
    delay(50);                
    digitalWrite(LED_Pin, LOW);// Turn the LED off
    delay(50); 
    delay(100);
  }
  Serial.print("\nConnecting...");
  while (!client.connect("arduino", "try", "try")) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("\nConnected!");
}

void messageReceived(String &amp;topic, String &amp;payload) {
  Serial.println("incoming: " + topic + " - " + payload);
}

void setup() {
  pinMode(LED_Pin, OUTPUT); 
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  
  if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    while (1) {}
  }
  // Connecting to the MQTT server
  // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
  // You need to set the IP address directly.
  client.begin("192.168.0.100", 1883 ,net); // here you insert the IP/domain of the MQTT server and the port
  connect();
}

void loop() {
  client.loop();
  delay(10);  // fixes some issues with WiFi stability

  if (!client.connected()) {
    connect();
  }

  // publish a message roughly every second.
  if (millis() - lastMillis > 1000) {
    lastMillis = millis();
    // sending values to topics in a JSON format
    client.publish("sensor/temperatura", "{\"value\": "+ String(bmp.readTemperature()) +"}" );
    client.publish("sensor/pressao", "{\"value\": "+ String(bmp.readSealevelPressure()) +"}" );
  }
}

Assim que o codigo for carregado no ESP8266, ele já começará a enviar as leituras para o MQTT. Note aqui que é importante configurar corretamente o IP do seu Raspberry (ou da máquina que esteja rodando o Mosquitto) na linha client.begin(“192.168.0.10”, 1883 ,net);

Agora é só rodar o terminal, e subscrever no tópico, que você ja começa a ver os dados no terminal.

mosquitto_sub -h localhost -t 'sensor/temperatura'

InfluxDB

Para fazer a persistência dos dados e conectar o Grafana, vamos usar o InflluxDB que é um banco de dados desenvolvido especialmente para armazenamento de time-serie data.
Para instalar siga os comandos:

curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add - echo "deb https://repos.influxdata.com/debian stretch stable" | sudo tee /etc/apt/sources.list.d/influxdb.list

Depois instalamos o Influx

sudo apt update
sudo apt -y install influxdb

Agora vamos iniciar o Influx e criar os usuários no banco de dados.

sudo service influxdb start
influx -execute "CREATE USER "telegraf" WITH PASSWORD 'suasenhatelegraf' WITH ALL PRIVILEGES;"
influx -execute "CREATE USER "grafana" WITH PASSWORD 'suasenhagrafana' WITH ALL PRIVILEGES;"

Instalando Telegraf

Precisamos de um client que receba os dados do nosso servidor MQTT e persista no InfluxDB. Para isso existe um plugin chamado Telegraf que após configurado faz isso de forma automática.

sudo apt -y install telegraf

Você pode fazer o download direto aqui

Agora temos que configurar o Telegraf para capturar as mensagens dos tópicos. Para isso devemos abrir o arquivo /etc/telegraf/telegraf.conf 
Na linha [[inputs.mqtt_consumer]] você deve descomentar as seguintes linhas, e inserir os tópicos que deseja ouvir:

[..]
 # Read metrics from MQTT topic(s)
 [[inputs.mqtt_consumer]]
   servers = ["localhost:1883"]
   ## MQTT QoS, must be 0, 1, or 2
   qos = 0

   ## Topics to subscribe to
   topics = [
     "sensor/temperatura",
     "sensor/pressao",
   ]

[..]
   data_format = "json"
[..]

Devemos cadastrar os tópicos que vamos conectar e setar o data_format como JSON (existem outros formatos e você pode ver aqui). Como nosso servidor MQTT não requer nenhuma autenticação, nao é necessario inserir nada na parte de usuário/senha, mas você pode estudar a documentação do Mosquitto e introduzir essa feature.

Outra parte que devemos alterar são os dados de autenticação que o Telegraf irá utilizar para salvar os dados no Influx:

# Configuration for influxdb server to send metrics to                          
[[outputs.influxdb]]                                                            
  ## The HTTP or UDP URL for your InfluxDB instance.  Each item should be       
  ## of the form:                                                               
  ##   scheme "://" host [ ":" port]                                            
  ##                                                                            
  ## Multiple urls can be specified as part of the same cluster,                
  ## this means that only ONE of the urls will be written to each interval.     
  # urls = ["udp://localhost:8089"] # UDP endpoint example                      
  urls = ["http://localhost:8086"] # required                                   
  ## The target database for metrics (telegraf will create it if not exists).   
  database = "esp8266" # required                                              
                                                                                
  ## Name of existing retention policy to write to.  Empty string writes to     
  ## the default retention policy.                                              
  retention_policy = ""                                                         
  ## Write consistency (clusters only), can be: "any", "one", "quorum", "all"   
  write_consistency = "any"                                                     
                                                                                
  ## Write timeout (for the InfluxDB client), formatted as a string.            
  ## If not provided, will default to 5s. 0s means no timeout (not recommended).
  timeout = "5s"                                                                
  username = "telegraf"                                                       
  password = "suasenhatelegraf"                                   
  ## Set the user agent for HTTP POSTs (can be useful for log differentiation)  
  # user_agent = "telegraf"                                                     
  ## Set UDP payload size, defaults to InfluxDB UDP Client default (512 bytes)  
  # udp_payload = 512                                                           
 [...]

As partes importantes são URL, database, timeout, username e password. Lembre-se de utilizar a mesma senha que você usou ao criar o usuario no InfluxDB.

A próxima etapa é testar o influxdb e o telegraf e conferir se os dados estão sendo armazenados. Após salvar as configurações você deve reiniciar os serviços:

sudo service influxdb restart
sudo service telegraf restart

Agora você pode verificar se os serviços estão rodando:

sudo service influxdb status
sudo service telegraf status

Ambos os serviços estão rodando normalmente.
Se o seu ESP8266 está conectado e enviando os valores para o servidor MQTT, você pode conferir se já suas medições estão de fato aramazenadas no InfluxDB. Para isso você deve iniciar o Influx, escolher o banco de dados e checar as informações.
Para isso vamos entrar no terminal do Influx:

influx
>SHOW DATABASES

Caso o banco de dados “esp8266” nao apareca voce deve cria-lo:

CREATE DATABASE esp8266
No meu caso, o nome do meu banco de dados é telegraf
USE esp8266
SHOW MEASUREMENTS

Quando você entrar com a query SHOW MEASUREMENTS, se todas as configurações estiverem corretas, você deve ver uma tabela de medições chamada mqtt_consumer. Isso indica que está tudo certo, o ultimo passo é criar a dashboard no Grafana.

Configurando Grafana para receber os dados do MQTT/InfluxDB

Depois de criar uma conta no Grafana, voce deve iniciar uma instância. Feito isso, você terá uma url do tipo https://usuario.grafana.net/
Agora você deve linkar o data source com o seu RaspberryPi (ou na maquina onde você fez todo o processo do InfluxDB).
Um ponto importante e enjoado quando fazemos tudo isso com maquinas locais, é que você deve agora criar uma porta de direcionamento no seu roteador, para que o InfluxDB seja acessado externamente. Se o IP da sua internet não é fixo, é interessante que você instale o No-Ip no RaspberryPi. Seguem aqui as instruções.

No meu roteador eu coloquei as segintes configurações:

Agora você pode acessar tanto seu servidor MQTT quanto o InfluxDB externamente via endereço.no-ip.xxx:numero_da_porta

Configurando agora o datasource do Grafana

Em URL você vai colocar o seu IP ou o endereço do seu No-Ip, seguido da porta externa que você direcionou no seu roteador (no meu caso seria a 8086 mesmo)
Em InfluxDB Details você irá inserir o nome da sua base de dados “esp8266”, usuario e a senha que você criou anteriomente. (“grafana”/ “suasenhagrafana”). Se estiver tudo ok, salve e teste a conexão

Agora você só precisa inserir uma dashboard e criar uma query. Os dados já vao auto carregar no criador de querys e você só precisa escolher o mqtt_consumer, e especificar o tópico no WHERE

Pronto, agora é so criar os paineis com os dados e as configurações que desejar

Se ficou alguma dúvida ou sugestão é só comentar! 😀

 

Leave a Reply

Your email address will not be published. Required fields are marked *