//#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SdFat.h>
#include <RTClib.h>
/*
ESP32 (38 PINS) WIRING
SPI
MOSI GPIO 23
MISO GPIO 19
SCK GPIO 18
RFID CS GPIO 2
RFID RST GPIO 17
TFT CS GPIO 5
TFT RST GPIO 16
TFT DC GPIO 15
SD CS GPIO 4
*/
#define SS_PIN 5
#define RST_PIN 16
MFRC522 mfrc522(SS_PIN, RST_PIN);
#define nextion Serial2
#define SUN 0
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define TIME(h, m) ((h)*60 + (m))
struct Student {
const char* uid;
const char* name;
bool loggedIn;
};
struct Schedule {
int day;
int startMinutes;
int endMinutes;
};
struct Section {
const char* name;
Schedule* schedules;
int numSchedules;
Student* students;
int numStudents;
};
// DATA
/*
NEW SECTION AND SCHEDULE TEMPLATE
Student sectNumberStudents[] = {
{"RFID UID", "name", false},
};
Schedule sectNumberSchedules[] = {
{MON, TIME(8,0), TIME(12,0)},
};
*/
Student sect1Students[9] = {
{"0cf2a703", "Aguirre, Mary Grace A.", false},
{"8373a52c", "Eraldo, Miraphem A.", false},
{"7ae9a703", "Esplana, Geff B.", false},
{"dea3a703", "Libertino, Xyryl Dave L.", false},
{"d3de1d2d", "Montealegre, Symon Dwayne A.", false},
{"d699a603", "Nagares, Jerlyn Mae B.", false},
{"3cf3a603", "Reyes, Chris Paul B.", false},
{"ac6db603", "Santos, Harleni Xandria T.", false},
{"53dbb503", "Tranquilino, Neil Ryan D.G.", false}
};
Schedule sect1Schedules[] = {
{MON, TIME(12,20), TIME(17,30)},
{TUE, TIME(12,20), TIME(16,30)},
{WED, TIME(12,10), TIME(16,30)},
{THU, TIME(12,10), TIME(16,30)}
};
Student sect2Students[8] = {
{"63a5a603", "Almodal, Nicole Kyla R.", false},
{"b3fc3a2d", "Arriola, Princess Ahlondra C.", false},
{"628fa603", "Berdan, Janine O.", false},
{"09cfb603", "Carajay, Reinjun M.", false},
{"0a7cb603", "Chan, Jov Simon B.", false},
{"2404b703", "Custodio, Hannah Lee J.", false},
{"5ad2b503", "Gorgonio, Karl Arthur D.", false},
{"beacb603", "Perez, Rhamz Dave R.", false},
};
Schedule sect2Schedules[] = {
{MON, TIME(12,20), TIME(17,30)},
{TUE, TIME(12,20), TIME(16,30)},
{WED, TIME(11,10), TIME(15,20)},
{THU, TIME(11,10), TIME(15,20)}
};
Student sect3Students[7] = {
{"5c20a703", "Bautista, Princess Jamirah A.", false},
{"d3f1f72c", "Diga, William Rodly A.", false},
{"e3107d2d", "Gipulan, Ayesha Lynzee M.", false},
{"6332f22c", "Rocero, Irish Simone V.", false},
{"cadeb603", "Samonte, Tricia Jane C.", false},
{"532e892d", "Ternate, Sheenary Miles C.", false},
{"2398a736", "Turgo, Mandy Chrizel F.", false},
};
Schedule sect3Schedules[] = {
{MON, TIME(12,10), TIME(16,30)},
{TUE, TIME(13,10), TIME(16,30)},
{WED, TIME(11,20), TIME(16,30)},
{THU, TIME(11,20), TIME(16,30)}
};
Student sect4Students[6] = {
{"3b4cb603", "Aduca, Joyce Anne", false},
{"53a8dc2c", "Bautista, Queen Miszha Euri H.", false},
{"862ab603", "Hancock, Sydney Shelldon C.", false},
{"c72da703", "Jugo, Raim Jannah Sophia C.", false},
{"0c0aa803", "Licera, Cassey Mhariz C.", false},
{"735d4416", "Reyes, Princess Nicole E.", false},
};
Schedule sect4Schedules[] = {
{MON, TIME(12,20), TIME(16,30)},
{TUE, TIME(12,20), TIME(16,30)},
{WED, TIME(12,10), TIME(17,0)},
{THU, TIME(12,10), TIME(16,30)}
};
Section sections[] = {
// {"Section Template", sectNumberSchedules, 1, sectNumberStudents, 1}
{"12 STEMa - St. Luke the Evangelist", sect1Schedules, 4, sect1Students, 9},
{"12 STEMb - St. Hubert of Liege", sect2Schedules, 4, sect2Students, 8},
{"12 STEMc - St. Barbara", sect3Schedules, 4, sect3Students, 7},
{"12 STEMd - St. Dominic dela Calzada", sect4Schedules, 4, sect4Students, 6}
};
int sectionsSize = sizeof(sections) / sizeof(sections[0]);
// ================= GLOBALS =================
int currentDay = -1;
int currentMinutes = -1;
String lastUID = "";
unsigned long lastScanMillis = 0;
const unsigned long scanCooldown = 3000;
unsigned long loopMillis = 0;
const unsigned long loopCooldown = 1000;
Section* activeSection = nullptr;
Schedule* activeSchedule = nullptr;
Section* currentSectionOnDisplay = nullptr;
// ================= FUNCTIONS =================
void parseTimeFromLogger(String s) {
s.trim();
if (s.length() < 5) return;
String dayStr = s.substring(0, 3);
if (dayStr == "SUN") currentDay = SUN;
else if (dayStr == "MON") currentDay = MON;
else if (dayStr == "TUE") currentDay = TUE;
else if (dayStr == "WED") currentDay = WED;
else if (dayStr == "THU") currentDay = THU;
else if (dayStr == "FRI") currentDay = FRI;
else if (dayStr == "SAT") currentDay = SAT;
else return;
int spaceIndex = s.indexOf(' ');
if (spaceIndex != -1) {
currentMinutes = s.substring(spaceIndex + 1).toInt();
}
}
Student* findStudent(const String& uid, Section*& outSection) {
for (int s = 0; s < sectionsSize; s++) {
for (int i = 0; i < sections[s].numStudents; i++) {
if (uid == sections[s].students[i].uid) {
outSection = §ions[s];
return §ions[s].students[i];
}
}
}
return nullptr;
}
bool isInSchedule(Section* sec) {
for (int i = 0; i < sec->numSchedules; i++) {
Schedule sch = sec->schedules[i];
if (currentDay == sch.day &&
currentMinutes >= sch.startMinutes &&
currentMinutes < sch.endMinutes) {
return true;
}
}
return false;
}
Schedule* getCurrentSchedule(Section* sec) {
for (int i = 0; i < sec->numSchedules; i++) {
Schedule& sch = sec->schedules[i];
if (currentDay == sch.day &&
currentMinutes >= sch.startMinutes &&
currentMinutes < sch.endMinutes) {
return &sch;
}
}
return nullptr;
}
// ================= SETUP =================
void setup() {
Serial.begin(115200);
nextion.begin(9600, SERIAL_8N1, 16, 17);
SPI.begin(18, 19, 23, 5);
mfrc522.PCD_Init();
Serial.println("ESP32 ready");
}
// ================= LOOP =================
void loop() {
unsigned long currMillis = millis();
if (Serial.available()) {
String s = Serial.readStringUntil('\n');
parseTimeFromLogger(s);
}
if (currMillis - loopMillis >= loopCooldown) {
loopMillis = currMillis;
activeSection = nullptr;
activeSchedule = nullptr;
for (int s = 0; s < sectionsSize; s++) {
Schedule* sch = getCurrentSchedule(§ions[s]);
if (sch) {
activeSection = §ions[s];
activeSchedule = sch;
break;
}
}
}
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
String scannedUid = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
if (mfrc522.uid.uidByte[i] < 0x10) scannedUid += "0";
scannedUid += String(mfrc522.uid.uidByte[i], HEX);
}
if (scannedUid != lastUID || currMillis - lastScanMillis >= scanCooldown) {
lastUID = scannedUid;
lastScanMillis = currMillis;
Section* sec = nullptr;
Student* stu = findStudent(scannedUid, sec);
if (!stu) {
Serial.println("Unknown card");
}
else if (!isInSchedule(sec)) {
Serial.println("Not in schedule");
}
else {
char buffer[6];
sprintf(buffer, "%02d:%02d", currentMinutes / 60, currentMinutes % 60);
String displayText = String(buffer) + " | " + stu->name;
bool isLogin = !stu->loggedIn;
stu->loggedIn = isLogin;
String finalLog = String(sec->name) + " | " + displayText;
finalLog += isLogin ? " - login" : " - logout";
Serial.println(finalLog); // 🔥 THIS FIXES SD LOGGING
if (isLogin) {
nextion.print("slt0.txt=slt0.txt+\"\\r");
nextion.print(displayText);
nextion.print("\"");
} else {
nextion.print("slt1.txt=slt1.txt+\"\\r");
nextion.print(displayText);
nextion.print("\"");
}
nextion.write(0xFF);
nextion.write(0xFF);
nextion.write(0xFF);
}
}
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}