ÍNDICE DE CONTEÚDO
Nesse artigo, iremos fazer um projeto para praticarmos a construção de um ambiente IoT, principalmente para iniciantes na área, que pode vir a ser até mesmo um produto, o objetivo do projeto é realizar a leitura dos dados de temperatura e umidade fornecidos pelo sensor DHT11 através do microcontrolador ESP32 e com a ajuda do protocolo MQTT iremos transmitir estes dados para um servidor (que no caso, será nosso próprio computador) e mostraremos estes mesmos dados em uma aplicação de dashboards chamada Grafana.
Para o projeto iremos precisar:
- IDE / Plataforma — Arduino IDE para programar o código do microcontrolador.
- ESP32.
- MÓDULO SENSOR DHT11.
- PROTOBOARD.
- JUMPERS.
Além disso, por questões de preferência e praticidade, o S.O (Sistema Operacional) usado neste artigo foi o Linux Ubuntu 22.04, dito isso todo e qualquer software usado nesse projeto, sendo eles: broker MQTT, Grafana, Arduino IDE, bancos de dados e entre outros terão seus comandos de instalação e uso nos terminais voltados para o S.O escolhido. Contudo, todos eles estão disponíveis em outros Sistemas Operacionais, como por exemplo: Windows.
Circuito
Na imagem abaixo, vemos o esquemático da parte física do projeto que vai ser feito usando a protoboard. O esquemático vai nos auxiliar na construção do hardware envolvido no projeto.
Embarcados Experience 2024: Evento Presencial
Participe do Embarcados Experience 2024 em São Paulo. Conhecimento técnico, palestras, workshops e oportunidade de networking com profissionais experientes.
Uma observação sobre o circuito acima é que nele temos apenas o DHT11 e não o módulo dele que será usado no projeto, o DHT11 contém quatros terminais, sendo eles: VCC, DATA, NC e GND. Porém o módulo do sensor, não expõe o terminal NC.
Ligações dos pinos do módulo do DHT11 ao ESP32:
- Terminal VCC → Vin (5V) ESP32
- Terminal GND → GND ESP32
- Terminal DATA → D23 (GPIO 23) ESP32
Durante o artigo vai ser usado o módulo do DHT11, usando ele não é necessário fazer o pull-up que está no circuito acima, ou seja, você não irá precisar colocar o resistor e fazer suas devidas ligações, somente irá ligar os terminais do DHT11 ao ESP32 assim como está no circuito acima. Porém, caso você queira usar o sensor direto, você deve então utilizar o pull-up.
Funcionamento básico e características do DHT11:
O sensor de temperatura DHT11 é um dos mais populares e baratos do mercado, o que o torna acessível e prático para projetos. Além disso, o seu uso não é complicado.
Outra informação importante de se ter são as medidas alcançadas pelo sensor, segundo o seu DataSheet (manual), a precisão da temperatura medida pelo sensor pode variar em ± 2°C e a umidade em ± 5%.
Caso queiram saber mais sobre o sensor, é possível encontrar o datasheet do DHT11 facilmente na internet.
Configuração do ambiente:
Para usarmos o sensor é preciso instalar a biblioteca do mesmo dentro da Arduino IDE, para isso você deve seguir os passos:
- Gerenciador de bibliotecas.
- Procurar por DHT sensor library by Adafruit.
- Instalar.
Ou caso queira, você também pode instalar o arquivo da biblioteca por meio do link: https://www.arduino.cc/reference/en/libraries/dht-sensor-library/, descompactar o arquivo e inseri-lo na pasta de libraries que se encontra dentro da pasta raiz do seu Arduino IDE.
Funcionamento e instalação básica do broker MQTT:
O broker funciona como um intermediador dos nossos dados que é capaz de recebê-los de inúmeros dispositivos ao mesmo tempo. No caso, trabalhamos com duas nomenclaturas ao lidar com um broker, temos a publicação e a inscrição, sendo assim quando realizamos a publicação estamos enviando os dados para o broker. Já a inscrição é a forma que outros dispositivos ou aplicações, como, por exemplo, o servidor, recebem ou “pegam” esses dados.
Nesse caso, usaremos o Broker Mosquitto que é o software que nos permite utilizar o protocolo de comunicação MQTT no lado do servidor.
Para instalação do broker no Linux, basta seguir os comandos abaixo:
- sudo apt-get update -y && sudo apt-get upgrade -y
- sudo apt-get install mosquitto
Após a instalação é recomendado usar o comando: systemctl status mosquitto.
Para verificar de fato se o broker, após instalado, já está ativo. Caso o mesmo apareça como STOPPED, use o comando abaixo para iniciar a sua aplicação: systemctl start mosquitto.
Outro fator importante é que por padrão quando se instala o broker MQTT, a porta atribuída para aplicação é a 1883, porém fique atento, pois você pode já ter alguma outra aplicação usando essa mesma porta na sua rede. Caso isso aconteça, você deve trocar a porta usada pelo broker ou pela outra aplicação.
Além disso, você pode também estar instalando uma aplicação no seu computador chamada MQTT explorer, essa aplicação nos permite enviar e ver os dados que estão trafegando no broker.
Lembrando que caso você use outro S.O, você deve procurar os devidos passos de como instalar o broker MQTT (Mosquitto) e o MQTT Explorer.
Código da conexão DHT11 + ESP32 e suas devidas explicações
Agora que já vimos como o sensor foi estruturado e como o broker funciona, vamos introduzir os passos que envolvem o código que será executado no ESP32, o mesmo vai fazer a comunicação com o sensor e será possível medirmos a temperatura e umidade do ambiente.
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 52 53 54 55 56 57 58 59 60 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 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 123 124 125 126 127 128 129 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 |
#include "DHT.h" #include "WiFi.h" #include "PubSubClient.h" #include "esp_system.h" #include "NTPClient.h" #define DHTPIN 23 #define DHTTYPE DHT11 //Variaveis esp_random uint64_t chipid = 0; WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); DHT dht(DHTPIN, DHTTYPE); WiFiUDP udp; NTPClient ntp(udp, "a.st1.ntp.br", 0, 60000); void setup() { Serial.begin(115200); Serial.println("DHTxx test!"); //inicializa o sensor dht dht.begin(); // Conectar WiFi const char *SSID = "....."; const char *PWD = "....."; wifi_connect(SSID, PWD); //servidor ntp ntp.begin(); ntp.forceUpdate(); //MQTT char *mqttServer = "192.168.1.10"; int mqttPort = 1883; mqtt_connect(mqttServer, mqttPort); //Mac Address ESP chipid= ESP.getEfuseMac(); Serial.printf("%llu\n",chipid); } //Reconexao void mqtt_reconnect () { while (!mqttClient.connected()) { Serial.printf("Reconnecting to Mqtt Broker ..\n"); if (mqttClient.connect("ESP32_DHT11")) { Serial.printf("Conecting \n"); mqttClient.subscribe("/commands"); } } Serial.printf("Connected to Mqtt Broker ...\n"); } void wifi_connect (const char *SSID, const char *PWD) { WiFi.begin(SSID,PWD); while (WiFi.status() != WL_CONNECTED) { Serial.printf("..."); delay(500); } Serial.print("Connected.\n"); Serial.println(WiFi.localIP()); } void mqtt_connect (const char *server, int port) { mqttClient.setServer(server, port); mqttClient.setCallback(mqtt_callback); if (mqttClient.connect("ESP32_DHT11")) { Serial.printf("Connecting ...\n"); mqttClient.subscribe("/commands"); } } //CallBack void mqtt_callback(char* topic, byte* payload, unsigned int length) { Serial.print("Callback - Message:"); for (uint i = 0; i < length; i++) { Serial.print((char)payload[i]); } } void loop() { float humidity = dht.readHumidity(); float temperature = dht.readTemperature(); if (isnan(humidity) || isnan(temperature)) { Serial.println("Failed to read from DHT sensor!\n"); return; } Serial.printf("Umidade: %.2f \n", humidity, "%"); Serial.printf("Temperatura: %.2f °C \n", temperature); // pega a hora via ntp long time = ntp.getEpochTime(); // Verificando conexao if (!mqttClient.connected()) { mqtt_reconnect(); } mqttClient.loop(); //variavel usada para receber o retorno da funcao millis long now = millis(); //variavel estatica usada para receber o valor de now static long last_time = 0; //envio de 5 em 5 segundos os valores do sensor para o broker mqtt if(now - last_time >5000) { //DHT11 Read char data [128] = {0}; snprintf(data,128,"{\"Id\":%llu,\"Temperature\":%.2f,\"Date\":%ld,\"Humidity\":%.2f}", chipid, temperature, time, humidity); mqttClient.publish("dht/data", data); last_time=now; } delay(1000); } |
Explicando o código:
1 – Importando as bibliotecas e definição de algumas diretivas
Nessa etapa iremos importar as bibliotecas necessárias para o código executar, incluindo a biblioteca do DHT11 que instalamos no início do projeto e a biblioteca para a comunicação MQTT.
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 |
#include "DHT.h" #include "WiFi.h" #include "PubSubClient.h" #include "esp_system.h" #include "NTPClient.h" #define DHTPIN 23 #define DHTTYPE DHT11 //Variaveis esp_random uint64_t chipid = 0; WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); DHT dht(DHTPIN, DHTTYPE); WiFiUDP udp; NTPClient ntp(udp, "a.st1.ntp.br", 0, 60000); |
Além disso, é definido algumas variáveis e diretivas de compilação, como por exemplo: na linha 8 foi determinado que o pino ao qual ligamos o DHT11 no ESP32 é o 23 (lembrando que a escolha do pino fica ao seu critério).
Alguns objetos são criados:
- “WiFiClient” que se conecta em um endereço de IP e porta específico, esse objeto será usado como parâmetro para a criação do objeto MQTT que vai nos permitir configurar e publicar as informações no broker.
- Objeto DHT, que vai receber como parâmetro o tipo do sensor DHT e o pino ao qual ele vai se comunicar com o microcontrolador.
- Objeto WiFiUDP que tem como propósito enviar e receber mensagens UDP, esse objeto será usado como parâmetro para a criação do objeto NTP que é um protocolo que retorna em unix time a hora e data atualizada e usa o protocolo UDP para a comunicação.
2 – Função SETUP
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 |
void setup() { Serial.begin(115200); Serial.println("DHTxx test!"); //inicializa o sensor dht dht.begin(); // Conectar WiFi const char *SSID = "....."; const char *PWD = "....."; wifi_connect(SSID, PWD); //servidor ntp ntp.begin(); ntp.forceUpdate(); //MQTT char *mqttServer = "192.168.1.10"; int mqttPort = 1883; mqtt_connect(mqttServer, mqttPort); //Mac Address ESP chipid= ESP.getEfuseMac(); Serial.printf("%llu\n",chipid); } |
A função de setup, é onde inicializamos algumas funções importantes e determinamos certos valores para variáveis, a fim de “configurar” o nosso sistema, segue uma explicação mais detalhada dessa função:
INICIALIZAÇÕES:
- É inicializado o objeto do DHT que foi criado no passo anterior.
- É inicializado o objeto do Wi-Fi, que recebe como parâmetro as variáveis SSID e PWD que são respectivamente: nome da sua rede Wi-Fi e a senha da mesma.
- É Inicializado o NTP que é o servidor que usamos para obter a data e hora atual em formato unix.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void wifi_connect (const char *SSID, const char *PWD) { WiFi.begin(SSID,PWD); while (WiFi.status() != WL_CONNECTED) { Serial.printf("..."); delay(500); } Serial.print("Connected.\n"); Serial.println(WiFi.localIP()); } |
Logo após, é executada a função wifi_connect() que tem como objetivo fazer a conexão do microcontrolador com a sua rede Wi-Fi.
1 2 3 4 5 6 7 8 9 10 11 12 |
void mqtt_connect (const char *server, int port) { mqttClient.setServer(server, port); mqttClient.setCallback(callback); if (mqttClient.connect("ESP32_DHT11")) { Serial.printf("Connecting ...\n"); mqttClient.subscribe("/commands"); } } |
Além disso, é executado também a função mqtt_connect() que tem como objetivo fazer a conexão com o servidor broker MQTT, a função recebe como parâmetros: IP da máquina onde o Broker MQTT está executando e a porta do broker, que por padrão é 1883. Meu computador, onde o broker foi instalado, tem o IP 192.168.0.10, mas o seu provavelmente será diferente e você deve alterá-lo, nesse caso, não se deve usar o localhost: 127.0.0.1, pois nesse caso será entendido que o broker está instalado no microcontrolador.
Explorando um pouco mais como foi construída a função mqtt_connect(), podemos ver que a mesma executa duas funções, sendo estas: mqttClient.setServer() e a mqttClient.setCallback().
A função setServer() aponta ao IP e a porta que a aplicação do broker MQTT utiliza para que possamos acessar a ferramenta. Já a função setCallback(), é a função de callback do MQTT, ou seja, uma função que vai sempre ser chamada quando um evento assíncrono acontece e dispara um gatilho que chama essa função, no caso o gatilho acontece quando uma nova mensagem é recebida.
1 2 3 4 5 6 7 8 |
void mqtt_callback(char* topic, byte* payload, unsigned int length) { Serial.print("Callback - Message:"); for (uint i = 0; i < length; i++) ] { Serial.print((char)payload[i]); } } |
A função mqtt_callback() é criada seguindo o padrão apresentado na documentação da biblioteca PubSubClient que usamos para se comunicar com o broker.
E por fim na função setup, é feito a captura do MAC (valor único de cada dispositivo) do ESP32, pois usaremos este valor para identificar qual dispositivo está enviando os dados para o MQTT.
3 — Função LOOP
Na função loop o seu código irá rodar sem parar até que você o mande parar através de comandos ou o microcontrolador desligue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
float humidity = dht.readHumidity(); float temperature = dht.readTemperature(); if ( isnan(humidity) || isnan(temperature) ) { Serial.println("Failed to read from DHT sensor!\n"); return; } Serial.printf("Umidade: %.2f \n", humidity, "%"); Serial.printf("Temperatura: %.2f °C \n", temperature); // pega a hora via ntp long time = ntp.getEpochTime(); // Verificando conexao if ( !mqttClient.connected() ) { mqtt_reconnect(); } mqttClient.loop(); |
Inicialmente nessa função, é criado as variáveis responsáveis por armazenar os valores do sensor que se referem a umidade e a temperatura. Além disso, é feito uma verificação se os valores enviados pelo sensor são realmente números, por vezes pode ocorrer mal contato entre as ligações do hardware.
Logo após, é criado a variável time que recebe o retorno da função getEpochTime() da biblioteca NTP que é referente a hora atual de quando os dados do sensor foram capturados, que posteriormente será enviada junto com os outros dados para ser armazenado no banco de dados.
Em seguida, é feita a verificação da conexão do broker MQTT através da função mqtt_reconnect(), essa função tem como objetivo reconectar o ESP32 ao broker, caso o mesmo esteja desconectado.
Logo após é executada a função mqttClient.loop(), ela tem como propósito, executar mesmo que invisível aos nosso olhos, funções que: Verificam novamente se o mqtt continua ou não conectado e verificar se há mensagens recebidas no tópico, caso não exista ela irá chamar a função de callback que já vimos anteriormente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void mqtt_reconnect () { while (!mqttClient.connected()) { Serial.printf("Reconnecting to Mqtt Broker ..\n"); if (mqttClient.connect("ESP32_DHT11")) { Serial.printf("Connecting \n"); mqttClient.subscribe("/commands"); } } Serial.printf("Conected to Mqtt Broker ...\n"); } |
Explorando um pouco mais como foi construída a função mqtt_reconnect(), que irá se reconectar com o broker caso necessário através da função mqttClient.connect() sendo o parâmetro dessa função o clientID, ou seja, um identificador único que você vai dar para a sua placa para que possamos saber quando a mesma subscrever ou escrever algo no broker, nesse caso, você pode usar um nome que você queira ou o próprio MAC do seu microcontrolador como identificador.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//variavel usada para receber o retorno da funcao millis long now = millis(); //variavel estatica usada para receber o valor de now static long last_time = 0; //envio de 5 em 5 segundos os valores do sensor para o broker mqtt if(now - last_time >5000) { //DHT11 Read char data [128] = {0}; snprintf(data,128,"{\"Id\":%llu,\"Temperature\":%d,\"Hora\":%ld,\"Humidity\":%d}",chipid, esp_random(), time, esp_random()); mqttClient.publish("dht/data", data); last_time=now; } delay(1000); |
Em seguida, é feita uma verificação para saber se a diferença de tempo entre as duas variáveis: now (que recebe o retorno da função millis() que é o valor em milissegundos que representa a quanto tempo a placa está ativa) e last_time são maiores que 5 segundos, ou seja, será enviado os dados somente de 5 em 5 segundos (o tempo de 5 segundos foi determinado somente por preferência, fique a vontade para determinar o tempo que mais lhe convém), caso o tempo seja maior que 5 segundos é montado então a string em formato JSON para ser enviado os valores, que contém os dados:
- Id — Identificador único de cada placa que está conectada no broker, podendo assim identificar a qual placa pertence os dados armazenados no banco de dados.
- Temperatura — valores da temperatura atual capturada pelo DHT11.
- Umidade — valores da umidade atual capturada pelo DHT11.
- Hora — hora local atualizada.
Por fim, os dados de fato são publicados e é dado um delay() no código para que o mesmo não trave nessa única tarefa e seja dado o intervalo de 1 segundo para que possamos pegar os valores de 1 em 1 segundo.
Instalação e configuração do Banco de Dados
Agora que já fizemos toda a comunicação do broker com o ESP32 e o sensor, podemos iniciar a terceira etapa do projeto, que consiste em:
- Instalar e criar o Banco de Dados
Etapas básicas para criação do banco de dados
Não irei me aprofundar nesse tema, pois esse assunto detalhado é muito extenso o que o faz virar assunto para outro artigo.
O banco de dados escolhido foi o PostgreSQL, considerado um dos melhores do mercado. Porém, fica ao seu critério escolher este ou outro banco de dados de sua preferência para utilizar.
1 — Instale o banco de dados no seu computador.
Para a instalação do mesmo no sistema é necessário seguir o conjunto de comando detalhados pela própria desenvolvedora do banco:
https://www.postgresql.org/download/linux/ubuntu
Já para outros sistemas operacionais, fica como aditivo para você pesquisar como fazer essa instalação.
2- Crie o seu banco de dados e configure o mesmo
Após a instalação, deve-se então acessar o seu postgresql e criar o seu banco de dados com suas devidas tabelas para uso no projeto, além de também criar usuários e configurar permissões.
Para o acesso ao postgres no linux ubuntu, vai ser usado o psql, porém fica ao seu critério qual aplicação usar para acessar o banco de dados, para acessar use os comando:
- sudo su postgres
- psql
Os comandos acima são para acessar o postgresql com o usuário postgres, o recomendado que se você usar esse usuário, você deve trocar a senha do mesmo, com o comando abaixo:
- ALTER USER postgres WITH PASSWORD ‘123456’;
Caso deseje criar outro usuário com as devidas permissões sejam elas de leitura e ou escrita para usar no banco, use o comando:
- CREATE USER nome WITH PASSWORD ‘123456’;
Para criar o seu banco de dados, use o comando:
- CREATE DATABASE name;
E por fim, para criar tabela do banco que vai receber os dados do sensor, use o comando:
- CREATE TABLE dht_11 (id BIGINT, temperature real, humidity real, date bigint);
Lembrando que o seu banco de dados deve ter no mínimo uma tabela para uso e essa tabela deve conter colunas que servem para armazenar os dados que serão recebidos, fique a vontade para criar quantas colunas quiserem, mas novamente deve se ter no mínimo 4 colunas obrigatórias, sendo estas para armazenar os dados: ID, Temperatura, Umidade e Hora, para isso atente-se para criar colunas que suportam esse tipo de dado, como no exemplo acima.
Como dito anteriormente, não irei me aprofundar no tema, mas todas essas questões e etapas da criação do banco são fáceis de achar a solução através de pesquisas. Além disso, a própria documentação do PostgreSQL conta com essas etapas e como executá-las.
Documentação do PostgreSQL: https://www.postgresql.org/docs/
A tabela já com os dados deve ficar parecido com a imagem abaixo:
Código da conexão do banco de dados + Grafana e suas devidas explicações
Agora chegamos na etapa de comunicarmos os dados que estão no MQTT com o nosso banco de dados que vai ficar hospedado no nosso servidor (próprio computador).
Resumidamente, ao mesmo tempo que o seu código embarcado no microcontrolador estiver sendo executado, teremos o código que vai subscrever os dados do broker também sendo executado no seu computador.
Para este código, como o mesmo não tem comunicação com o ESP32 e com nenhum outro dispositivo como sensores, outros microcontroladores e etc, foi escolhido NodeJs como a linguagem de programação, mas acredite se você desenvolveu até aqui em C / C++, você não terá grandes dificuldades com NodeJs.
Para compilar e executar esse código no seu computador, você precisa instalar o NodeJs, no linux ubuntu os comando para instalação são:
- sudo apt update
- sudo apt install nodejs npm
Após a instalação verifique a versão do Node instalada, o recomendando para que as bibliotecas usadas no código funcionem é que a versão seja da 16.0 para cima.
Caso, a instalada seja abaixo da recomendada, você deve atualizar essa instalação, podendo para isso usar os comandos:
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
- source ~/.bashrc
1 — Importando as bibliotecas e definição de algumas diretivas
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
const mqtt = require('mqtt'); const { Pool, Client } = require('pg'); //Conexao do Banco const client_database = new Client( { user: '......', password: '......', host: '127.0.0.1', database: '......', }) client_database.connect(); |
Inicialmente, nas primeiras linhas deste código, iremos importar as bibliotecas necessárias no código, que serão: a biblioteca pg que é a biblioteca que usaremos para se comunicar com o banco de dados criado no passo anterior, lembrando que o uso dessa biblioteca acontece porque foi usado o banco postgresql e a biblioteca mqtt para que possamos conectar nosso servidor ao mqtt e capturar as informações para serem enviadas ao banco de dados.
Em seguida, é criado um cliente (denominamos cliente a aplicação que vai consumir e se comunicar com o banco de dados) e declaramos os parâmetros necessários para a conexão com o banco, sendo estes:
- user: Nome do usuário que você criou para acessar o seu banco de dados, lembrando que esse usuário deve ter permissão de escrita para que possamos salvar os dados no banco.
- password: Senha que você designou para esse usuário de acesso ao banco de dados.
- host: IP do servidor onde seu banco de dados está hospedado, no caso, usamos o nosso próprio computador, então pode usar o IP de localhost do computador.
- database: Nome do seu banco de dados criado na etapa acima.
Após criado o cliente, devemos fazer a conexão do banco de dados, no caso, essa conexão é feita com a função client_database.connect().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Conexao MQTT const port = "1883"; const host = `mqtt://127.0.0.1:${port}`; var client = mqtt.connect(host); let topic = '#'; client.on('connect', function success() { console.log("Connecting MQTT"); client.subscribe(topic, function mqtt_subscribe() { console.log("Subscribe to" + topic); }); }); |
Logo após, é feita a conexão com o broker MQTT, nesse caso diferente do código embarcado no ESP32 que é um publicador dos dados, esse código faz o papel de subscrição dos dados.
A função mqtt.connect() tem como objetivo fazer a conexão com o broker MQTT, essa conexão não trava o código enquanto se espera a resposta de sucesso ou não, ou seja, é uma função assíncrona, caso a conexão seja um sucesso, será emitido um evento chamado “connect”, exatamente por este motivo a função client.on() é executada pois a mesma espera pela emissão do evento “connect” declarado como parâmetro. Essa função ao detectar a conexão, chama uma função de callback, sendo esta a mesma função criada diretamente como o segundo parâmetro da função client.on().
A função de callback, executa a função client.subscribe() do MQTT, essa função como o próprio nome diz faz uma subscrição no tópico (declarado na variável topics) capturando então os dados enviados pelo ESP ao MQTT.
Antes que você se pergunte sobre o que significa o “#” no MQTT, ele é um wildcard (símbolo coringa). Quando utilizado em uma assinatura de tópico, o # permite “escutar” todos os tópicos que surgirem no broker a partir do ponto onde ele é usado. Isso inclui, por exemplo, o tópico específico dht/data, que é o tópico no qual o ESP32 está publicando os dados do sensor.
Em outras palavras, se você assinar um tópico com “#”, como “dht/#”, você receberá todas as mensagens publicadas em qualquer subnível de “dht/”, incluindo “dht/data”.
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 |
client.on('message', mqtt_message); function mqtt_message(topic, message) { var J = JSON.parse(message); var T = J.Temperature; var H = J.Humidity; var D = J.Date; var I = J.Id; console.log('topic'+ topic + ' Message' + message); // Insercao const q="INSERT INTO dht11_data(id, temperature, humidity, date) VALUES($1,$2,$3,$4) RETURNING*"; const v =[I, T, H, D]; client_database.query(q,v, (err, res) => { if (err) { console.log(err.stack) } else { console.log(res.rows[0]) } }); } |
Novamente a função client.on() é chamada, agora com o objetivo de esperar a emissão do evento “message”, esse evento é emitido quando uma nova mensagem chega ao broker nos tópicos que o seu cliente está inscrito, acionando então a função de callback declarada na função client.on(), chamada de mqtt_message().
A função mqtt_message() é a função que irá tratar a mensagem recebida via broker, no caso, será feito um parser das informações que chegaram em formato JSON, após a separação desses dados é criado uma query (instrução para o banco de dados) que irá fazer um insert do seus dados no banco. Por fim, é enviado ao banco de dados a query, gravando então as informações no banco.
Instalação e configuração do Grafana
Nessa etapa iremos instalar o Grafana, configurar o básico para o seu funcionamento, assim teremos então a possibilidade de criar as dashboards de acordo com as informações do banco de dados.
Etapas básicas da instalação e configuração do Grafana
1 — Instale o Grafana no seu computador.
Para a instalação do Grafana, é necessário seguir o conjunto de comando detalhados no site da aplicação, conforme o seu Sistema Operacional:
https://grafana.com/grafana/download?pg=oss-graf&plcmt=hero-btn-1.
Se atente na hora da escolha da versão do Grafana, é sempre indicado escolher a versão mais recente. Além disso, atente-se também em escolher a edição OSS (edição para uso livre e gratuito).
Após a instalação é recomendado novamente usar o comando systemctl status grafana para verificar se o Grafana, após instalado, já está ativo. Caso o mesmo apareça como STOPPED, use o comando abaixo para iniciar a sua aplicação: systemctl start grafana
Outro fator é que, por padrão, o Grafana usa a porta 3000 para executar a sua aplicação, porém fique atento caso alguma outra aplicação do seu computador já esteja usando essa porta, se isso acontecer você deve mudar a porta.
Nesse caso, o arquivo ao qual você deve acessar para mudar a porta, muda de localização conforme o Sistema Operacional que você está usando e instalou o Grafana, nesse caso usando Linux Ubuntu para acessar esse arquivo, siga o caminho:
- Acesse o diretório /etc/grafana
- Abra com permissão de sudo o arquivo grafana.init.
- Ache onde está a variável que guarda o valor da porta e mude.
- Salve o arquivo.
Conforme na imagem a seguir:
Para mais informações, acesse:
2- Acessando e configurando o Grafana
Após a instalação, para acessar o Grafana, vá para o seu navegador e use o localhost da sua máquina com a porta do Grafana para acessá-lo: 127.0.0.1:3000
Caso esteja tudo certo, você deve ver uma tela como essa aparecendo:
O usuário e senha para o primeiro acesso é padrão, sendo respectivamente: admin, admin.
Após o primeiro acesso, fica a seu critério trocar a senha do usuário admin, ou como iremos ver logo em seguida, criar um outro usuário para acesso.
O recomendando é que mesmo que você crie um novo usuário para uso, você deve trocar a senha do usuário admin.
3 — Criando um novo usuário
- Acesse a barra lateral e vá em Administração (Figura 1)
- Acesse a aba de usuários e acessos (Figura 1)
- Vá em usuários (Figura 1)
- Clique em novo usuário (Figura 1)
- Preencha as informações (Figura 1), sendo estas:
- Nome: nome da pessoa que será o novo usuário.
- Email: email que deseja atrelar a esse novo usuário (não obrigatório).
- Username: nome do usuário.
- Password: senha de acesso ao novo usuário.
- Após criar o usuário, irá aparecer uma tela para habilitar as permissões que você deseja dar a esse usuário. Por exemplo: você pode dar permissão de admin para o novo usuário ou você pode querer que esse novo usuário só tenha acesso a algumas dashboards e painéis específicos). (Figura 2)
4 — Conexão do banco de dados com o Grafana
Nessa etapa iremos conectar o banco de dados criado na etapa 2.
- Acesse a barra lateral e vá em Administração (Figura 3)
- Acesse a aba de conexões (Figura 3)
- Escolha o modelo de Banco de Dados que você usou para criar o banco no passo anterior(caso seja o postgresql, irá aparecer 2 quando procurar por nome, basta escolher qualquer opção) (Figura 3)
- Clique em Adicionar nova fonte de dados (Figura 3)
- Preencha as informações (Figura 4 e 5) referentes a conexão com a sua fonte de dados, sendo estas as principais:
- Nome: Você pode trocar o nome dado pelo Grafana a sua conexão de dados, fique a vontade!
- Host URL: IP do seu banco de dados, no caso, seguindo o mesmo IP que colocamos no código que envia as informações para o banco de dados, temos o IP: 127.0.0.1:5432.
- Nome do banco: nome que você deu ao seu banco quando criou o mesmo.
- Nome do usuário: nome do usuário criado para acessar o seu banco de dados quando você estava criando o mesmo. Lembre-se: o usuário deve ter a permissão de leitura desse banco.
- Senha: Senha do usuário do banco de dados.
- As informações envolvendo TLS/SSL e opções adicionais do seu banco de dados, fica ao seu critério alterar ou não. Atente-se no campo versão nas opções adicionais do banco de dados nessa mesma tela, pois ali você irá colocar a versão do seu banco de dados atualmente (Figura 5).
5 — Criando as Dashboards
- Acesse a barra lateral e vá em Dashboards (Figura 6).
- Clique em Novo -> Nova Dashboard OU Criar Dashboard (Figura 6).
- Clique em Adicionar Visualização (Figura 6).
- Escolha o banco de dados que você deseja visualizar os dados (Figura 7).
- Edite o seu primeiro gráfico do modo que achar melhor (há dois modos: usando o builder que “facilita” para quem não entende muito sobre query o uso das tabelas e como “pegar” e “transformar” esses dados e code que permite que você programe em SQL e crie sua query e com isso “pegue” e mostre os dados também) e clique em Aplicar (Figura 8).
- Para salvar a dashboard, clique no ícone de gravador na página.
Após as etapas acima, o mesmo irá liberar o uso dos gráficos para você, a partir daqui você está livre para explorar a infinidade de ferramentas dentro do Grafana e criar suas diversas dashboards com quantos dados e bancos de dados forem necessários.
Abaixo, segue um exemplo de gráficos simples com os dados do sensor armazenados no banco de dados:
Dessa forma finalizamos o projeto, porém caso você esteja buscando por desafios e queira deixar esse projeto com um maior nível de dificuldade, você pode implementá-lo usando o FreeRTOS que é um dos Sistema operacionais ao qual o ESP32 suporta.
Os códigos completos deste projeto está no link abaixo:
https://github.com/MariaLgA/Projeto_esp32
Espero que este artigo tenha contribuído de formas positivas no seu aprendizado! 🙂
Ótimo artigo
Fico feliz que tenha gostado Michael!