Přidání blokace zámku po X špatných pokusů

This commit is contained in:
Matěj Kubíček
2026-06-08 10:23:06 +02:00
parent da759fa0b6
commit 4f704b3b29
+100 -9
View File
@@ -33,6 +33,13 @@ bool isOpen = false;
// enkodér // enkodér
int lastCLK = HIGH; int lastCLK = HIGH;
// blokace po špatných pokusech
constexpr byte MAX_WRONG_ATTEMPTS = 3;
constexpr unsigned long LOCKOUT_DURATION_MS = 30000UL;
byte wrongAttempts = 0;
bool lockedOut = false;
unsigned long lockoutStart = 0;
// maska po kolika ms nečinnosti se heslo maskuje // maska po kolika ms nečinnosti se heslo maskuje
constexpr unsigned long MASK_DELAY_MS = 2000; constexpr unsigned long MASK_DELAY_MS = 2000;
unsigned long lastEncoderMove = 0; unsigned long lastEncoderMove = 0;
@@ -95,6 +102,15 @@ void NeutralLED() {
analogWrite(RGB_RED_PIN, 0); analogWrite(RGB_RED_PIN, 0);
} }
// blikání červené během blokace
void BlockedLED() {
// bliká každých 500 ms
const bool blink = millis() / 500 % 2 == 0;
analogWrite(RGB_RED_PIN, blink ? 120 : 0);
analogWrite(RGB_GREEN_PIN, 0);
analogWrite(RGB_BLUE_PIN, 0);
}
void ButtonPressed() { void ButtonPressed() {
if (savedPassword != "") if (savedPassword != "")
{ {
@@ -242,6 +258,58 @@ void setup() {
} }
void loop() { void loop() {
// Serial Monitor příkaz "unblock" zruší blokaci
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd == "unblock") {
if (lockedOut) {
lockedOut = false;
wrongAttempts = 0;
Serial.println("[SERIAL] Blokace zrusena. Zamek je stale zamcen.");
CloseLED();
password = 0;
masked = false;
lastEncoderMove = millis();
showEntryScreen(true);
} else {
Serial.println("[SERIAL] Zamek neni zablokovan.");
}
} else {
Serial.println("[SERIAL] Nezname prikazani. Pouzij: unblock");
}
}
// blokace čeká odpočítávání, neblokuje loop
if (lockedOut) {
if (const unsigned long elapsed = millis() - lockoutStart; elapsed >= LOCKOUT_DURATION_MS) {
// konec blokace
lockedOut = false;
wrongAttempts = 0;
Serial.println("Blokace skoncila.");
CloseLED();
password = 0;
masked = false;
lastEncoderMove = millis();
showEntryScreen(true);
} else {
// odpočítávání na LCD aktualizuje jen každou sekundu
static unsigned long lastCountdownUpdate = 0;
if (millis() - lastCountdownUpdate >= 1000) {
lastCountdownUpdate = millis();
const int remaining = static_cast<int>((LOCKOUT_DURATION_MS - elapsed + 999) / 1000);
lcd.setCursor(0, 0);
lcd.printstr("Zablokovano! ");
lcd.setCursor(0, 1);
String line = "Zbyva: " + String(remaining) + "s ";
line = line.substring(0, 16);
lcd.printstr(line.c_str());
}
BlockedLED();
}
return; // zbytek loop se přeskočí
}
// čtení enkodéru jen pokud je zamčeno // čtení enkodéru jen pokud je zamčeno
// (při odemčeném stavu enkodér nemá smysl) // (při odemčeném stavu enkodér nemá smysl)
if (!isOpen) { if (!isOpen) {
@@ -275,6 +343,7 @@ void loop() {
// pokus o odemčení // pokus o odemčení
if (formatCode(password) == savedPassword) { if (formatCode(password) == savedPassword) {
isOpen = true; isOpen = true;
wrongAttempts = 0; // reset po úspěšném odemčení
OpenLock(); OpenLock();
OpenLED(); OpenLED();
OpenSound(); OpenSound();
@@ -284,18 +353,40 @@ void loop() {
lcd.setCursor(0, 1); lcd.setCursor(0, 1);
lcd.printstr("Stiskni pro zamk"); lcd.printstr("Stiskni pro zamk");
} else { } else {
// špatné heslo
wrongAttempts++;
Serial.print("Spatny pokus: ");
Serial.print(wrongAttempts);
Serial.print("/");
Serial.println(MAX_WRONG_ATTEMPTS);
CloseSound(); CloseSound();
lcd.setCursor(0, 0); if (wrongAttempts >= MAX_WRONG_ATTEMPTS) {
lcd.printstr("Spatne heslo! "); // spustit blokaci
lcd.setCursor(0, 1); lockedOut = true;
lcd.printstr(" "); lockoutStart = millis();
delay(1500); Serial.println("Zamek zablokovan na 30 sekund. Pouzij 'unblock' pro zruseni.");
// návrat na zadávací obrazovku, hodnota zachována lcd.setCursor(0, 0);
masked = false; lcd.printstr("Zablokovano! ");
lastEncoderMove = millis(); lcd.setCursor(0, 1);
showEntryScreen(true); lcd.printstr("Zbyva: 30s ");
BlockedLED();
} else {
lcd.setCursor(0, 0);
String warn = "Spatne! (" + String(wrongAttempts) + "/" + String(MAX_WRONG_ATTEMPTS) + ") ";
warn = warn.substring(0, 16);
lcd.printstr(warn.c_str());
lcd.setCursor(0, 1);
lcd.printstr(" ");
delay(1500);
// návrat na zadávací obrazovku, hodnota zachována
masked = false;
lastEncoderMove = millis();
showEntryScreen(true);
}
} }
} else { } else {
// zamčení // zamčení