// Librerías necesarias para conexión MQTT, WiFi y sensor DHT
#include <PubSubClient.h>
#include <WiFi.h>
#include "DHTesp.h"
#define TEMP_LED 2 // LED de alarma de temperatura conectado al pin 2
#define CMD_LED 5 // LED controlado por comando MQTT conectado al pin 5
// Configuración de red WiFi
const char* ssid = "Wokwi-GUEST"; // Nombre de la red WiFi
const char* password = ""; // Contraseña de la red WiFi
// Configuración del servidor MQTT
const char *mqtt_server = "broker.emqx.io"; // Dirección del broker MQTT
const int mqtt_port = 1883; // Puerto del servidor MQTT
const char *mqtt_username = "emqx"; // Usuario para autenticación MQTT
const char *mqtt_password = "public"; // Contraseña para autenticación MQTT
// Tópicos MQTT para suscribirse y publicar
const char *comandoLuz = "campus/edf_a/esp32_01/comandoLuz"; // Tópico de suscripción para controlar el LED de luz
const char *comandoTemp = "campus/edf_a/esp32_01/comandoTemp"; // Tópico de suscripción para controlar el LED de temperatura
const char *temperatura = "campus/edf_a/sala1/temperatura"; // Tópico para publicar temperatura
const char *humedad = "campus/edf_a/sala1/humedad"; // Tópico para publicar humedad
// Variables globales
WiFiClient espClient; // Cliente WiFi para manejar la conexión
PubSubClient client(espClient); // Cliente MQTT que usa la conexión WiFi
DHTesp dhtSensor; // Objeto para manejar el sensor DHT
// Pin donde está conectado el sensor DHT22
const int DHT_PIN = 15; // Pin GPIO para el sensor DHT22
// Variables para gestionar tiempos
unsigned long lastDHTReadTime = 0; // Última vez que se leyó el sensor DHT
const unsigned long DHTInterval = 3000; // Intervalo de tiempo para leer el sensor DHT
// Declaración de funciones
void callback(char* topic, byte* payload, unsigned int length); // Función de callback para recibir mensajes MQTT
void reconnect(); // Función para reconectar con el broker MQTT
void setup_wifi(); // Función para configurar la conexión WiFi
// Función de inicialización
void setup() {
Serial.begin(115200); // Inicia la comunicación serial para depuración
setup_wifi(); // Conexión a la red WiFi
client.setServer(mqtt_server, mqtt_port); // Configura el servidor MQTT
client.setCallback(callback); // Configura el callback para recibir mensajes MQTT
dhtSensor.setup(DHT_PIN, DHTesp::DHT22); // Configura el sensor DHT22
pinMode(TEMP_LED, OUTPUT); // Configura el pin del LED de temperatura como salida
pinMode(CMD_LED, OUTPUT); // Configura el pin del LED controlado por comando como salida
}
// Bucle principal
void loop() {
if (!client.connected()) reconnect(); // Si no está conectado al servidor MQTT, intenta reconectar
unsigned long currentMillis = millis(); // Tiempo actual en milisegundos
// Leer datos de temperatura y humedad cada 3 segundos sin bloquear el bucle
if (currentMillis - lastDHTReadTime >= DHTInterval) {
lastDHTReadTime = currentMillis;
TempAndHumidity data = dhtSensor.getTempAndHumidity();
// Verificación de errores en la lectura del sensor
if (isnan(data.temperature) || isnan(data.humidity)) {
Serial.println("Error al leer del sensor DHT!");
} else {
// Mostrar los valores de temperatura y humedad en el monitor serial
Serial.printf("Temp: %.2f°C\n", data.temperature);
Serial.printf("Humidity: %.1f%%\n---\n", data.humidity);
// Si está conectado al servidor MQTT, publica los valores de temperatura y humedad
if (client.connected()) {
client.publish(temperatura, String(data.temperature).c_str()); // Publicar temperatura
client.publish(humedad, String(data.humidity).c_str()); // Publicar humedad
}
// Alarma de temperatura alta (LED en el pin 2)
if (data.temperature > 24) {
digitalWrite(TEMP_LED, HIGH); // Activa el LED si la temperatura es mayor a 24°C
Serial.println("Alarma de temperatura alta activada (LED encendido)");
} else {
digitalWrite(TEMP_LED, LOW); // Apaga el LED si la temperatura es menor o igual a 24°C
Serial.println("Alarma de temperatura baja desactivada (LED apagado)");
}
}
}
client.loop(); // Mantiene el cliente MQTT ejecutando tareas pendientes
}
// Función para conectarse a la red WiFi
void setup_wifi() {
Serial.printf("\nConectando a ssid: %s", ssid); // Muestra el nombre de la red WiFi a la que se va a conectar
WiFi.begin(ssid, password); // Inicia la conexión WiFi
// Espera hasta que se logre la conexión
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("."); // Muestra puntos mientras se conecta
}
Serial.println("\nConectado a red WiFi!"); // Mensaje de éxito al conectar
Serial.print("Dirección IP: "); // Muestra la dirección IP asignada
Serial.println(WiFi.localIP());
}
// Función para reconectar al servidor MQTT si la conexión se ha perdido
void reconnect() {
while (!client.connected()) {
Serial.print("Intentando conexión MQTT...");
// Genera un ID de cliente MQTT único basado en un número aleatorio
String clientId = "campus_esp32_01_" + String(random(0xffff), HEX);
// Intenta conectar al servidor MQTT con el usuario y contraseña
if (client.connect(clientId.c_str(), mqtt_username, mqtt_password)) {
Serial.println("Conectado!");
// Suscribirse a los tópicos de comando
if (client.subscribe(comandoLuz)) {
Serial.println("Suscripción al tópico de comandoLuz exitosa");
}
if (client.subscribe(comandoTemp)) {
Serial.println("Suscripción al tópico de comandoTemp exitosa");
}
} else {
// Si falla la conexión, muestra el error y espera 5 segundos antes de reintentar
Serial.printf("Falló :( con error -> %d. Reintentamos en 5 segundos\n", client.state());
delay(5000);
}
}
}
// Función callback que se ejecuta cuando se recibe un mensaje en un tópico suscrito
void callback(char* topic, byte* payload, unsigned int length) {
String incoming_msg = ""; // Inicializa una cadena para almacenar el mensaje entrante
// Convierte el payload (mensaje recibido) de bytes a string
for (int i = 0; i < length; i++) incoming_msg += (char)payload[i];
incoming_msg.trim(); // Elimina espacios en blanco o caracteres no deseados al inicio y fin
// Muestra el tópico y el mensaje recibido en el monitor serial
Serial.printf("Mensaje recibido desde: %s\nMensaje: %s\n", topic, incoming_msg.c_str());
// Control del LED en el pin 5 mediante comandos MQTT
if (String(topic) == comandoLuz) {
if (incoming_msg == "1") {
digitalWrite(CMD_LED, HIGH); // Enciende el LED en el pin 5
Serial.println("LED del pin 5 encendido por comando MQTT");
} else if (incoming_msg == "0") {
digitalWrite(CMD_LED, LOW); // Apaga el LED en el pin 5
Serial.println("LED del pin 5 apagado por comando MQTT");
}
}
// Control del LED en el pin 2 (TEMP_LED) mediante comandos MQTT
if (String(topic) == comandoTemp) {
if (incoming_msg == "1") {
digitalWrite(TEMP_LED, HIGH); // Enciende el LED de temperatura en el pin 2
Serial.println("LED del pin 2 encendido por comandoTemp");
} else if (incoming_msg == "0") {
digitalWrite(TEMP_LED, LOW); // Apaga el LED de temperatura en el pin 2
Serial.println("LED del pin 2 apagado por comandoTemp");
}
}
}