#include <WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
// --- Configurações de rede e MQTT ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* mqtt_sub_topic = "esp32/led";
const char* mqtt_pub_topic = "esp32/dados";
const char* mqtt_status_topic = "esp32/status";
const char* mqtt_heartbeat_topic = "esp32/heartbeat";
// --- Pinos ---
#define LED_PIN 19
#define BUZZER_PIN 27
#define DHT_PIN 4
#define DHT_TYPE DHT22
// --- Objetos ---
WiFiClient espClient;
PubSubClient mqttClient(espClient);
LiquidCrystal_I2C lcd(0x27, 16, 2);
DHT dht(DHT_PIN, DHT_TYPE);
// --- Variáveis de controle ---
bool ledState = false;
unsigned long lastDataSent = 0;
unsigned long lastHeartbeat = 0;
const unsigned long DATA_INTERVAL = 10000;
const unsigned long HEARTBEAT_INTERVAL = 15000;
// --- Funções ---
void showLCD(const String& line1, const String& line2 = "") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) msg += (char)payload[i];
msg.trim();
Serial.print("[MQTT] Mensagem recebida: ");
Serial.println(msg);
if (msg.equalsIgnoreCase("ligar")) {
ledState = true;
digitalWrite(LED_PIN, HIGH);
showLCD("LED LIGADO");
} else if (msg.equalsIgnoreCase("desligar")) {
ledState = false;
digitalWrite(LED_PIN, LOW);
showLCD("LED DESLIGADO");
}
}
bool connectMQTT() {
if (mqttClient.connected()) return true;
Serial.print("Conectando ao MQTT... ");
String clientId = "ESP32-" + String(random(0xffff), HEX);
if (mqttClient.connect(clientId.c_str(), "", "", mqtt_status_topic, 1, true, "offline")) {
Serial.println("conectado!");
mqttClient.publish(mqtt_status_topic, "online", true);
mqttClient.subscribe(mqtt_sub_topic);
return true;
} else {
Serial.print("Falha, rc=");
Serial.println(mqttClient.state());
return false;
}
}
void setupWiFi() {
WiFi.begin(ssid, password);
Serial.print("Conectando Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi conectado.");
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
lcd.init();
lcd.backlight();
showLCD("Iniciando...");
dht.begin();
setupWiFi();
mqttClient.setServer(mqtt_server, mqtt_port);
mqttClient.setCallback(mqttCallback);
randomSeed(micros());
}
void beepBuzzer() {
digitalWrite(BUZZER_PIN, HIGH);
delay(200);
digitalWrite(BUZZER_PIN, LOW);
}
void loop() {
// Reconectar MQTT se necessário
if (!mqttClient.connected()) {
connectMQTT();
} else {
mqttClient.loop();
}
unsigned long now = millis();
// Enviar dados a cada 10 segundos
if (now - lastDataSent > DATA_INTERVAL) {
lastDataSent = now;
float temp = dht.readTemperature();
float umid = dht.readHumidity();
if (isnan(temp) || isnan(umid)) {
Serial.println("Falha ao ler DHT22");
return;
}
char payload[64];
sprintf(payload, "{\"temp\": %.2f, \"umid\": %.2f}", temp, umid);
mqttClient.publish(mqtt_pub_topic, payload);
Serial.println(String("[MQTT] Dados publicados: ") + payload);
if (umid < 40.0) {
showLCD("ALERTA UMIDADE!", "Umi: " + String(umid, 1) + "%");
beepBuzzer();
} else {
String linha1 = ledState ? "LED LIGADO" : "LED DESLIGADO";
String linha2 = "T:" + String(temp, 1) + " U:" + String(umid, 1);
showLCD(linha1, linha2);
}
}
// Heartbeat
if (now - lastHeartbeat > HEARTBEAT_INTERVAL) {
lastHeartbeat = now;
char hb[64];
sprintf(hb, "{\"uptime_ms\": %lu}", now);
mqttClient.publish(mqtt_heartbeat_topic, hb);
Serial.println(String("[MQTT] Heartbeat: ") + hb);
}
delay(10); // loop mais leve
}