#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <MFRC522.h>
// ── WIFI ─────────────────────────────
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
// ── FIREBASE ─────────────────────────
#define FIREBASE_HOST "https://camionesitt-default-rtdb.firebaseio.com"
// ── RFID ─────────────────────────────
#define SS_PIN 5
#define RST_PIN 4
MFRC522 mfrc522(SS_PIN, RST_PIN);
// ── LCD ──────────────────────────────
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ── CONTROL ──────────────────────────
String lastUID = "";
unsigned long lastScanTime = 0;
#define COOLDOWN 3000
// ===================================================
// SETUP
// ===================================================
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("===== INICIO =====");
Wire.begin(21, 22);
lcd.init();
lcd.backlight();
lcd.print("Iniciando...");
SPI.begin();
mfrc522.PCD_Init();
// WiFi
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
lcd.clear();
lcd.print("Conectando WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi OK");
lcd.clear();
lcd.print("WiFi OK");
delay(1500);
lcd.clear();
lcd.print("Acerca tarjeta");
}
// ===================================================
// LOOP
// ===================================================
void loop() {
if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial()) return;
String uid = leerUID();
unsigned long ahora = millis();
Serial.println("UID: " + uid);
// Anti doble scan
if (uid == lastUID && (ahora - lastScanTime) < COOLDOWN) {
Serial.println("Doble escaneo");
registrarAlerta("DOBLE_ESCANEO", uid);
lcd.clear();
lcd.print("ERROR");
lcd.setCursor(0,1);
lcd.print("Doble scan");
delay(2000);
lcd.clear();
lcd.print("Acerca tarjeta");
return;
}
lastUID = uid;
lastScanTime = ahora;
procesar(uid);
delay(1500);
lcd.clear();
lcd.print("Acerca tarjeta");
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
// ===================================================
// PROCESAR UID
// ===================================================
void procesar(String uid) {
HTTPClient http;
String url = String(FIREBASE_HOST) + "/camiones.json";
http.begin(url);
int code = http.GET();
if (code != 200) {
Serial.println("Error Firebase");
return;
}
String payload = http.getString();
http.end();
int pos = payload.indexOf(uid);
if (pos == -1) {
Serial.println("NO REGISTRADO");
registrarAlerta("NO_REGISTRADO", uid);
lcd.clear();
lcd.print("INTRUSO");
return;
}
// Obtener nombre del camion
int start = payload.lastIndexOf("\"", pos - 5);
int end = payload.indexOf("\":", start);
String nombre = payload.substring(start + 1, end);
Serial.println("Camion: " + nombre);
String estado = obtenerEstado(nombre);
if (estado == "DENTRO") {
salida(nombre, uid);
} else {
entrada(nombre, uid);
}
}
// ===================================================
// ENTRADA
// ===================================================
void entrada(String nombre, String uid) {
Serial.println("ENTRADA");
lcd.clear();
lcd.print("ENTRADA");
lcd.setCursor(0,1);
lcd.print(nombre);
int enPlanta = leerNumero("/estado_actual/camiones_en_planta");
int entradas = leerNumero("/estado_actual/entradas_total");
int entradasCamion = leerNumero("/camiones/" + nombre + "/entradas");
enviarPUT("/camiones/" + nombre + "/estado", "\"DENTRO\"");
enviarPUT("/camiones/" + nombre + "/entradas", String(entradasCamion + 1));
enviarPUT("/estado_actual/ultimo_evento", "\"ENTRADA\"");
enviarPUT("/estado_actual/ultimo_uid", "\"" + uid + "\"");
enviarPUT("/estado_actual/camiones_en_planta", String(enPlanta + 1));
enviarPUT("/estado_actual/entradas_total", String(entradas + 1));
registrarEvento("ENTRADA", nombre, uid);
}
// ===================================================
// SALIDA
// ===================================================
void salida(String nombre, String uid) {
Serial.println("SALIDA");
lcd.clear();
lcd.print("SALIDA");
lcd.setCursor(0,1);
lcd.print(nombre);
int enPlanta = leerNumero("/estado_actual/camiones_en_planta");
int salidas = leerNumero("/estado_actual/salidas_total");
int salidasCamion = leerNumero("/camiones/" + nombre + "/salidas");
if (enPlanta > 0) enPlanta--;
enviarPUT("/camiones/" + nombre + "/estado", "\"FUERA\"");
enviarPUT("/camiones/" + nombre + "/salidas", String(salidasCamion + 1));
enviarPUT("/estado_actual/ultimo_evento", "\"SALIDA\"");
enviarPUT("/estado_actual/ultimo_uid", "\"" + uid + "\"");
enviarPUT("/estado_actual/camiones_en_planta", String(enPlanta));
enviarPUT("/estado_actual/salidas_total", String(salidas + 1));
registrarEvento("SALIDA", nombre, uid);
}
// ===================================================
// EVENTOS
// ===================================================
void registrarEvento(String tipo, String nombre, String uid) {
String ts = String(millis());
enviarPUT("/eventos/" + ts + "/tipo", "\"" + tipo + "\"");
enviarPUT("/eventos/" + ts + "/camion", "\"" + nombre + "\"");
enviarPUT("/eventos/" + ts + "/uid", "\"" + uid + "\"");
}
// ===================================================
// ALERTAS
// ===================================================
void registrarAlerta(String tipo, String uid) {
String ts = String(millis());
enviarPUT("/alertas/" + ts + "/tipo", "\"" + tipo + "\"");
enviarPUT("/alertas/" + ts + "/uid", "\"" + uid + "\"");
enviarPUT("/estado_actual/ultima_alerta", "\"" + tipo + "\"");
}
// ===================================================
// LEER NUMERO FIREBASE
// ===================================================
int leerNumero(String path) {
HTTPClient http;
String url = String(FIREBASE_HOST) + path + ".json";
http.begin(url);
int code = http.GET();
if (code != 200) {
http.end();
return 0;
}
String payload = http.getString();
http.end();
payload.replace("\"", "");
return payload.toInt();
}
// ===================================================
// OBTENER ESTADO
// ===================================================
String obtenerEstado(String nombre) {
HTTPClient http;
String url = String(FIREBASE_HOST) + "/camiones/" + nombre + "/estado.json";
http.begin(url);
int code = http.GET();
if (code != 200) {
http.end();
return "FUERA";
}
String estado = http.getString();
http.end();
estado.replace("\"", "");
return estado;
}
// ===================================================
// HTTP PUT
// ===================================================
void enviarPUT(String path, String data) {
HTTPClient http;
String url = String(FIREBASE_HOST) + path + ".json";
http.begin(url);
http.addHeader("Content-Type", "application/json");
int code = http.PUT(data);
Serial.println("PUT " + path + " -> " + String(code));
http.end();
}
// ===================================================
// UID
// ===================================================
String leerUID() {
String uid = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
if (mfrc522.uid.uidByte[i] < 0x10) uid += "0";
uid += String(mfrc522.uid.uidByte[i], HEX);
}
uid.toUpperCase();
return uid;
}