#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <Wire.h>
#include "RTClib.h"
// WIFI CONFIG
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const String SCRIPT_URL = "https://script.google.com/macros/s/AKfycbyjf42vrBKf3DMt6bmosTxuNRHcUNH7WPho3qRxiQoMWEt7E4w5Za2iD4Uc8aux9PUi/exec";
// PIN CONFIG
#define SS_PIN 5
#define RST_PIN 4
#define BUZZER_PIN 2
#define GREEN_LED 13
#define RED_LED 12
// STAFF DATA
String staffNames[] = {"SATISH", "RAJ", "ANU", "VENU"};
String staffCards[] = {"01020304", "11223344", "55667788", "04E2A3B1"};
bool isInOffice[] = {false, false, false, false};
MFRC522 rfid(SS_PIN, RST_PIN);
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231 rtc;
void setup() {
Serial.begin(115200);
SPI.begin();
rfid.PCD_Init();
pinMode(BUZZER_PIN, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, LOW);
Wire.begin(21, 22);
if (!rtc.begin()) {
Serial.println("RTC not found!");
while (1);
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
lcd.init();
lcd.backlight();
lcd.print("Connecting WiFi");
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
attempts++;
}
lcd.clear();
if (WiFi.status() == WL_CONNECTED) {
lcd.print("WiFi OK!");
Serial.println("WiFi Connected");
} else {
lcd.print("WiFi Failed!");
Serial.println("WiFi Failed");
}
delay(2000);
}
void loop() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Scan Employee");
lcd.setCursor(0,1);
lcd.print("Card...");
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, LOW);
if (!rfid.PICC_IsNewCardPresent()) {
delay(200);
return;
}
if (!rfid.PICC_ReadCardSerial()) return;
String cardID = "";
for (byte i = 0; i < rfid.uid.size; i++) {
if (rfid.uid.uidByte[i] < 0x10) cardID += "0";
cardID += String(rfid.uid.uidByte[i], HEX);
}
cardID.toUpperCase();
int empID = -1;
for (int i = 0; i < 4; i++) {
if (staffCards[i] == cardID) {
empID = i;
break;
}
}
if (empID == -1) {
lcd.clear();
lcd.print("UNKNOWN CARD!");
errorBeep();
rfid.PICC_HaltA();
delay(3000);
return;
}
String name = staffNames[empID];
String status = isInOffice[empID] ? "Check OUT" : "Check IN";
isInOffice[empID] = !isInOffice[empID];
// LED LOGIC
if (status == "Check IN") {
digitalWrite(GREEN_LED, HIGH);
digitalWrite(RED_LED, LOW);
} else {
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, HIGH);
}
String timestamp = getDateTime();
String date = timestamp.substring(0,10);
String time = timestamp.substring(11);
sendToGoogleSheets(name, cardID, status, date, time);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(name);
lcd.setCursor(0,1);
lcd.print(status + " " + time);
successBeep();
rfid.PICC_HaltA();
delay(4000);
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, LOW);
}
String getDateTime() {
DateTime now = rtc.now();
char buffer[25];
sprintf(buffer, "%02d-%02d-%04d %02d:%02d:%02d",
now.day(),
now.month(),
now.year(),
now.hour(),
now.minute(),
now.second());
return String(buffer);
}
void sendToGoogleSheets(String name, String card, String status, String date, String time) {
Serial.println("\n==============================");
Serial.println("ATTENDANCE DATA");
Serial.print("Name : "); Serial.println(name);
Serial.print("CardID : "); Serial.println(card);
Serial.print("Status : "); Serial.println(status);
Serial.print("Date : "); Serial.println(date);
Serial.print("Time : "); Serial.println(time);
Serial.println("==============================");
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
client.setInsecure();
HTTPClient https;
https.begin(client, SCRIPT_URL);
https.addHeader("Content-Type", "application/x-www-form-urlencoded");
String postData = "name=" + name +
"&card=" + card +
"&status=" + status +
"&date=" + date +
"&time=" + time;
int httpCode = https.POST(postData);
Serial.print("HTTP Response Code: ");
Serial.println(httpCode);
https.end();
}
}
void successBeep() {
tone(BUZZER_PIN, 1000, 300);
delay(400);
}
void errorBeep() {
for(int i=0; i<3; i++) {
tone(BUZZER_PIN, 2000, 200);
delay(300);
}
}