#include <WiFi.h>
#include <HTTPClient.h>
#include <Keypad.h>
#include <ESP32Servo.h>
#include <SPI.h>
#include <MFRC522.h>
// --- 1. WIFI ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// --- 2. LIEN TA3 MANEL (CLOUDFLARE) ---
String serverName = "https://yarn-ref-scripts-acre.trycloudflare.com" ;
// --- 3. CONFIGURATION RFID 🆕 ---
#define SS_PIN 5
#define RST_PIN 22
MFRC522 rfid(SS_PIN, RST_PIN);
// --- 4. KEYPAD CONFIG (Les Pins Jdad bash ma ytkhltouch m3a RFID) 🛠️ ---
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
// Bdeltlek les pins hna bash nkhelliw 5, 18, 19 l'RFID
byte rowPins[ROWS] = {32, 33, 26, 27};
byte colPins[COLS] = {14, 12, 16, 4};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// --- 5. HARDWARE CONFIG ---
Servo gateServo;
const int servoPin = 13;
const int buzzerPin = 25;
String inputBuffer = "";
void setup() {
Serial.begin(115200);
// Initialisation Moteur & Buzzer
gateServo.attach(servoPin);
gateServo.write(0);
pinMode(buzzerPin, OUTPUT);
// Initialisation RFID 🆕
SPI.begin();
rfid.PCD_Init();
// Connexion WiFi
Serial.print("Connecting to WiFi...");
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\n[SUCCESS] WiFi Connected!");
Serial.println("===============================");
Serial.println("1. Scannez le Badge (RFID) pour entrer");
Serial.println("2. [Apt Num] + * : Resident Entry (Backup)");
Serial.println("3. [Apt Num] + # : Guest Calling");
Serial.println("===============================\n");
}
void loop() {
// -----------------------------------------------------
// SCENARIO 1 : L'UTILISATEUR YFAWET L'BADGE (RFID) 🎫
// -----------------------------------------------------
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
String uid = "";
for (byte i = 0; i < rfid.uid.size; i++) {
uid += String(rfid.uid.uidByte[i] < 0x10 ? "0" : "");
uid += String(rfid.uid.uidByte[i], HEX);
}
uid.toUpperCase();
Serial.println("\n[SCAN] Badge detecte! UID: " + uid);
// Nba3tho l'ID ta3 l'badge l'Manel bash tverifih
verifyRFID(uid);
rfid.PICC_HaltA(); // Bash ma yqrahsh bzaf khatrat f thanya
}
// -----------------------------------------------------
// SCENARIO 2 & 3 : L'UTILISATEUR YSTA3MEL CLAVIER 🔢
// -----------------------------------------------------
char key = keypad.getKey();
if (key) {
if (key != '*' && key != '#') {
inputBuffer += key;
Serial.print(key);
}
// GUEST LOGIC (ex: 12#) - Unexpected Guest
else if (key == '#') {
Serial.println("\n[INFO] Guest is calling Apartment: " + inputBuffer);
callGuestApartment(inputBuffer);
inputBuffer = "";
}
// RESIDENT LOGIC BACKUP (ex: 12*) - Ida nsa l'badge ta3ou
else if (key == '*') {
Serial.println("\n[INFO] Verifying Resident for Appt: " + inputBuffer + "...");
verifyResidentDB(inputBuffer);
inputBuffer = "";
}
}
}
// ==========================================
// LES FONCTIONS TA3 L'API
// ==========================================
// --- SOUND FUNCTION ---
void beep(int times) {
for(int i=0; i<times; i++){
tone(buzzerPin, 1000);
delay(150);
noTone(buzzerPin);
delay(150);
}
}
// --- FUNCTION 1: VERIFIER L'BADGE (RFID) 🆕 ---
void verifyRFID(String badgeID) {
if(WiFi.status() == WL_CONNECTED){
HTTPClient http;
// Tqder Manel tbaddel had l'route l'esem li t7abou f l'backend ta3ha
http.begin(serverName + "/scan-badge");
http.addHeader("Content-Type", "application/json");
String jsonBody = "{\"badge_id\":\"" + badgeID + "\"}";
int httpResponseCode = http.POST(jsonBody);
if(httpResponseCode == 200) {
Serial.println("[SUCCESS] Badge Verified! Access Granted.");
openDoor();
} else {
Serial.println("[DENIED] Unknown Badge!");
beep(3);
}
http.end();
}
}
// --- FUNCTION 2: VERIFIER F LA BASE DE DONNEES (KEYPAD) ---
void verifyResidentDB(String aptNum) {
if(WiFi.status() == WL_CONNECTED){
HTTPClient http;
http.begin(serverName + "/check-apartment");
http.addHeader("Content-Type", "application/json");
String jsonBody = "{\"apartment\":\"" + aptNum + "\"}";
int httpResponseCode = http.POST(jsonBody);
if(httpResponseCode == 200) {
Serial.println("[SUCCESS] Resident Verified! Opening Gate...");
openDoor();
} else {
Serial.println("[DENIED] Apartment not found in Database!");
beep(3);
}
http.end();
}
}
// --- FUNCTION 3: GUEST CALL ---
void callGuestApartment(String aptNum) {
if(WiFi.status() == WL_CONNECTED){
HTTPClient http;
http.begin(serverName + "/guest-arrival");
http.addHeader("Content-Type", "application/json");
String jsonBody = "{\"apartment\":\"" + aptNum + "\"}";
int httpResponseCode = http.POST(jsonBody);
if(httpResponseCode > 0) {
Serial.println("[SUCCESS] Notification sent to owner's app.");
beep(2);
} else {
Serial.println("[ERROR] Failed to send notif!");
}
http.end();
}
}
// --- FUNCTION 4: OPEN GATE ---
void openDoor() {
beep(1);
gateServo.write(90);
delay(5000);
gateServo.write(0);
Serial.println("[ACTION] Gate Closed.");
}