#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>

// Initialize the LCD with I2C address 0x27
LiquidCrystal_I2C lcd(0x27, 16, 2);  
Servo myservo;

// Keypad setup
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'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; 
byte colPins[COLS] = {5, 4, 3, 2}; 
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

String correctOTP = "";
String enteredOTP = "";

const int ledPin = 11;  // LED connected to digital pin 10 through a resistor
const int buzzerPin = 12;  // Buzzer connected to digital pin 12

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);  // Initialize the LCD
  lcd.backlight();   // Turn on the backlight
  myservo.attach(10);  // Attach servo to pin 11
  pinMode(ledPin, OUTPUT);  // Initialize the LED pin as an output
  pinMode(buzzerPin, OUTPUT);  // Initialize the buzzer pin as an output
  generateOTP();  // Generate a new OTP at startup
  lcd.print("Welcome!");
  delay(1000);
  lcd.setCursor(0,0);
  lcd.print("Enter OTP:");
   
}

void loop() {
  char key = keypad.getKey();
  if (key) {
    Serial.print("Key pressed: ");
    Serial.println(key);

    if (enteredOTP.length() < 4) {
      enteredOTP += key;
      lcd.setCursor(0, 0);
      lcd.print(enteredOTP);

      if (enteredOTP.length() == 4) {
        if (enteredOTP == correctOTP) {
          grantAccess();
        } else {
          denyAccess();
        }
        enteredOTP = "";  // Reset entered OTP
        delay(2000);
        lcd.clear();
        
      }
    }
  }
}

void grantAccess() {
  lcd.clear();
  lcd.print("Access Granted");
  delay(5000);
  digitalWrite(buzzerPin, HIGH);  // Turn on Buzzer
  delay(1000);  // Keep buzzer on for 1 second
  digitalWrite(buzzerPin, LOW);  // Turn off Buzzer
  myservo.write(90);  // Unlock door (rotate servo to 90 degrees)
  delay(5000);  // Keep door unlocked for 5 seconds
  myservo.write(0);  // Lock door (rotate servo back to 0 degrees)
  digitalWrite(ledPin, LOW);  // Ensure LED is off
}

void denyAccess() {
  lcd.clear();
  lcd.print("Access Denied");
  digitalWrite(ledPin, HIGH);  // Turn on LED to indicate access denied
  for (int i = 0; i < 3; i++) {
    digitalWrite(buzzerPin, HIGH);  // Turn on Buzzer
    delay(500);  // Keep buzzer on for 0.5 second
    digitalWrite(buzzerPin, LOW);  // Turn off Buzzer
    delay(500);  // Wait for 0.5 second
    digitalWrite(ledPin, HIGH);
  }
  digitalWrite(ledPin, LOW);  // Turn off LED after indicating access denied
}

void generateOTP() {
  correctOTP = "";
  for (int i = 0; i < 4; i++) {
    correctOTP += String(random(0, 10));  // Generate a random digit between 0 and 9
  }
  Serial.print("New OTP: ");
  Serial.println(correctOTP);  // Print the new OTP to the serial monitor for testing
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
servo1:GND
servo1:V+
servo1:PWM
led1:A
led1:C
bz1:1
bz1:2
r1:1
r1:2