#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Servo.h>
#include <WiFi.h>
#include <HTTPClient.h>
// LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int SDA_PIN = 16;
const int SCL_PIN = 17;
// Pines
const int BUTTON_PIN = 21;
const int LED_PIN = 12;
const int BUZZER_PIN = 14;
const int SERVO_PIN = 15;
// WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const String backendURL = "https://edge-iot-test.onrender.com/api/validate";
// Estado
bool locked = true;
Servo lockServo;
// Debounce
int buttonState = HIGH;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50;
// Funciones auxiliares
void printLCD(const String& line1, const String& line2 = "") {
lcd.clear();
lcd.setCursor(0, 0); lcd.print(line1);
if (line2.length()) {
lcd.setCursor(0, 1); lcd.print(line2);
}
}
void soundAlarm() {
unsigned long endTime = millis() + 3000;
while (millis() < endTime) {
for (int f = 800; f <= 2000 && millis() < endTime; f += 20) {
tone(BUZZER_PIN, f, 10); delay(10);
}
for (int f = 2000; f >= 800 && millis() < endTime; f -= 20) {
tone(BUZZER_PIN, f, 10); delay(10);
}
}
noTone(BUZZER_PIN);
}
// Cerradura
void abrirCerradura(const String& motivo) {
locked = false;
digitalWrite(LED_PIN, HIGH);
lockServo.write(90);
tone(BUZZER_PIN, 1000, 200);
Serial.println(motivo + ". Abierta.");
printLCD("Acceso OK", motivo);
delay(1000);
noTone(BUZZER_PIN);
}
void cerrarCerradura() {
locked = true;
digitalWrite(LED_PIN, LOW);
lockServo.write(180);
tone(BUZZER_PIN, 500, 200);
Serial.println("Cerrada.");
printLCD("Cerradura C.");
delay(1000);
noTone(BUZZER_PIN);
}
void procesarToggle(const String& motivo) {
if (locked) abrirCerradura(motivo);
else cerrarCerradura();
}
// Validación remota
bool validarUsuario(String usuario) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = backendURL + "?user=" + usuario;
Serial.println("Accediendo a: " + url);
http.begin(url);
int httpCode = http.GET();
Serial.println("Código HTTP: " + String(httpCode));
if (httpCode == 200) {
String respuesta = http.getString();
respuesta.trim();
Serial.println("Respuesta cruda: " + respuesta);
http.end();
return respuesta == "true";
}
http.end();
} else {
Serial.println("WiFi no conectado.");
}
return false;
}
// Conexión WiFi
void conectarWiFi() {
printLCD("Conectando WiFi");
WiFi.begin(ssid, password, 6);
int intentos = 0;
while (WiFi.status() != WL_CONNECTED && intentos < 20) {
delay(500);
Serial.print(".");
intentos++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi conectado. IP: " + WiFi.localIP().toString());
printLCD("WiFi OK");
} else {
Serial.println("\nFallo WiFi.");
printLCD("WiFi ERROR");
}
delay(1000);
}
// DEMO por teclado
void demoValidacionInicial() {
printLCD("Ingrese usuario", "por Serial:");
Serial.println("Escribe tu nombre y presiona ENTER para validación inicial:");
while (!Serial.available()) {
delay(100);
}
String nombreDemo = Serial.readStringUntil('\n');
nombreDemo.trim();
if (nombreDemo.length()) {
bool autorizado = validarUsuario(nombreDemo);
if (autorizado) {
procesarToggle("Bienvenido " + nombreDemo);
} else {
Serial.println("Acceso denegado para: " + nombreDemo);
printLCD("Acceso Denegado", nombreDemo);
soundAlarm();
}
}
delay(2000);
}
// Setup
void setup() {
Serial.begin(115200);
Wire.begin(SDA_PIN, SCL_PIN);
lcd.init(); lcd.backlight();
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
lockServo.setPeriodHertz(50);
lockServo.attach(SERVO_PIN, 1000, 2000);
lockServo.write(180); // Cerrado
printLCD("FaceLock Init", "Cerradura Cerr.");
delay(1000);
conectarWiFi();
demoValidacionInicial();
printLCD("FaceLock Listo");
Serial.println("--- FaceLock Ready ---");
Serial.println("Presiona botón o escribe nombre:");
}
// Loop
void loop() {
// Botón físico
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) lastDebounceTime = millis();
if ((millis() - lastDebounceTime > debounceDelay) && (reading != buttonState)) {
if (reading == LOW) procesarToggle("Botón Pulsado");
buttonState = reading;
}
lastButtonState = reading;
// Entrada Serial
if (Serial.available()) {
String entrada = Serial.readStringUntil('\n');
entrada.trim();
if (entrada.length()) {
bool autorizado = validarUsuario(entrada);
if (autorizado) {
procesarToggle("Autenticado: " + entrada);
} else {
Serial.println("NO registrado: " + entrada);
printLCD("U. Desconocido", entrada);
soundAlarm();
if (!locked) cerrarCerradura();
}
}
}
}