/*
Configure o cliente do navegador HiveMQ para visualizar as
mensagens MQTT publicadas pelo cliente MQTT.
1) Vá para a URL abaixo e clique no botão conectar
http://www.hivemq.com/demos/websocket-client/
2) Adicione os tópicos de assinatura um para cada tópico que o ESP32 usa:
topic_on_off_led/#
topic_sensor_temperature/#
topic_sensor_humidity/#
3) Experimento publicar no topico topic_on_off_led com a mensagem 1 e 0
para ligar e desligar o LED"
IMPORTANTE: É necessário rodar o Wokwi Gateway e habilitar a opção
"Enable Private Wokwi IoT Gateway" através da tecla de atalho F1 no editor de código.
Para baixar o Wokwi IoT Network Gateway acesse o seguinte link:
https://github.com/wokwi/wokwigw/releases/
*/
#include <DHTesp.h>
#include <PubSubClient.h>
#include <WiFi.h>
#define PIN_LED 15 // GPIO que está ligado o LED
#define PIN_DHT 21 // GPIO que está ligado o pino do sensor
/* Configura os tópicos do MQTT */
#define TOPIC_SUBSCRIBE_LED "ledControl"
#define TOPIC_PUBLISH_TEMPERATURE "temperature"
#define TOPIC_PUBLISH_HUMIDITY "humidity"
#define PUBLISH_DELAY 2000 // Atraso da publicação (2 segundos)
#define ID_MQTT "djedu28" // ClientId (para identificação de sessão)
// IMPORTANTE: Este deve ser único no broker, ou seja, se um client MQTT
// tentar entrar com o mesmo id de outro já conectado ao broker,
// o broker irá fechar a conexão de um deles.
/* Variaveis, constantes e objetos globais */
DHTesp dht;
const char *SSID = "Wokwi-GUEST"; // SSID / nome da rede WI-FI que deseja se conectar
const char *PASSWORD = ""; // Senha da rede WI-FI que deseja se conectar
// URL do broker MQTT que se deseja utilizar
const char *BROKER_MQTT = "test.mosquitto.org";
int BROKER_PORT = 1883; // Porta do Broker MQTT
unsigned long publishUpdate;
static char strTemperature[10] = {0};
static char strHumidity[10] = {0};
// Variáveis e objetos globais
WiFiClient espClient; // Cria o objeto espClient
PubSubClient MQTT(espClient); // Instancia o Cliente MQTT passando o objeto espClient
/* Prototypes */
float getTemperature(void);
float getHumidity(void);
void initWiFi(void);
void initMQTT(void);
void callbackMQTT(char *topic, byte *payload, unsigned int length);
void reconnectMQTT(void);
void reconnectWiFi(void);
void checkWiFIAndMQTT(void);
/* Faz a leitura da temperatura (sensor DHT22)
Retorno: temperatura (graus Celsius) */
float getTemperature(void)
{
TempAndHumidity data = dht.getTempAndHumidity();
if (!(isnan(data.temperature)))
return data.temperature;
else
return -99.99;
}
/* Faz a leitura da umidade relativa do ar (sensor DHT22)
Retorno: umidade (0 - 100%) */
float getHumidity(void)
{
TempAndHumidity data = dht.getTempAndHumidity();
if (!(isnan(data.humidity)))
return data.humidity;
else
return -99.99;
}
/* Inicializa e conecta-se na rede WI-FI desejada */
void initWiFi(void)
{
delay(10);
Serial.println("------Conexao WI-FI------");
Serial.print("Conectando-se na rede: ");
Serial.println(SSID);
Serial.println("Aguarde");
reconnectWiFi();
}
/* Inicializa os parâmetros de conexão MQTT(endereço do broker, porta e seta
função de callback) */
void initMQTT(void)
{
MQTT.setServer(BROKER_MQTT, BROKER_PORT); // Informa qual broker e porta deve ser conectado
MQTT.setCallback(callbackMQTT); // Atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega)
}
/* Função de callback esta função é chamada toda vez que uma informação
de um dos tópicos subescritos chega */
void callbackMQTT(char *topic, byte *payload, unsigned int length)
{
String msg;
// Obtem a string do payload recebido
for (int i = 0; i < length; i++) {
char c = (char)payload[i];
msg += c;
}
Serial.printf("Chegou a seguinte string via MQTT: %s do topico: %s\n", msg, topic);
/* Toma ação dependendo da string recebida */
if (msg.equals("ON")) {
digitalWrite(PIN_LED, HIGH);
Serial.print("LED ligado por comando MQTT");
}
if (msg.equals("OFF")) {
digitalWrite(PIN_LED, LOW);
Serial.print("LED desligado por comando MQTT");
}
}
/* Reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair)
em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. */
void reconnectMQTT(void)
{
while (!MQTT.connected()) {
Serial.print("* Tentando se conectar ao Broker MQTT: ");
Serial.println(BROKER_MQTT);
if (MQTT.connect(ID_MQTT)) {
Serial.println("Conectado com sucesso ao broker MQTT!");
MQTT.subscribe(TOPIC_SUBSCRIBE_LED);
} else {
Serial.println("Falha ao reconectar no broker.");
Serial.println("Nova tentativa de conexao em 2 segundos.");
delay(2000);
}
}
}
/* Verifica o estado das conexões WiFI e ao broker MQTT.
Em caso de desconexão (qualquer uma das duas), a conexão é refeita. */
void checkWiFIAndMQTT(void)
{
if (!MQTT.connected())
reconnectMQTT(); // se não há conexão com o Broker, a conexão é refeita
reconnectWiFi(); // se não há conexão com o WiFI, a conexão é refeita
}
void reconnectWiFi(void)
{
// se já está conectado a rede WI-FI, nada é feito.
// Caso contrário, são efetuadas tentativas de conexão
if (WiFi.status() == WL_CONNECTED)
return;
WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println();
Serial.print("Conectado com sucesso na rede ");
Serial.print(SSID);
Serial.println("IP obtido: ");
Serial.println(WiFi.localIP());
}
void setup()
{
Serial.begin(115200);
// Configura o pino do LED como output e inicializa em nível baixo
pinMode(PIN_LED, OUTPUT);
digitalWrite(PIN_LED, LOW);
// Inicializacao do sensor de temperatura
dht.setup(PIN_DHT, DHTesp::DHT22);
// Inicializa a conexao Wi-Fi
initWiFi();
// Inicializa a conexao ao broker MQTT
initMQTT();
}
void loop()
{
/* Repete o ciclo após 2 segundos */
if ((millis() - publishUpdate) >= PUBLISH_DELAY) {
publishUpdate = millis();
// Verifica o funcionamento das conexões WiFi e ao broker MQTT
checkWiFIAndMQTT();
// Formata as strings a serem enviadas para o dashboard (campos texto)
sprintf(strTemperature, "%.2fC", getTemperature());
sprintf(strHumidity, "%.2f", getHumidity());
// Envia as strings ao dashboard MQTT
MQTT.publish(TOPIC_PUBLISH_TEMPERATURE, strTemperature);
MQTT.publish(TOPIC_PUBLISH_HUMIDITY, strHumidity);
// Keep-alive da comunicação com broker MQTT
MQTT.loop();
}
}