#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <PubSubClient.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

// Pines
const int trigPin = 19;
const int echoPin = 23;
const int relayBombaPin = 18;
const int relayLed1Pin = 14;
const int relayLed2Pin = 27;
const int botonStartPin = 13;
const int botonStopPin = 25;
const int buzzerPin = 26;
const int ledAlarmaPin = 33;

// Estado del sistema
bool sistemaActivo = false;
bool bombaEncendida = false;
bool alarmaActiva = false;

// Umbrales del tanque (15 cm alto)
const float nivelCritico = 15.0;
const float nivelBajo = 10.0;
const float nivelMedio = 5.0;

// Wi‑Fi & MQTT
const char* ssid = "Wokwi-GUEST";  // Cambia esto si usas ESP32 físico
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* mqtt_topic = "esp32/wokwi/nivel";

WiFiClient espClient;
PubSubClient client(espClient);

float medirDistanciaCM() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duracion = pulseIn(echoPin, HIGH, 30000);
  if (duracion == 0) return -1;
  return (duracion / 2.0) * 0.0343;
}

void conectarWiFi() {
  Serial.print("Conectando a WiFi");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" conectado!");
}

void conectarMQTT() {
  while (!client.connected()) {
    Serial.print("MQTT connect…");
    if (client.connect("ESP32-Wokwi")) {
      Serial.println(" listo!");
    } else {
      Serial.print("falló rc=");
      Serial.print(client.state());
      Serial.println(", retry en 5 s");
      delay(5000);
    }
  }
}

// 🔴 NUEVA FUNCIÓN MODIFICADA
void publicarMQTT(float dist) {
  char payload[128];

  const char* estadoBomba = bombaEncendida ? "ENCENDIDA" : "APAGADA";
  const char* estadoAlarma = alarmaActiva ? "ACTIVA" : "INACTIVA";

  snprintf(payload, sizeof(payload),
           "{\"nivel\": %.2f, \"bomba\": \"%s\", \"alarma\": \"%s\"}",
           dist, estadoBomba, estadoAlarma);

  client.publish(mqtt_topic, payload);
}

void setup() {
  Serial.begin(115200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(relayBombaPin, OUTPUT);
  pinMode(relayLed1Pin, OUTPUT);
  pinMode(relayLed2Pin, OUTPUT);
  pinMode(botonStartPin, INPUT_PULLUP);
  pinMode(botonStopPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  pinMode(ledAlarmaPin, OUTPUT);

  digitalWrite(relayBombaPin, LOW);
  digitalWrite(relayLed1Pin, LOW);
  digitalWrite(relayLed2Pin, LOW);
  digitalWrite(buzzerPin, LOW);
  digitalWrite(ledAlarmaPin, LOW);

  lcd.init();
  lcd.backlight();
  lcd.print("Iniciando...");
  conectarWiFi();
  lcd.setCursor(0, 1);
  lcd.print("WiFi listo");
  delay(1000);
  lcd.clear();

  client.setServer(mqtt_server, mqtt_port);
  conectarMQTT();
}

void loop() {
  if (!client.connected()) conectarMQTT();
  client.loop();

  float distancia = medirDistanciaCM();

  bool btnStart = digitalRead(botonStartPin) == LOW;
  bool btnStop = digitalRead(botonStopPin) == LOW;

  if (btnStart) { sistemaActivo = true; alarmaActiva = false; }
  if (btnStop) { sistemaActivo = false; bombaEncendida = false; alarmaActiva = false; }

  if (sistemaActivo) {
    if (distancia < 0 || distancia >= nivelCritico) {
      bombaEncendida = false;
      digitalWrite(relayLed1Pin, LOW);
      digitalWrite(relayLed2Pin, LOW);
      alarmaActiva = true;
    }
    else if (distancia > nivelBajo && distancia < nivelCritico) {
      bombaEncendida = true;
      digitalWrite(relayLed1Pin, LOW);
      digitalWrite(relayLed2Pin, HIGH);
      alarmaActiva = false;
    }
    else if (distancia > nivelMedio && distancia <= nivelBajo) {
      bombaEncendida = true;
      digitalWrite(relayLed1Pin, HIGH);
      digitalWrite(relayLed2Pin, LOW);
      alarmaActiva = false;
    }
    else {
      bombaEncendida = false;
      digitalWrite(relayLed1Pin, HIGH);
      digitalWrite(relayLed2Pin, HIGH);
      alarmaActiva = false;
    }
  } else {
    bombaEncendida = false;
    digitalWrite(relayLed1Pin, LOW);
    digitalWrite(relayLed2Pin, LOW);
    alarmaActiva = false;
  }

  digitalWrite(relayBombaPin, bombaEncendida ? LOW : HIGH);
  digitalWrite(buzzerPin, alarmaActiva ? HIGH : LOW);
  digitalWrite(ledAlarmaPin, alarmaActiva ? HIGH : LOW);

  lcd.setCursor(0, 0);
  lcd.print("Dist: ");
  if (distancia < 0) lcd.print("Error   ");
  else {
    lcd.print(distancia);
    lcd.print(" cm   ");
  }

  lcd.setCursor(0, 1);
  if (!sistemaActivo) lcd.print("Sistema OFF  ");
  else if (distancia < 0 || distancia >= nivelCritico) lcd.print("VACIO        ");
  else if (distancia > nivelBajo) lcd.print("BAJO         ");
  else if (distancia > nivelMedio) lcd.print("MEDIO        ");
  else lcd.print("ALTO         ");

  // Publicar MQTT cada 1 segundo
  static unsigned long lastEnvio = 0;
  if (millis() - lastEnvio > 1000) {
    publicarMQTT(distancia);
    lastEnvio = millis();
  }

  delay(500);
}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module