alle Locker öffnen gleichzeitig, Hardcodes implementiert
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
const int RELAY_PINS[6] = {13, 12, 14, 27, 26, 25}; // Relay pins for doors 1-6
|
const int RELAY_PINS[6] = {13, 12, 14, 27, 26, 25}; // Relay pins for doors 1-6
|
||||||
const int DOOR_OPEN_TIME = 5000; // 5 seconds in milliseconds
|
const int DOOR_OPEN_TIME = 10000;
|
||||||
|
|
||||||
// I2C devices
|
// I2C devices
|
||||||
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD with I2C address 0x27
|
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD with I2C address 0x27
|
||||||
@@ -22,6 +22,15 @@ unsigned long lockoutEndTime = 0;
|
|||||||
const int MAX_FAILED_ATTEMPTS = 3;
|
const int MAX_FAILED_ATTEMPTS = 3;
|
||||||
const unsigned long LOCKOUT_DURATION = 30000; // 30 seconds in milliseconds
|
const unsigned long LOCKOUT_DURATION = 30000; // 30 seconds in milliseconds
|
||||||
|
|
||||||
|
// Door control state
|
||||||
|
struct DoorState {
|
||||||
|
bool isOpen;
|
||||||
|
unsigned long openedAt;
|
||||||
|
int doorNumber;
|
||||||
|
};
|
||||||
|
DoorState doorStates[6] = {{false, 0, 0}};
|
||||||
|
bool doorsActive = false;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
@@ -82,11 +91,14 @@ void loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle door timers (non-blocking)
|
||||||
|
handleDoorTimers();
|
||||||
|
|
||||||
// Check if keypad button was pressed
|
// Check if keypad button was pressed
|
||||||
keypad.updateFIFO();
|
keypad.updateFIFO();
|
||||||
char button = keypad.getButton();
|
char button = keypad.getButton();
|
||||||
|
|
||||||
if (button != 0 && !processingLoan) {
|
if (button != 0 && !processingLoan && !doorsActive) {
|
||||||
handleKeypadInput(button);
|
handleKeypadInput(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,8 +113,11 @@ void handleKeypadInput(char button) {
|
|||||||
// Submit code
|
// Submit code
|
||||||
if (currentCode.length() == 6) {
|
if (currentCode.length() == 6) {
|
||||||
processLoanCode(currentCode);
|
processLoanCode(currentCode);
|
||||||
|
} else if (currentCode.length() == 8) {
|
||||||
|
// Check for hardcode
|
||||||
|
checkHardcode(currentCode);
|
||||||
} else {
|
} else {
|
||||||
showError("Code muss 6-stellig sein!");
|
showError("Code: 6 oder 8 Ziffern!");
|
||||||
currentCode = "";
|
currentCode = "";
|
||||||
updateCodeDisplay();
|
updateCodeDisplay();
|
||||||
}
|
}
|
||||||
@@ -114,7 +129,7 @@ void handleKeypadInput(char button) {
|
|||||||
lcd.print("Code eingeben: ");
|
lcd.print("Code eingeben: ");
|
||||||
} else {
|
} else {
|
||||||
// Add digit to code
|
// Add digit to code
|
||||||
if (currentCode.length() < 6) {
|
if (currentCode.length() < 8) {
|
||||||
currentCode += button;
|
currentCode += button;
|
||||||
updateCodeDisplay();
|
updateCodeDisplay();
|
||||||
}
|
}
|
||||||
@@ -125,7 +140,7 @@ void updateCodeDisplay() {
|
|||||||
lcd.setCursor(0, 1);
|
lcd.setCursor(0, 1);
|
||||||
// Display asterisks for entered digits
|
// Display asterisks for entered digits
|
||||||
String display = "";
|
String display = "";
|
||||||
for (int i = 0; i < currentCode.length(); i++) {
|
for (unsigned int i = 0; i < currentCode.length(); i++) {
|
||||||
display += "*";
|
display += "*";
|
||||||
}
|
}
|
||||||
// Pad with spaces
|
// Pad with spaces
|
||||||
@@ -198,15 +213,16 @@ void processLoanCode(String code) {
|
|||||||
lcd.print("Ausleihe");
|
lcd.print("Ausleihe");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open doors one by one
|
// Collect all door numbers to open
|
||||||
JsonArray lockerArray = doc.as<JsonArray>();
|
JsonArray lockerArray = doc.as<JsonArray>();
|
||||||
|
int doorNumbers[6];
|
||||||
int doorCount = 0;
|
int doorCount = 0;
|
||||||
|
|
||||||
for (JsonVariant locker : lockerArray) {
|
for (JsonVariant locker : lockerArray) {
|
||||||
int doorNumber = locker.as<int>();
|
int doorNumber = locker.as<int>();
|
||||||
if (doorNumber >= 1 && doorNumber <= 6) {
|
if (doorNumber >= 1 && doorNumber <= 6 && doorCount < 6) {
|
||||||
|
doorNumbers[doorCount] = doorNumber;
|
||||||
doorCount++;
|
doorCount++;
|
||||||
openDoor(doorNumber);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,19 +232,96 @@ void processLoanCode(String code) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open all doors simultaneously (non-blocking)
|
||||||
|
openDoorsSimultaneous(doorNumbers, doorCount);
|
||||||
|
|
||||||
// Update loan status in backend
|
// Update loan status in backend
|
||||||
if (isReturn) {
|
if (isReturn) {
|
||||||
setReturnDate(code);
|
setReturnDate(code);
|
||||||
lcd.clear();
|
|
||||||
lcd.setCursor(0, 0);
|
|
||||||
lcd.print("Rueckgabe OK!");
|
|
||||||
} else {
|
} else {
|
||||||
setTakeDate(code);
|
setTakeDate(code);
|
||||||
lcd.clear();
|
|
||||||
lcd.setCursor(0, 0);
|
|
||||||
lcd.print("Ausleihe OK!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for all doors to close, then show completion message
|
||||||
|
// This will be handled by handleDoorTimers() and finishLoanProcess()
|
||||||
|
processingLoan = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void openDoorsSimultaneous(int doorNumbers[], int count) {
|
||||||
|
doorsActive = true;
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
// Display which doors are opening
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
lcd.print("Fach: ");
|
||||||
|
|
||||||
|
// Show door numbers
|
||||||
|
for (int i = 0; i < count && i < 4; i++) { // Max 4 doors shown due to LCD width
|
||||||
|
lcd.print(doorNumbers[i]);
|
||||||
|
if (i < count - 1) lcd.print(",");
|
||||||
|
}
|
||||||
|
if (count > 4) {
|
||||||
|
lcd.print("...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad with spaces
|
||||||
|
String padding = "";
|
||||||
|
for (int i = 0; i < (10 - count * 2); i++) {
|
||||||
|
padding += " ";
|
||||||
|
}
|
||||||
|
lcd.print(padding);
|
||||||
|
|
||||||
|
// Open all doors at the same time
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
int doorNumber = doorNumbers[i];
|
||||||
|
if (doorNumber >= 1 && doorNumber <= 6) {
|
||||||
|
int pinIndex = doorNumber - 1;
|
||||||
|
|
||||||
|
// Activate relay (LOW = on for most relay modules)
|
||||||
|
digitalWrite(RELAY_PINS[pinIndex], LOW);
|
||||||
|
|
||||||
|
// Track door state
|
||||||
|
doorStates[pinIndex].isOpen = true;
|
||||||
|
doorStates[pinIndex].openedAt = now;
|
||||||
|
doorStates[pinIndex].doorNumber = doorNumber;
|
||||||
|
|
||||||
|
Serial.println("Opened door " + String(doorNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleDoorTimers() {
|
||||||
|
if (!doorsActive) return;
|
||||||
|
|
||||||
|
unsigned long now = millis();
|
||||||
|
bool anyDoorOpen = false;
|
||||||
|
|
||||||
|
// Check each door
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if (doorStates[i].isOpen) {
|
||||||
|
// Check if door should be closed
|
||||||
|
if (now - doorStates[i].openedAt >= DOOR_OPEN_TIME) {
|
||||||
|
// Close door
|
||||||
|
digitalWrite(RELAY_PINS[i], HIGH);
|
||||||
|
doorStates[i].isOpen = false;
|
||||||
|
Serial.println("Closed door " + String(doorStates[i].doorNumber));
|
||||||
|
} else {
|
||||||
|
anyDoorOpen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no doors are open anymore, finish the process
|
||||||
|
if (!anyDoorOpen) {
|
||||||
|
doorsActive = false;
|
||||||
|
finishLoanProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void finishLoanProcess() {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print("Vorgang OK!");
|
||||||
lcd.setCursor(0, 1);
|
lcd.setCursor(0, 1);
|
||||||
lcd.print("Vielen Dank!");
|
lcd.print("Vielen Dank!");
|
||||||
|
|
||||||
@@ -246,6 +339,7 @@ bool getLoanInfo(String loanCode, String &lockers, bool &isReturn) {
|
|||||||
String url = String(BACKEND_URL) + "/get-loan-by-code/" + API_KEY + "/" + loanCode;
|
String url = String(BACKEND_URL) + "/get-loan-by-code/" + API_KEY + "/" + loanCode;
|
||||||
|
|
||||||
http.begin(url);
|
http.begin(url);
|
||||||
|
http.setTimeout(10000); // 10 second timeout
|
||||||
int httpCode = http.GET();
|
int httpCode = http.GET();
|
||||||
|
|
||||||
if (httpCode != 200) {
|
if (httpCode != 200) {
|
||||||
@@ -298,32 +392,6 @@ bool getLoanInfo(String loanCode, String &lockers, bool &isReturn) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void openDoor(int doorNumber) {
|
|
||||||
if (doorNumber < 1 || doorNumber > 6) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pinIndex = doorNumber - 1;
|
|
||||||
|
|
||||||
lcd.setCursor(0, 1);
|
|
||||||
lcd.print("Oeffne Fach ");
|
|
||||||
lcd.print(doorNumber);
|
|
||||||
lcd.print(" ");
|
|
||||||
|
|
||||||
Serial.println("Opening door " + String(doorNumber));
|
|
||||||
|
|
||||||
// Activate relay (LOW = on for most relay modules)
|
|
||||||
digitalWrite(RELAY_PINS[pinIndex], LOW);
|
|
||||||
|
|
||||||
// Keep door open for specified time
|
|
||||||
delay(DOOR_OPEN_TIME);
|
|
||||||
|
|
||||||
// Deactivate relay (close door)
|
|
||||||
digitalWrite(RELAY_PINS[pinIndex], HIGH);
|
|
||||||
|
|
||||||
Serial.println("Door " + String(doorNumber) + " closed");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool setReturnDate(String loanCode) {
|
bool setReturnDate(String loanCode) {
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
return false;
|
return false;
|
||||||
@@ -333,6 +401,7 @@ bool setReturnDate(String loanCode) {
|
|||||||
String url = String(BACKEND_URL) + "/set-return-date/" + API_KEY + "/" + loanCode;
|
String url = String(BACKEND_URL) + "/set-return-date/" + API_KEY + "/" + loanCode;
|
||||||
|
|
||||||
http.begin(url);
|
http.begin(url);
|
||||||
|
http.setTimeout(10000); // 10 second timeout
|
||||||
int httpCode = http.POST("");
|
int httpCode = http.POST("");
|
||||||
|
|
||||||
bool success = (httpCode == 200);
|
bool success = (httpCode == 200);
|
||||||
@@ -351,6 +420,7 @@ bool setTakeDate(String loanCode) {
|
|||||||
String url = String(BACKEND_URL) + "/set-take-date/" + API_KEY + "/" + loanCode;
|
String url = String(BACKEND_URL) + "/set-take-date/" + API_KEY + "/" + loanCode;
|
||||||
|
|
||||||
http.begin(url);
|
http.begin(url);
|
||||||
|
http.setTimeout(10000); // 10 second timeout
|
||||||
int httpCode = http.POST("");
|
int httpCode = http.POST("");
|
||||||
|
|
||||||
bool success = (httpCode == 200);
|
bool success = (httpCode == 200);
|
||||||
@@ -373,6 +443,7 @@ void showError(String message) {
|
|||||||
void resetState() {
|
void resetState() {
|
||||||
currentCode = "";
|
currentCode = "";
|
||||||
processingLoan = false;
|
processingLoan = false;
|
||||||
|
doorsActive = false;
|
||||||
lcd.clear();
|
lcd.clear();
|
||||||
lcd.setCursor(0, 0);
|
lcd.setCursor(0, 0);
|
||||||
lcd.print("Code eingeben:");
|
lcd.print("Code eingeben:");
|
||||||
@@ -414,3 +485,58 @@ void connectToWiFi() {
|
|||||||
delay(2000);
|
delay(2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkHardcode(String code) {
|
||||||
|
Serial.println("Checking hardcode: " + code);
|
||||||
|
|
||||||
|
// Check each door's hardcode
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if (code == String(DOOR_HARDCODES[i])) {
|
||||||
|
// Hardcode matched for door i+1
|
||||||
|
Serial.println("Hardcode match for door " + String(i + 1));
|
||||||
|
|
||||||
|
// Reset failed attempts on successful hardcode
|
||||||
|
failedAttempts = 0;
|
||||||
|
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print("Notcode erkannt");
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
lcd.print("Fach: ");
|
||||||
|
lcd.print(i + 1);
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// Open only this door
|
||||||
|
int doorNumber = i + 1;
|
||||||
|
openDoorsSimultaneous(&doorNumber, 1);
|
||||||
|
|
||||||
|
// Don't update backend (emergency access)
|
||||||
|
processingLoan = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No hardcode matched
|
||||||
|
failedAttempts++;
|
||||||
|
|
||||||
|
if (failedAttempts >= MAX_FAILED_ATTEMPTS) {
|
||||||
|
lockoutEndTime = millis() + LOCKOUT_DURATION;
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print("Zu viele Fehler!");
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
lcd.print("Gesperrt 30s");
|
||||||
|
delay(2000);
|
||||||
|
} else {
|
||||||
|
showError("Ungueltiger Code!");
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
lcd.print("Versuch ");
|
||||||
|
lcd.print(failedAttempts);
|
||||||
|
lcd.print("/");
|
||||||
|
lcd.print(MAX_FAILED_ATTEMPTS);
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetState();
|
||||||
|
}
|
||||||
@@ -12,4 +12,15 @@ const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
|
|||||||
const char* BACKEND_URL = "https://insta.the1s.de/backend/api";
|
const char* BACKEND_URL = "https://insta.the1s.de/backend/api";
|
||||||
const char* API_KEY = "12345678"; // Replace with your 8-digit API key
|
const char* API_KEY = "12345678"; // Replace with your 8-digit API key
|
||||||
|
|
||||||
|
// Emergency hardcodes for each door (8-digit codes)
|
||||||
|
// These codes will always open the specific door, bypassing the backend
|
||||||
|
const char* DOOR_HARDCODES[6] = {
|
||||||
|
"11111111", // Door 1 hardcode
|
||||||
|
"22222222", // Door 2 hardcode
|
||||||
|
"33333333", // Door 3 hardcode
|
||||||
|
"44444444", // Door 4 hardcode
|
||||||
|
"55555555", // Door 5 hardcode
|
||||||
|
"66666666" // Door 6 hardcode
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CONFIG_H
|
#endif // CONFIG_H
|
||||||
Reference in New Issue
Block a user