317 lines
7.0 KiB
C++
317 lines
7.0 KiB
C++
#include <WiFi.h>
|
|
#include <SPI.h>
|
|
#include <MFRC522.h>
|
|
#include <Firebase_ESP_Client.h>
|
|
#include <Wire.h>
|
|
#include <LiquidCrystal_I2C.h>
|
|
|
|
// ================= WIFI =================
|
|
#define WIFI_SSID "ivann"
|
|
#define WIFI_PASSWORD "12345678"
|
|
|
|
// ================= FIREBASE =================
|
|
#define DATABASE_URL "https://doorguard-7fe8c-default-rtdb.firebaseio.com/"
|
|
#define DATABASE_SECRET "wKeZFSXj8cyroV5xnjkMIsefRgSvklLI9dgnnQJW"
|
|
|
|
// ================= RFID =================
|
|
#define SS_PIN 5
|
|
#define RST_PIN 4
|
|
#define SCK_PIN 18
|
|
#define MISO_PIN 19
|
|
#define MOSI_PIN 23
|
|
|
|
// ================= RELAY =================
|
|
#define RELAY_PIN 26
|
|
|
|
// ================= DOOR SENSOR =================
|
|
#define DOOR_SENSOR_PIN 27
|
|
|
|
// ================= EXIT =================
|
|
#define EXIT_BUTTON_PIN 32
|
|
|
|
// ================= LCD =================
|
|
#define SDA_LCD 21
|
|
#define SCL_LCD 22
|
|
|
|
// ================= OBJECT =================
|
|
MFRC522 rfid(SS_PIN, RST_PIN);
|
|
LiquidCrystal_I2C lcd(0x27, 16, 2);
|
|
|
|
FirebaseData fbdo;
|
|
FirebaseAuth auth;
|
|
FirebaseConfig config;
|
|
|
|
// ================= VARIABLE =================
|
|
String uidString = "";
|
|
String userName = "";
|
|
String lastDoorCommand = "CLOSE";
|
|
|
|
bool autoCloseActive = false;
|
|
unsigned long doorTimer = 0;
|
|
unsigned long lastScanTime = 0;
|
|
unsigned long lastButtonTime = 0;
|
|
|
|
bool lastDoorState = false;
|
|
|
|
// ================= SETUP =================
|
|
void setup()
|
|
{
|
|
Serial.begin(115200);
|
|
|
|
pinMode(RELAY_PIN, OUTPUT);
|
|
digitalWrite(RELAY_PIN, HIGH);
|
|
|
|
pinMode(DOOR_SENSOR_PIN, INPUT_PULLUP);
|
|
pinMode(EXIT_BUTTON_PIN, INPUT_PULLUP);
|
|
|
|
// LCD Initialization
|
|
Wire.begin(SDA_LCD, SCL_LCD);
|
|
lcd.init();
|
|
lcd.backlight();
|
|
|
|
lcd.setCursor(0,0);
|
|
lcd.print("SMART DOOR LOCK");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("STARTING...");
|
|
delay(2000);
|
|
|
|
// RFID Initialization
|
|
SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, SS_PIN);
|
|
rfid.PCD_Init();
|
|
|
|
// WIFI Connection
|
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
|
Serial.print("Connecting WiFi");
|
|
while (WiFi.status() != WL_CONNECTED)
|
|
{
|
|
Serial.print(".");
|
|
delay(500);
|
|
}
|
|
Serial.println("\nWiFi Connected");
|
|
|
|
// FIREBASE Configuration
|
|
config.database_url = DATABASE_URL;
|
|
config.signer.tokens.legacy_token = DATABASE_SECRET;
|
|
|
|
Firebase.begin(&config, &auth);
|
|
Firebase.reconnectWiFi(true);
|
|
Serial.println("Firebase Connected");
|
|
|
|
// Reset State Awal
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/doorControl", "CLOSE");
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/status", "IDLE");
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/lastScan", "IDLE");
|
|
}
|
|
|
|
// ================= LOOP =================
|
|
void loop()
|
|
{
|
|
handleRemoteControl();
|
|
handleRFID();
|
|
handleExitButton();
|
|
handleDoorSensor();
|
|
handleAutoClose();
|
|
}
|
|
|
|
// ================= REMOTE CONTROL =================
|
|
void handleRemoteControl()
|
|
{
|
|
if (Firebase.RTDB.getString(&fbdo, "/rfid/doorControl"))
|
|
{
|
|
String cmd = fbdo.stringData();
|
|
|
|
if (cmd != lastDoorCommand)
|
|
{
|
|
lastDoorCommand = cmd;
|
|
|
|
if (cmd == "OPEN")
|
|
{
|
|
lcd.clear();
|
|
lcd.setCursor(0,0);
|
|
lcd.print("DOOR OPENED");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("FROM APP");
|
|
|
|
openDoor(false);
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/status", "DOOR OPENED FROM APP");
|
|
}
|
|
else if (cmd == "CLOSE")
|
|
{
|
|
lcd.clear();
|
|
lcd.setCursor(0,0);
|
|
lcd.print("DOOR CLOSED");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("FROM APP");
|
|
|
|
closeDoor();
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/status", "DOOR CLOSED FROM APP");
|
|
}
|
|
delay(2000);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ================= HANDLE RFID =================
|
|
void handleRFID()
|
|
{
|
|
if (millis() - lastScanTime < 1000) return;
|
|
|
|
if (!rfid.PICC_IsNewCardPresent()) return;
|
|
if (!rfid.PICC_ReadCardSerial()) return;
|
|
|
|
uidString = "";
|
|
for (byte i = 0; i < rfid.uid.size; i++)
|
|
{
|
|
if (rfid.uid.uidByte[i] < 0x10) uidString += "0";
|
|
uidString += String(rfid.uid.uidByte[i], HEX);
|
|
}
|
|
uidString.toLowerCase();
|
|
|
|
Serial.print("UID Detected: ");
|
|
Serial.println(uidString);
|
|
|
|
lcd.clear();
|
|
lcd.setCursor(0,0);
|
|
lcd.print("SCANNING CARD...");
|
|
lcd.setCursor(0,1);
|
|
lcd.print(uidString);
|
|
|
|
bool access = false;
|
|
if (Firebase.RTDB.getBool(&fbdo, "/rfid/cards/" + uidString + "/active"))
|
|
{
|
|
if (fbdo.boolData()) access = true;
|
|
}
|
|
|
|
if (access)
|
|
{
|
|
if (Firebase.RTDB.getString(&fbdo, "/rfid/cards/" + uidString + "/name"))
|
|
{
|
|
userName = fbdo.stringData();
|
|
} else {
|
|
userName = "User";
|
|
}
|
|
}
|
|
|
|
if (access)
|
|
{
|
|
lcd.clear();
|
|
lcd.setCursor(0,0);
|
|
lcd.print("ACCESS GRANTED");
|
|
lcd.setCursor(0,1);
|
|
|
|
|
|
String displayWelcome = "WELCOME " + userName;
|
|
displayWelcome.toUpperCase();
|
|
lcd.print(displayWelcome);
|
|
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/lastScan", uidString);
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/status", "ACCESS_GRANTED");
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/lastUser", userName);
|
|
|
|
openDoor(true);
|
|
}
|
|
else
|
|
{
|
|
lcd.clear();
|
|
lcd.setCursor(0,0);
|
|
lcd.print("ACCESS DENIED");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("UNKNOWN CARD");
|
|
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/lastScan", uidString);
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/status", "ACCESS_DENIED");
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/notification", "ACCESS_DENIED");
|
|
}
|
|
|
|
delay(3500);
|
|
lastScanTime = millis();
|
|
|
|
rfid.PICC_HaltA();
|
|
rfid.PCD_StopCrypto1();
|
|
}
|
|
|
|
// ================= HANDLE EXIT BUTTON =================
|
|
void handleExitButton()
|
|
{
|
|
if (digitalRead(EXIT_BUTTON_PIN) == LOW && (millis() - lastButtonTime > 1000))
|
|
{
|
|
lcd.clear();
|
|
lcd.setCursor(0,0);
|
|
lcd.print("ACCESS GRANTED");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("EXIT");
|
|
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/status", "OPENED FROM INSIDE");
|
|
openDoor(true);
|
|
|
|
delay(1500);
|
|
lastButtonTime = millis();
|
|
}
|
|
}
|
|
|
|
// ================= OPEN DOOR =================
|
|
void openDoor(bool autoClose)
|
|
{
|
|
digitalWrite(RELAY_PIN, LOW);
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/relay", "ON");
|
|
|
|
delay(300);
|
|
rfid.PCD_Init();
|
|
|
|
if (autoClose)
|
|
{
|
|
autoCloseActive = true;
|
|
doorTimer = millis();
|
|
}
|
|
}
|
|
|
|
// ================= CLOSE DOOR =================
|
|
void closeDoor()
|
|
{
|
|
digitalWrite(RELAY_PIN, HIGH);
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/relay", "OFF");
|
|
|
|
autoCloseActive = false;
|
|
delay(300);
|
|
rfid.PCD_Init();
|
|
}
|
|
|
|
// ================= AUTO CLOSE =================
|
|
void handleAutoClose()
|
|
{
|
|
if (autoCloseActive && (millis() - doorTimer >= 3000))
|
|
{
|
|
closeDoor();
|
|
}
|
|
}
|
|
|
|
// ================= DOOR SENSOR =================
|
|
void handleDoorSensor()
|
|
{
|
|
bool doorOpen = digitalRead(DOOR_SENSOR_PIN);
|
|
|
|
if (doorOpen != lastDoorState)
|
|
{
|
|
lastDoorState = doorOpen;
|
|
lcd.clear();
|
|
|
|
if (doorOpen)
|
|
{
|
|
lcd.setCursor(0,0);
|
|
lcd.print("STATUS:");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("DOOR OPEN");
|
|
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/doorSensor", "OPEN");
|
|
}
|
|
else
|
|
{
|
|
lcd.setCursor(0,0);
|
|
lcd.print("STATUS:");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("DOOR CLOSED");
|
|
|
|
Firebase.RTDB.setString(&fbdo, "/rfid/doorSensor", "CLOSED");
|
|
}
|
|
}
|
|
} |