/*
ESP32 + DHT11 + LDR + Buzzer + MQTT (MyMQTT)
- Não há SSID/SENHA hardcoded: insira via Serial na inicialização.
- Substitua MQTT_SERVER por "seu link do server aqui".
- Bibliotecas: DHTesp, PubSubClient, ArduinoJson
*/
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHTesp.h>
#include <ArduinoJson.h>
// ===== CONFIGURAÇÕES MQTT =====
const char* MQTT_SERVER = "3.17.12.250"; // <--- substitua quando souber
const uint16_t MQTT_PORT = 1883;
const char* MQTT_USER = ""; // se houver, coloque; senão deixe ""
const char* MQTT_PASS = ""; // se houver, coloque; senão deixe ""
// tópicos
const char* TOPIC_PUBLISH = "sensors/esp32/data";
const char* TOPIC_COMMAND = "sensors/esp32/command";
const char* TOPIC_STATUS = "sensors/esp32/status";
// ===== PINOS =====
const int DHT_PIN = 15; // DHT11 data
const int LDR_PIN = 35; // pino ADC (GPIO34)
const int BUZZER_PIN = 23; // pino do buzzer (PWM/OUTPUT)
// ===== PARÂMETROS =====
const unsigned long PUBLISH_INTERVAL_MS = 30000; // 30s
const int ADC_MAX = 4095; // 12-bit ADC do ESP32
// Alerta por temperatura (padrão)
const float TEMP_ALERT_C = 30.0; // °C
// ===== OBJETOS =====
DHTesp dht;
WiFiClient espClient;
PubSubClient mqttClient(espClient);
// controle interno
unsigned long lastPublish = 0;
unsigned long lastBuzzerToggle = 0;
bool buzzerState = false;
bool buzzerForced = false; // true quando BUZZER_ON via MQTT
bool buzzerAutoAlarm = true; // checar temperatura e disparar buzzer automaticamente
unsigned long buzzerIntervalMs = 500; // intervalo de piscar do buzzer quando em alarme
// leitura WiFi via Serial (sem deixar credenciais no código)
String wifiSSID = "";
String wifiPASS = "";
// -------- Funções utilitárias --------
void debugPrint(String s) {
Serial.println(s);
}
void startBuzzer() {
buzzerForced = true;
digitalWrite(BUZZER_PIN, HIGH);
buzzerState = true;
}
void stopBuzzer() {
buzzerForced = false;
digitalWrite(BUZZER_PIN, LOW);
buzzerState = false;
}
void setBuzzerOnOff(bool on) {
analogWrite(BUZZER_PIN, on ? 255 : 0); // se usar PWM lib; caso analógico não funcione, digitalWrite abaixo:
digitalWrite(BUZZER_PIN, on ? HIGH : LOW);
buzzerState = on;
}
// -------- MQTT callback --------
void handleCommand(const String &cmd) {
debugPrint("Comando recebido: " + cmd);
if (cmd == "BUZZER_ON") {
buzzerForced = true;
buzzerAutoAlarm = false;
setBuzzerOnOff(true);
mqttClient.publish(TOPIC_STATUS, "BUZZER_ON");
} else if (cmd == "BUZZER_OFF") {
buzzerForced = false;
buzzerAutoAlarm = false;
setBuzzerOnOff(false);
mqttClient.publish(TOPIC_STATUS, "BUZZER_OFF");
} else if (cmd == "ALARM_ON") {
buzzerAutoAlarm = true;
mqttClient.publish(TOPIC_STATUS, "ALARM_ON");
} else if (cmd == "ALARM_OFF") {
buzzerAutoAlarm = false;
setBuzzerOnOff(false);
mqttClient.publish(TOPIC_STATUS, "ALARM_OFF");
} else if (cmd.startsWith("SET_BUZZER_INTERVAL:")) {
String val = cmd.substring(cmd.indexOf(':') + 1);
long v = val.toInt();
if (v > 50) {
buzzerIntervalMs = v;
mqttClient.publish(TOPIC_STATUS, "BUZZER_INTERVAL_SET");
}
} else if (cmd == "PING") {
mqttClient.publish(TOPIC_STATUS, "PONG");
} else if (cmd == "RESTART") {
mqttClient.publish(TOPIC_STATUS, "RESTARTING");
delay(500);
ESP.restart();
} else {
mqttClient.publish(TOPIC_STATUS, "UNKNOWN_CMD");
}
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String msg;
for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];
handleCommand(msg);
}
// -------- Conexão MQTT --------
void connectMQTT() {
mqttClient.setServer(MQTT_SERVER, MQTT_PORT);
mqttClient.setCallback(mqttCallback);
if (WiFi.status() != WL_CONNECTED) return;
while (!mqttClient.connected()) {
Serial.print("Conectando ao MQTT...");
String clientId = "ESP32Client-";
clientId += String((uint32_t)ESP.getEfuseMac(), HEX); // id único
bool connected;
if (String(MQTT_USER) == "") {
connected = mqttClient.connect(clientId.c_str());
} else {
connected = mqttClient.connect(clientId.c_str(), MQTT_USER, MQTT_PASS);
}
if (connected) {
Serial.println("Conectado ao broker MQTT.");
mqttClient.subscribe(TOPIC_COMMAND);
mqttClient.publish(TOPIC_STATUS, "ONLINE");
} else {
Serial.print("Falha (rc=");
Serial.print(mqttClient.state());
Serial.println("). Tentando novamente em 3s...");
delay(3000);
}
}
}
// -------- Conexão WiFi via Serial input --------
void connectWiFiFromSerial() {
Serial.println("=== CONFIGURAÇÃO DE REDE ===");
Serial.println("Se sua placa já souber a rede, pressione Enter para pular.");
Serial.println("Caso contrário, insira SSID e pressione ENTER, depois insira SENHA e ENTER.");
Serial.println("Digite: skip (para pular)");
Serial.print("SSID: ");
// aguarda entrada
unsigned long start = millis();
while (!Serial.available()) {
if (millis() - start > 30000) { // timeout 30s
Serial.println();
Serial.println("Timeout de entrada Serial. Pulei a configuração.");
return;
}
delay(10);
}
wifiSSID = Serial.readStringUntil('\n');
wifiSSID.trim();
if (wifiSSID.length() == 0 || wifiSSID.equalsIgnoreCase("skip")) {
Serial.println("Configuração de rede pulada.");
return;
}
Serial.print("SENHA: ");
// esperar senha
start = millis();
while (!Serial.available()) {
if (millis() - start > 30000) {
Serial.println();
Serial.println("Timeout de entrada Serial para senha. Pulando.");
wifiSSID = "";
return;
}
delay(10);
}
wifiPASS = Serial.readStringUntil('\n');
wifiPASS.trim();
Serial.print("Tentando conectar a rede: ");
Serial.println(wifiSSID);
WiFi.begin(wifiSSID.c_str(), wifiPASS.c_str());
unsigned long attemptStart = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (millis() - attemptStart > 20000) {
Serial.println();
Serial.println("Falha ao conectar WiFi (timeout 20s). Verifique credenciais ou rede.");
return;
}
}
Serial.println();
Serial.print("WiFi conectado. IP: ");
Serial.println(WiFi.localIP());
}
// -------- Setup e Loop --------
void setup() {
Serial.begin(115200);
delay(200);
// pinos
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
dht.setup(DHT_PIN, DHTesp::DHT11);
analogReadResolution(12); // 0..4095
// conectar via Serial (sem salvar SSID no código)
connectWiFiFromSerial();
if (WiFi.status() == WL_CONNECTED) {
debugPrint("Conectado ao WiFi - tentando conectar MQTT...");
connectMQTT();
} else {
debugPrint("WiFi não conectado. Você deve conectar o ESP32 à mesma rede do celular para usar MyMQTT.");
debugPrint("Se preferir, conecte manualmente pelo Serial Monitor (reabra e insira SSID/SENHA).");
}
lastPublish = millis();
}
void loop() {
// se wifi conectado, garante MQTT
if (WiFi.status() == WL_CONNECTED) {
if (!mqttClient.connected()) {
connectMQTT();
}
mqttClient.loop();
} else {
// tenta reconectar WiFi se usuário já forneceu credenciais
static unsigned long lastTryWiFi = 0;
if (wifiSSID.length() > 0 && millis() - lastTryWiFi > 10000) {
lastTryWiFi = millis();
Serial.println("Tentando reconectar WiFi com credenciais fornecidas...");
WiFi.begin(wifiSSID.c_str(), wifiPASS.c_str());
}
}
unsigned long now = millis();
// Publicação periódica
if (now - lastPublish >= PUBLISH_INTERVAL_MS) {
lastPublish = now;
// lê DHT
float humidity = dht.getHumidity();
float temperature = dht.getTemperature();
// lê LDR
int raw = analogRead(LDR_PIN); // 0..4095
int lightPercent = map(raw, 0, ADC_MAX, 100, 0);
if (lightPercent < 0) lightPercent = 0;
if (lightPercent > 100) lightPercent = 100;
// montar JSON
StaticJsonDocument<256> doc;
if (!isnan(temperature)) doc["temperature"] = temperature;
else doc["temperature"] = nullptr;
if (!isnan(humidity)) doc["humidity"] = humidity;
else doc["humidity"] = nullptr;
doc["light"] = raw;
doc["light_percent"] = lightPercent;
doc["ip"] = (WiFi.status() == WL_CONNECTED) ? WiFi.localIP().toString() : "no_wifi";
char payload[256];
serializeJson(doc, payload);
Serial.print("Publicando: ");
Serial.println(payload);
if (mqttClient.connected()) {
bool ok = mqttClient.publish(TOPIC_PUBLISH, payload);
if (!ok) {
Serial.println("Falha ao publicar MQTT.");
}
} else {
Serial.println("MQTT não conectado; pulando publicação.");
}
// checagem rápida para alarme automático
if (buzzerAutoAlarm && !buzzerForced) {
if (!isnan(temperature) && temperature >= TEMP_ALERT_C) {
// ligar pisca-pisca do buzzer (não contínuo)
// marcar que está em alarme
// buzzerState será alternado na parte de controle abaixo
} else {
// garantir buzzer desligado se não for forçado
if (!buzzerForced) setBuzzerOnOff(false);
}
}
}
// controle de buzzer em alarme (piscar) se ALARM ativo e temperatura alta
if (buzzerAutoAlarm && !buzzerForced) {
float t = dht.getTemperature();
if (!isnan(t) && t >= TEMP_ALERT_C) {
if (millis() - lastBuzzerToggle >= buzzerIntervalMs) {
lastBuzzerToggle = millis();
buzzerState = !buzzerState;
setBuzzerOnOff(buzzerState);
}
} else {
// não em alarme; garantir buzzer desligado
if (buzzerState) {
buzzerState = false;
setBuzzerOnOff(false);
}
}
}
delay(10); // pequena folga
}