#include <WiFi.h>
#include <PubSubClient.h>
#include <Keypad.h>
#include <ESP32Servo.h>
// Pin definitions
#define PIR_PIN 14
#define TRIG_PIN 27
#define ECHO_PIN 26
#define LED_PIN 33
#define BUZZER_PIN 25
#define SERVO_PIN 13
// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// MQTT Broker
const char* mqtt_server = "broker.hivemq.com";
WiFiClient espClient;
PubSubClient client(espClient);
Servo locker;
const int ROW_NUM = 4;
const int COL_NUM = 4;
char keys[ROW_NUM][COL_NUM] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROW_NUM] = {19, 18, 5, 17};
byte colPins[COL_NUM] = {16, 4, 2, 15};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROW_NUM, COL_NUM);
String correctPassword = "1234";
String inputPassword = "";
unsigned long presenceStart = 0;
bool presenceDetected = false;
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) msg += (char)payload[i];
if (String(topic) == "locker/control" && msg == "UNLOCK") {
Serial.println(" Remote unlock requested via MQTT");
// Unlock logic inline
digitalWrite(LED_PIN, LOW);
tone(BUZZER_PIN, 1000, 200);
locker.write(90);
delay(5000);
locker.write(0);
digitalWrite(LED_PIN, HIGH);
}
if (String(topic) == "locker/password") {
Serial.print(" Password received via MQTT: ");
Serial.println(msg);
if (msg == correctPassword) {
Serial.println(" Password correct via Node-RED!");
// Unlock logic inline
digitalWrite(LED_PIN, LOW);
tone(BUZZER_PIN, 1000, 200);
locker.write(90);
delay(5000);
locker.write(0);
digitalWrite(LED_PIN, HIGH);
} else {
Serial.println(" Wrong password from Node-RED!");
alert();
}
}
}
void reconnect() {
while (!client.connected()) {
if (client.connect("ESP32Client")) {
Serial.println("connected");
client.subscribe("locker/control");
client.subscribe("locker/password");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 2 seconds");
delay(2000);
}
}
}
long getDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
long distance = duration * 0.034 / 2;
if (duration == 0) return 999;
return distance;
}
void alert() {
for (int i = 0; i < 3; i++) {
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 800);
delay(300);
digitalWrite(LED_PIN, LOW);
noTone(BUZZER_PIN);
delay(300);
}
digitalWrite(LED_PIN, HIGH);
}
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZZER_PIN, LOW);
locker.attach(SERVO_PIN, 500, 2400);
locker.write(0);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
Serial.println("System ready, waiting for presence...");
}
void loop() {
if (!client.connected()) {
Serial.print("Attempting MQTT connection...");
reconnect();
}
client.loop();
long dist = getDistance();
Serial.print("Distance: ");
Serial.print(dist);
Serial.println(" cm");
client.publish("locker/distance", String(dist).c_str());
if (dist < 100 && digitalRead(PIR_PIN) == HIGH) {
Serial.println("Presence detected! You have 3 minutes.");
presenceDetected = true;
presenceStart = millis();
inputPassword = "";
while (millis() - presenceStart < 180000) {
char key = keypad.getKey();
if (key) {
Serial.print("*");
inputPassword += key;
if (inputPassword.length() == correctPassword.length()) {
if (inputPassword == correctPassword) {
Serial.println("\nCorrect password!");
// Unlock logic inline
digitalWrite(LED_PIN, LOW);
tone(BUZZER_PIN, 1000, 200);
locker.write(90);
delay(5000);
locker.write(0);
digitalWrite(LED_PIN, HIGH);
break;
} else {
Serial.println("\nWrong password!");
alert();
break;
}
}
}
if (getDistance() > 120) {
Serial.println("User left.");
break;
}
}
if (inputPassword.length() == 0 && (millis() - presenceStart) >= 180000) {
Serial.println("Timeout! No input entered.");
alert();
}
}
delay(500);
}