#include <WiFi.h>
#include <ThingESP.h>
// Configuración ThingESP
ThingESP32 thing("proyectvisec", "LED", "CONTROL");
// Configuración MQTT (EMQX Free)
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
const char* mqtt_topic_status = "viseca/status";
const char* mqtt_topic_alerts = "viseca/alerts";
const char* mqtt_topic_control = "viseca/control";
const char* mqtt_client_id = "ESP32_AlarmaPiscina";
// Configuración WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Pines del sistema
const int pinLectura = 36;
const int pinLedMovimiento = 18;
const int pinLedAlarma = 19;
const int pinLedVoltaje = 21;
const int pinBuzzer = 17;
const int pinLedEstadoAlarma = 16; // NUEVO: LED para indicar estado de la alarma
const int pinPulsadorActivar = 13;
const int pinPulsadorDesactivar = 14;
const int pinPulsadorSilencio = 27;
const int pinPulsadorReiniciar = 33;
// Variables del sistema
float voltaje = 0.0;
unsigned long lastTime = 0;
unsigned long tiempoEsperado = 0;
bool alarmaActivada = false;
bool esperandoSegundaSenal = false;
unsigned long lastPrintTime = 0;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 200;
int valorMovimiento = 0;
int valorAlarma = 0;
enum EstadoSistema { DESACTIVADO, ACTIVADO };
EstadoSistema estadoSistema = DESACTIVADO;
WiFiClient espClient;
PubSubClient mqttClient(espClient);
void mostrarMensajeBienvenida() {
Serial.println("========================================");
Serial.println("SISTEMA_DE_ALARMA_PARA_PISCINA_v2.2");
Serial.println("========================================");
Serial.println("Bienvenido. Este sistema detecta caidas en la piscina.");
Serial.println("Instrucciones:");
Serial.println("- Pulsador 1/Serial '1': ACTIVAR alarma");
Serial.println("- Pulsador 2/Serial '2': DESACTIVAR alarma");
Serial.println("- Pulsador 3/Serial '3': SILENCIAR sirena");
Serial.println("- Pulsador 4/Serial '4': REINICIAR sistema");
Serial.println("Comandos remotos: activar, desactivar, silenciar, reiniciar, estado");
Serial.println("========================================");
}
void conectarWiFi() {
Serial.println("Conectando a la red WiFi...");
WiFi.begin(ssid, password);
int intentos = 0;
while (WiFi.status() != WL_CONNECTED && intentos < 10) {
delay(1000);
Serial.print(".");
intentos++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nConexion WiFi exitosa.");
Serial.print("IP asignada: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nNo se pudo conectar a la red WiFi.");
}
}
void connectMQTT() {
while (!mqttClient.connected()) {
Serial.println("Conectando a EMQX...");
if (mqttClient.connect(mqtt_client_id)) {
Serial.println("Conectado a EMQX");
mqttClient.publish(mqtt_topic_control, "alarma_off");
} else {
Serial.print("Error, rc=");
Serial.print(mqttClient.state());
Serial.println(" Reintentando en 5s...");
delay(5000);
}
}
}
void notifyStatus(String message) {
if (mqttClient.connected()) {
mqttClient.publish(mqtt_topic_status, message.c_str());
Serial.println("Notificación MQTT enviada: " + message);
} else {
connectMQTT();
if (mqttClient.connected()) {
mqttClient.publish(mqtt_topic_status, message.c_str());
}
}
}
void notifyAlert(String message) {
if (mqttClient.connected()) {
mqttClient.publish(mqtt_topic_alerts, message.c_str());
Serial.println("Alerta MQTT enviada: " + message);
} else {
connectMQTT();
if (mqttClient.connected()) {
mqttClient.publish(mqtt_topic_alerts, message.c_str());
}
}
}
void controlarBuzzersRemotos(String comando) {
if (mqttClient.connected()) {
mqttClient.publish(mqtt_topic_control, comando.c_str());
Serial.println("Comando a buzzers remotos: " + comando);
} else {
connectMQTT();
if (mqttClient.connected()) {
mqttClient.publish(mqtt_topic_control, comando.c_str());
}
}
}
// FUNCIÓN NUEVA: Controlar LED de estado de alarma
void actualizarLedEstadoAlarma() {
digitalWrite(pinLedEstadoAlarma, (estadoSistema == ACTIVADO) ? HIGH : LOW);
}
String HandleResponse(String consulta) {
consulta.toLowerCase();
if (consulta == "activar" || consulta == "1") {
estadoSistema = ACTIVADO;
actualizarLedEstadoAlarma(); // Actualizar LED
notifyStatus("Sistema activado (por comando remoto)");
return "";
}
else if (consulta == "desactivar" || consulta == "2") {
estadoSistema = DESACTIVADO;
alarmaActivada = false;
esperandoSegundaSenal = false;
digitalWrite(pinLedAlarma, LOW);
digitalWrite(pinLedMovimiento, LOW);
digitalWrite(pinLedVoltaje, LOW);
noTone(pinBuzzer);
actualizarLedEstadoAlarma(); // Actualizar LED
controlarBuzzersRemotos("alarma_off");
notifyStatus("Sistema desactivado (por comando remoto)");
return "";
}
else if ((consulta == "silenciar" || consulta == "3") && alarmaActivada) {
digitalWrite(pinLedAlarma, LOW);
alarmaActivada = false;
noTone(pinBuzzer);
controlarBuzzersRemotos("alarma_off");
notifyStatus("Alarma silenciada (por comando remoto)");
return "";
}
else if (consulta == "reiniciar" || consulta == "4") {
notifyStatus("Sistema reiniciando por comando remoto...");
delay(1000);
ESP.restart();
return "";
}
else if (consulta == "estado" || consulta == "5") {
String status = "Dispositivo: ";
status += (estadoSistema == ACTIVADO) ? "ACTIVADO" : "DESACTIVADO";
status += ", Alarma: ";
status += alarmaActivada ? "ACTIVA" : "INACTIVA";
status += ", Preaviso: ";
status += esperandoSegundaSenal ? "DETECTADO" : "NO DETECTADO";
notifyStatus(status);
return "";
}
else {
notifyStatus("Comando no reconocido: " + consulta);
return "";
}
}
void procesarComandoSerial(String comando) {
comando.toLowerCase();
if (comando == "1" || comando == "activar") {
estadoSistema = ACTIVADO;
actualizarLedEstadoAlarma(); // Actualizar LED
notifyStatus("Sistema activado (por comando serial)");
Serial.println("Sistema activado");
}
else if (comando == "2" || comando == "desactivar") {
estadoSistema = DESACTIVADO;
alarmaActivada = false;
esperandoSegundaSenal = false;
digitalWrite(pinLedAlarma, LOW);
digitalWrite(pinLedMovimiento, LOW);
digitalWrite(pinLedVoltaje, LOW);
noTone(pinBuzzer);
actualizarLedEstadoAlarma(); // Actualizar LED
controlarBuzzersRemotos("alarma_off");
notifyStatus("Sistema desactivado (por comando serial)");
Serial.println("Sistema desactivado");
mostrarMensajeBienvenida();
}
else if ((comando == "3" || comando == "silenciar") && alarmaActivada) {
Serial.println("Alarma desactivada.");
digitalWrite(pinLedAlarma, LOW);
alarmaActivada = false;
noTone(pinBuzzer);
controlarBuzzersRemotos("alarma_off");
notifyStatus("Alarma silenciada (por comando serial)");
}
else if (comando == "4" || comando == "reiniciar") {
notifyStatus("Sistema reiniciando por comando serial...");
Serial.println("Reiniciando sistema...");
delay(1000);
ESP.restart();
}
else if (comando == "estado") {
String estado = "Estado del Dispositivo: ";
estado += (estadoSistema == ACTIVADO) ? "ACTIVADO" : "DESACTIVADO";
estado += ", Alarma: ";
estado += alarmaActivada ? "ACTIVA" : "INACTIVA";
estado += ", Preaviso: ";
estado += esperandoSegundaSenal ? "DETECTADO" : "NO DETECTADO";
Serial.println(estado);
}
else {
Serial.println("Entrada no valida. Comandos validos: 1/activar, 2/desactivar, 3/silenciar, 4/reiniciar, estado");
notifyStatus("Comando serial no reconocido: " + comando);
}
}
void manejarPulsadores() {
if (millis() - lastDebounceTime < debounceDelay) {
return;
}
if (digitalRead(pinPulsadorActivar) == LOW) {
estadoSistema = ACTIVADO;
actualizarLedEstadoAlarma(); // Actualizar LED
notifyStatus("Sistema activado (por pulsador)");
Serial.println("Sistema activado por pulsador");
lastDebounceTime = millis();
delay(300);
return;
}
if (digitalRead(pinPulsadorDesactivar) == LOW) {
estadoSistema = DESACTIVADO;
alarmaActivada = false;
esperandoSegundaSenal = false;
digitalWrite(pinLedAlarma, LOW);
digitalWrite(pinLedMovimiento, LOW);
digitalWrite(pinLedVoltaje, LOW);
noTone(pinBuzzer);
actualizarLedEstadoAlarma(); // Actualizar LED
controlarBuzzersRemotos("alarma_off");
notifyStatus("Sistema desactivado (por pulsador)");
Serial.println("Sistema desactivado por pulsador");
mostrarMensajeBienvenida();
lastDebounceTime = millis();
delay(300);
return;
}
if (digitalRead(pinPulsadorSilencio) == LOW && alarmaActivada) {
digitalWrite(pinLedAlarma, LOW);
alarmaActivada = false;
noTone(pinBuzzer);
controlarBuzzersRemotos("alarma_off");
notifyStatus("Alarma silenciada (por pulsador)");
Serial.println("Alarma silenciada por pulsador");
lastDebounceTime = millis();
delay(300);
return;
}
if (digitalRead(pinPulsadorReiniciar) == LOW) {
notifyStatus("Sistema reiniciando por pulsador...");
Serial.println("Reiniciando sistema por pulsador...");
delay(1000);
ESP.restart();
}
}
void playWeoWeoAlarm() {
for(int i = 0; i < 4; i++) {
for(int freq = 800; freq <= 1600; freq += 50) {
tone(pinBuzzer, freq, 20);
delay(5);
}
for(int freq = 1600; freq >= 800; freq -= 50) {
tone(pinBuzzer, freq, 20);
delay(5);
}
}
for(int i = 0; i < 2; i++) {
tone(pinBuzzer, 1200, 100);
delay(150);
tone(pinBuzzer, 900, 100);
delay(150);
}
}
void setup() {
delay(2000);
Serial.begin(9600);
Serial.println("Inicio del sistema...");
conectarWiFi();
thing.initDevice();
analogReadResolution(12);
pinMode(pinLectura, INPUT);
pinMode(pinLedMovimiento, OUTPUT);
pinMode(pinLedAlarma, OUTPUT);
pinMode(pinLedVoltaje, OUTPUT);
pinMode(pinBuzzer, OUTPUT);
pinMode(pinLedEstadoAlarma, OUTPUT); // NUEVO: Configurar pin del LED de estado
pinMode(pinPulsadorActivar, INPUT_PULLUP);
pinMode(pinPulsadorDesactivar, INPUT_PULLUP);
pinMode(pinPulsadorSilencio, INPUT_PULLUP);
pinMode(pinPulsadorReiniciar, INPUT_PULLUP);
digitalWrite(pinLedMovimiento, LOW);
digitalWrite(pinLedAlarma, LOW);
digitalWrite(pinLedVoltaje, LOW);
digitalWrite(pinLedEstadoAlarma, LOW); // NUEVO: Apagar LED al inicio
noTone(pinBuzzer);
mqttClient.setServer(mqtt_server, mqtt_port);
mqttClient.setKeepAlive(60);
connectMQTT();
mostrarMensajeBienvenida();
Serial.println("Sistema iniciado en estado DESACTIVADO.");
Serial.println("voltaje\tmovimiento\talarma");
}
void loop() {
thing.Handle();
if (!mqttClient.connected()) {
connectMQTT();
}
mqttClient.loop();
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
input.trim();
procesarComandoSerial(input);
}
manejarPulsadores();
if (estadoSistema == DESACTIVADO) {
delay(250);
return;
}
int lectura = analogRead(pinLectura);
voltaje = (lectura * 3.3) / 4095.0;
valorMovimiento = 0;
digitalWrite(pinLedVoltaje, (voltaje >= 2.8 && voltaje <= 3.3) ? HIGH : LOW);
if (voltaje >= 2.8 && voltaje <= 3.3 && !esperandoSegundaSenal && !alarmaActivada) {
Serial.println("Se ha detectado movimiento en la piscina.");
notifyAlert("ALERTA: Movimiento detectado en la piscina");
esperandoSegundaSenal = true;
lastTime = millis();
digitalWrite(pinLedMovimiento, HIGH);
tiempoEsperado = 0;
}
if (esperandoSegundaSenal) {
tiempoEsperado = millis() - lastTime;
valorMovimiento = 1;
if (millis() - lastPrintTime >= 1000) {
Serial.print("Tiempo de espera: ");
Serial.print(tiempoEsperado / 1000);
Serial.println(" segundos.");
lastPrintTime = millis();
}
if (tiempoEsperado >= 8000 && tiempoEsperado <= 15000) {
lectura = analogRead(pinLectura);
voltaje = (lectura * 3.3) / 4095.0;
if (voltaje >= 2.5 && voltaje <= 3.3) {
Serial.println("Se ha activado la alarma: Verifique caida en la piscina.");
Serial.println("Puede desactivar la Sirena escribiendo '3' o pulsador 3.");
notifyAlert("ALERTA CRÍTICA: Movimiento sospechoso en la piscina. Favor de Verificar la Situación ");
alarmaActivada = true;
digitalWrite(pinLedAlarma, HIGH);
digitalWrite(pinLedMovimiento, LOW);
esperandoSegundaSenal = false;
controlarBuzzersRemotos("alarma_on");
}
}
if (tiempoEsperado > 15000) {
alarmaActivada = false;
Serial.println("No se detecto mas movimiento. Falsa alarma.");
notifyStatus("Alerta cancelada: No se detectó movimiento adicional");
digitalWrite(pinLedAlarma, LOW);
digitalWrite(pinLedMovimiento, LOW);
esperandoSegundaSenal = false;
controlarBuzzersRemotos("alarma_off");
}
}
if (alarmaActivada) {
playWeoWeoAlarm();
delay(500);
} else {
noTone(pinBuzzer);
}
valorAlarma = alarmaActivada ? 1 : 0;
static unsigned long lastStatusTime = 0;
if (millis() - lastStatusTime >= 250) {
Serial.print("Voltaje: ");
Serial.print(voltaje);
Serial.print("\tMovimiento: ");
Serial.print(valorMovimiento);
Serial.print("\tAlarma: ");
Serial.println(valorAlarma);
lastStatusTime = millis();
}
delay(50);
}