#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
// --- CONFIGURACIÓN DE PINES ---
#define DHTPIN 15
#define DHTTYPE DHT22
const int LED_VERDE = 25; // Válvula de agua
const int LED_AMARILLO = 14; // Ventilador
const int LED_ROJO = 26; // Alarma visual
const int BUZZER = 27; // Alarma sonora
DHT dht(DHTPIN, DHTTYPE);
// --- CREDENCIALES DE RED VIRTUAL WOKWI ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// --- BROKER MQTT ---
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
// --- TÓPICOS ---
const char* topic_paro = "JoelTqz/invernadero/paro";
const char* topic_temp = "JoelTqz/invernadero/temp";
const char* topic_hum = "JoelTqz/invernadero/hum";
WiFiClient espClient;
PubSubClient client(espClient);
bool system_active = true;
unsigned long lastPublishTime = 0;
const long publishInterval = 2000;
void setup_wifi() {
delay(10);
Serial.begin(115200);
Serial.println("\n--- INICIANDO PROYECTO INVERNADERO ---");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\n¡Simulación conectada a Internet!");
}
// --- LÓGICA DEL SWITCH DE PARO POR MQTT ---
void callback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) { message += (char)payload[i]; }
Serial.print("Mensaje de Node-RED [");
Serial.print(topic);
Serial.print("]: ");
Serial.println(message);
if (String(topic) == topic_paro) {
if (message == "OFF") {
system_active = false;
// APAGADO INMEDIATO Y MANDATORIO
digitalWrite(LED_AMARILLO, LOW);
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_ROJO, LOW);
digitalWrite(BUZZER, LOW);
Serial.println("!!! PARO TOTAL ACTIVADO: TODOS LOS ACTUADORES BLOQUEADOS !!!");
} else if (message == "ON") {
system_active = true;
Serial.println(">>> MODO AUTOMÁTICO REANUDADO <<<");
}
}
}
void reconnect() {
while (!client.connected()) {
Serial.print("Buscando broker HiveMQ...");
String clientId = "ESP32-JoelTqz-E2-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println(" ¡Conectado!");
client.subscribe(topic_paro);
} else {
Serial.print("Error, rc=");
Serial.print(client.state());
Serial.println(" Reintentando en 2 segundos...");
delay(2000);
}
}
}
void setup() {
dht.begin();
pinMode(LED_ROJO, OUTPUT);
pinMode(LED_VERDE, OUTPUT);
pinMode(LED_AMARILLO, OUTPUT);
pinMode(BUZZER, OUTPUT);
digitalWrite(LED_ROJO, LOW);
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_AMARILLO, LOW);
digitalWrite(BUZZER, LOW);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long currentTime = millis();
if (currentTime - lastPublishTime >= publishInterval) {
lastPublishTime = currentTime;
// CAMBIO CRÍTICO: Si el sistema NO está activo, forzamos apagado continuo y salimos del ciclo
if (!system_active) {
digitalWrite(LED_AMARILLO, LOW);
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_ROJO, LOW);
digitalWrite(BUZZER, LOW);
Serial.println("[SEGURIDAD] Sistema en Paro. Ignorando sensores.");
return; // Detiene el código aquí para que no evalúe las temperaturas ni humedades
}
// --- Si system_active es TRUE, corre la automatización normal ---
float temp = dht.readTemperature();
float hum = dht.readHumidity();
if (isnan(temp) || isnan(hum)) {
Serial.println("Esperando lectura estable del sensor DHT22...");
return;
}
// Seguir enviando datos al teléfono aunque esté en automático
client.publish(topic_temp, String(temp).c_str());
client.publish(topic_hum, String(hum).c_str());
Serial.print("Monitoreo Activo -> Temp: "); Serial.print(temp);
Serial.print("°C | Hum: "); Serial.print(hum); Serial.println("%");
// 1. Control de Temperatura (> 30°C)
if (temp > 30.0) {
digitalWrite(LED_AMARILLO, HIGH);
digitalWrite(LED_ROJO, HIGH);
digitalWrite(BUZZER, HIGH);
} else {
digitalWrite(LED_AMARILLO, LOW);
digitalWrite(LED_ROJO, LOW);
digitalWrite(BUZZER, LOW);
}
// 2. Control de Humedad (< 60%)
if (hum < 60.0) {
digitalWrite(LED_VERDE, HIGH);
} else {
digitalWrite(LED_VERDE, LOW);
}
}
}