// Definición de pines
const int rele_valvula_pb = 16;     // Relé para válvula planta baja
const int rele_valvula_pp = 17;     // Relé para válvula primer piso
const int rele_caldera = 18;        // Relé para caldera

const int fin_carrera_pb = 32;      // Final de carrera planta baja
const int fin_carrera_pp = 33;      // Final de carrera primer piso
const int termostato_pb = 34;       // Termostato planta baja
const int termostato_pp = 35;       // Termostato primer piso

// Variables de estado
bool caldera_encendida = false;
bool valvula_pb_abierta = false;
bool valvula_pp_abierta = false;

// Temporizadores
unsigned long tiempo_valvula_pb = 0;
unsigned long tiempo_valvula_pp = 0;
const unsigned long timeout_valvula = 30000; // Timeout de 30 segundos
unsigned long tiempo_espera_caldera = 0;
const unsigned long tiempo_espera = 30000; // 5 minutos
bool esperar_cierre_valvulas = false;

void setup() {
  // Inicializar puerto serie
  Serial.begin(115200);
  
  // Configuración de pines
  pinMode(rele_valvula_pb, OUTPUT);
  pinMode(rele_valvula_pp, OUTPUT);
  pinMode(rele_caldera, OUTPUT);
  pinMode(fin_carrera_pb, INPUT);
  pinMode(fin_carrera_pp, INPUT);
  pinMode(termostato_pb, INPUT);
  pinMode(termostato_pp, INPUT);

  // Estado inicial de relés
  digitalWrite(rele_valvula_pb, LOW);
  digitalWrite(rele_valvula_pp, LOW);
  digitalWrite(rele_caldera, LOW);
}

void loop() {
  // Leer estados de termostatos y finales de carrera
  bool termostato_pb_activo = digitalRead(termostato_pb);
  bool termostato_pp_activo = digitalRead(termostato_pp);
  valvula_pb_abierta = digitalRead(fin_carrera_pb);
  valvula_pp_abierta = digitalRead(fin_carrera_pp);

  // Control de la planta baja
  if (termostato_pb_activo) {
    if (!valvula_pb_abierta && (millis() - tiempo_valvula_pb > timeout_valvula)) {
      Serial.println("Termostato planta baja activo. Abriendo válvula planta baja...");
      digitalWrite(rele_valvula_pb, HIGH);
      tiempo_valvula_pb = millis(); // Guardar el tiempo de inicio
    }
    if (valvula_pb_abierta && !caldera_encendida) {
      Serial.println("Válvula planta baja abierta. Encendiendo caldera...");
      encenderCaldera();
    }
  }

  // Control del primer piso
  if (termostato_pp_activo) {
    if (!valvula_pp_abierta && (millis() - tiempo_valvula_pp > timeout_valvula)) {
      Serial.println("Termostato primer piso activo. Abriendo válvula primer piso...");
      digitalWrite(rele_valvula_pp, HIGH);
      tiempo_valvula_pp = millis(); // Guardar el tiempo de inicio
    }
    if (valvula_pp_abierta && !caldera_encendida) {
      Serial.println("Válvula primer piso abierta. Encendiendo caldera...");
      encenderCaldera();
    }
  }

  // Chequear timeout de válvula planta baja solo si está en proceso de apertura
  if (millis() - tiempo_valvula_pb > timeout_valvula && !valvula_pb_abierta && tiempo_valvula_pb != 0) {
    Serial.println("Error: La válvula de planta baja no se abrió completamente dentro del tiempo esperado.");
    digitalWrite(rele_valvula_pb, LOW); // Cerrar la válvula
    tiempo_valvula_pb = 0; // Resetear el tiempo de apertura
  }

  // Chequear timeout de válvula primer piso solo si está en proceso de apertura
  if (millis() - tiempo_valvula_pp > timeout_valvula && !valvula_pp_abierta && tiempo_valvula_pp != 0) {
    Serial.println("Error: La válvula del primer piso no se abrió completamente dentro del tiempo esperado.");
    digitalWrite(rele_valvula_pp, LOW); // Cerrar la válvula
    tiempo_valvula_pp = 0; // Resetear el tiempo de apertura
  }

  // Apagar caldera si no hay demanda de calefacción
  if (!termostato_pb_activo && !termostato_pp_activo && caldera_encendida) {
    Serial.println("No se necesita calefacción en ningún piso. Apagando caldera...");
    apagarCaldera();
    tiempo_espera_caldera = millis(); // Guardar el tiempo de inicio de espera
    esperar_cierre_valvulas = true;
  }

  // Verificar si han pasado los 5 minutos de espera antes de cerrar las válvulas
  if (esperar_cierre_valvulas && (millis() - tiempo_espera_caldera > tiempo_espera)) {
    Serial.println("5 minutos pasados. Cerrando válvulas...");
    digitalWrite(rele_valvula_pb, LOW);
    digitalWrite(rele_valvula_pp, LOW);
    esperar_cierre_valvulas = false; // Resetear la bandera de espera
  }
}

void encenderCaldera() {
  if (!caldera_encendida) {
    digitalWrite(rele_caldera, HIGH);
    caldera_encendida = true;
    Serial.println("Caldera encendida.");
  }
}

void apagarCaldera() {
  if (caldera_encendida) {
    digitalWrite(rele_caldera, LOW);
    caldera_encendida = false;
    Serial.println("Caldera apagada.");
  }
}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
Termostato PB
Termostato 1er Piso
Final de Carrera PB
Final de Carrera 1er Piso