#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <WiFi.h>
#include <FirebaseESP32.h>
#define FIREBASE_HOST "https://smart-door-lock-81234-default-rtdb.firebaseio.com/"
#define FIREBASE_AUTH "VzN2lVXh36Mht6WYAH8yfs6wPl9g58M6bc138q48"
String uidMachine = "W7at9nCXzYQNVdcw0AeYLBSsP5o1";
int lastUpdate = 0;
const int lcdColumns = 16;
const int lcdRows = 2;
const int ROW_NUM = 4;
const int COLUMN_NUM = 4;
byte pin_rows[ROW_NUM] = {13, 12, 14, 27};
byte pin_column[COLUMN_NUM] = {26, 25, 33, 32};
const int buzzer_pin = 15;
const int button_pin = 34;
const int led_pin = 5;
const char* ssid = "Wokwi-GUEST";
const char* passwordWifi = "";
char keys[ROW_NUM][COLUMN_NUM] = {
{'1', '2', '3', 'L'},
{'4', '5', '6', 'C'},
{'7', '8', '9', 'A'},
{'*', '0', '#', 'E'}
};
String password = "";
long start_time = 0;
int prev_click = 0;
bool isDoorOpen = false, isLogin = false, isInput = false, isClick = false;
FirebaseData firebaseData;
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
void wifiConnect() {
WiFi.begin(ssid, passwordWifi);
Serial.print("Connecting wifi ");
while (WiFi.status() != WL_CONNECTED) {
delay(200);
Serial.print(".");
}
Serial.println("\nConnected!");
}
bool checkConnectToDB(){
wifiConnect();
Serial.println("Connecting firebase ... ");
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
if (!Firebase.beginStream(firebaseData, "/Log"))
{
Serial.println("Could not begin stream");
Serial.println("REASON: " + firebaseData.errorReason());
Serial.println();
return false;
}
Serial.println("Connecting firebase successfully ... ");
return true;
}
void turnOffSystem() {
lcd.noBacklight();
lcd.noDisplay();
lcd.clear();
isLogin = isInput = false;
password = "";
}
void printStatusDoor(String msg, int row = 0, int col = 0, bool isClear = true) {
lcd.backlight();
lcd.noDisplay();
if (isClear) lcd.clear();
lcd.setCursor(col, row);
lcd.print(msg);
lcd.display();
}
bool updateStatusInServer(bool status) {
String node_status = "/" + uidMachine + "/State";
if (Firebase.setBool(firebaseData, node_status, status)){
Serial.print("Update status successfully... New status: ");
Serial.println(status ? "Opened" : "Closed");
}
else{
Serial.print("Update status failed ... Error: ");
Serial.println(firebaseData.errorReason().c_str());
return false;
}
return true;
}
bool validatePassword(String password) {
if (password == "123")
return true;
else return false;
}
void getInformationScreen() {
char key = keypad.getKey();
if (!key || key == NO_KEY) return;
start_time = millis();
switch (key) {
case 'L':
if (isDoorOpen && !updateStatusInServer(false)) {
printStatusDoor("Cannot Locked");
return;
}
printStatusDoor("Locked Door");
isDoorOpen = false;
break;
case 'C':
printStatusDoor("Current Status:");
if (isDoorOpen) printStatusDoor("Opened", 1, 0, false);
else printStatusDoor("Closed", 1, 0, false);
break;
case 'A':
turnOffSystem();
break;
case 'E':
if (isDoorOpen) printStatusDoor("The door opened");
else{
isLogin = true; isInput = false;
printStatusDoor("Activating ...");
delay(1000);
return;
}
break;
}
}
void inputScreen() {
if (!isInput) {
printStatusDoor("Input password: ");
lcd.setCursor(0, 1);
isInput = true;
}
char key = keypad.getKey();
if (!key || key == NO_KEY) return;
start_time = millis();
switch (key) {
case 'L':
isLogin = isInput = false;
password = "";
printStatusDoor("Canceling ...");
delay(1000);
printStatusDoor("Current Status:");
if (isDoorOpen) printStatusDoor("Opened", 1, 0, false);
else printStatusDoor("Closed", 1, 0, false);
return;
case 'C':
password.remove(password.length() - 1);
lcd.setCursor(password.length(), 1);
lcd.print(" ");
lcd.setCursor(password.length(), 1);
break;
case 'A':
lcd.setCursor(0, 1);
for (int i = 0; i < password.length(); i++) lcd.print(" ");
lcd.setCursor(0, 1);
password = "";
break;
case 'E':
printStatusDoor("Checking ...");
if (!validatePassword(password)) {
printStatusDoor("Incorrect ...");
delay(1000);
password = "";
isInput = false;
return;
}
if (updateStatusInServer(true)){
printStatusDoor("The door opened");
isDoorOpen = true;
isLogin = false;
}
else{
printStatusDoor("Cannot Opened");
isLogin = isInput = false;
}
break;
default:
if (isDigit(key) || key == '*' || key == '#')
if (password.length() + 1 <= 16) {
password += key;
lcd.print(key);
}
else tone(buzzer_pin, 1000, 10);
}
}
unsigned long calculateTurnOffScreen(){
int TIMES_WAIT_ON_SCREEN = 180000;
if (isLogin)
return 5*60*1000;
return 2*60*1000;
}
void setup() {
Serial.begin(9600);
Serial.println("Hello, ESP32");
pinMode(led_pin, OUTPUT);
pinMode(buzzer_pin, OUTPUT);
pinMode(button_pin, INPUT);
lcd.init();
checkConnectToDB();
Serial.print("setup() running on core ");
Serial.println(xPortGetCoreID());
}
TaskHandle_t Task1;
void loop() {
if (isLogin) inputScreen();
else getInformationScreen();
// if (lastUpdate == 0 || millis())
// String node_status = "/" + uidMachine + "/State";
// Serial.println("Lay ne :v");
// int time = millis();
// if (Firebase.getBool(firebaseData, node_status)) {
// Serial.print("Duoc ne :v");
// Serial.println(millis() - time);
// bool statusServer = firebaseData.boolData();
// isDoorOpen = firebaseData.boolData();
// if (isDoorOpen){
// password = "";
// isLogin = false;
// }
// } else{
// Serial.print("Cannot get the status ... Error ");
// Serial.println(firebaseData.errorReason().c_str());
// }
digitalWrite(led_pin, HIGH * isDoorOpen);
int buttonState = digitalRead(button_pin);
if (prev_click == 0 && prev_click != buttonState) {
if (updateStatusInServer(!isDoorOpen)){
isDoorOpen = !isDoorOpen;
if (isDoorOpen) printStatusDoor("The door opened");
else printStatusDoor("The door locked");
isLogin = false;
password = "";
}
}
prev_click = buttonState;
if (millis() - start_time >= calculateTurnOffScreen())
turnOffSystem();
}