diff --git a/src/FingerprintManager.cpp b/src/FingerprintManager.cpp index d07631b..1b71803 100644 --- a/src/FingerprintManager.cpp +++ b/src/FingerprintManager.cpp @@ -130,19 +130,24 @@ Match FingerprintManager::scanFingerprint() { // no finger on sensor but ring was touched -> ring event //Serial.println("ring touched"); updateTouchState(true); - if (imagingPass < 15) // up to 10 image passes in a row are taken after touch ring was touched until noFinger will raise a noMatchFound event + if (imagingPass < 15) // up to x image passes in a row are taken after touch ring was touched until noFinger will raise a noMatchFound event { doImaging = true; // scan another image //delay(50); break; } else { - //Serial.println("10 times no image after touching ring"); + //Serial.println("15 times no image after touching ring"); match.scanResult = ScanResult::noMatchFound; return match; } } else { - match.scanResult = ScanResult::noFinger; - updateTouchState(false); + if (ignoreTouchRing && scanPass > 1) { + // the scan(s) in last iteration(s) have not found any match, now the finger was released (=no finger) -> return "no match" as result + match.scanResult = ScanResult::noMatchFound; + } else { + match.scanResult = ScanResult::noFinger; + updateTouchState(false); + } return match; } case FINGERPRINT_IMAGEFAIL: @@ -370,7 +375,7 @@ void FingerprintManager::deleteFinger(int id) { if ((id > 0) && (id <= 200)) { int8_t result = finger.deleteModel(id); if (result != FINGERPRINT_OK) { - Serial.println(String("Delete of finger template #") + id + " from sensor failed"); + notifyClients(String("Delete of finger template #") + id + " from sensor failed with code " + result); return; } else { @@ -454,6 +459,34 @@ void FingerprintManager::setLedRingReady() { finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_BLUE); // just an indicator for me to see if touch ring is active or not } +bool FingerprintManager::deleteAll() { + if (finger.emptyDatabase() == FINGERPRINT_OK) + { + bool rc; + Preferences preferences; + rc = preferences.begin("fingerList", false); + if (rc) + rc = preferences.clear(); + preferences.end(); + return rc; + } + else + return false; + +} + + + +void FingerprintManager::writeNotepad(String text) { + +} + + +String FingerprintManager::readNotepad() { + String text; + return text; +} + // ToDo: support sensor replacement by enable transferring of sensor DB to another sensor diff --git a/src/FingerprintManager.h b/src/FingerprintManager.h index 5f69524..2c5376b 100644 --- a/src/FingerprintManager.h +++ b/src/FingerprintManager.h @@ -7,6 +7,10 @@ #define mySerial Serial2 +#define FINGERPRINT_WRITENOTEPAD 0x18 // Write Notepad on sensor +#define FINGERPRINT_READNOTEPAD 0x19 // Read Notepad from sensor + + /* By using the touch ring as an additional input to the image sensor the sensitivity is much higher for door bell ring events. Unfortunately we cannot differ between touches on the ring by fingers or rain drops, so rain on the ring will cause false alarms. @@ -37,11 +41,14 @@ class FingerprintManager { int fingerCountOnSensor = 0; bool ignoreTouchRing = false; // set to true when the sensor is usually exposed to rain to avoid false ring events. Can also be set conditional by a rain sensor over MQTT bool lastIgnoreTouchRing = false; - + void updateTouchState(bool touched); bool isRingTouched(); void loadFingerListFromPrefs(); void disconnect(); + void writeNotepad(String text); + String readNotepad(); + public: bool connected; @@ -57,6 +64,9 @@ class FingerprintManager { void setLedRingWifiConfig(); void setLedRingReady(); + bool deleteAll(); + + // functions for sensor replacement void exportSensorDB(); void importSensorDB(); diff --git a/src/SettingsManager.cpp b/src/SettingsManager.cpp index c71e9e9..c49322f 100644 --- a/src/SettingsManager.cpp +++ b/src/SettingsManager.cpp @@ -64,3 +64,24 @@ bool SettingsManager::isWifiConfigured() { else return true; } + +bool SettingsManager::deleteAppSettings() { + bool rc; + Preferences preferences; + rc = preferences.begin("appSettings", false); + if (rc) + rc = preferences.clear(); + preferences.end(); + return rc; +} + +bool SettingsManager::deleteWifiSettings() { + bool rc; + Preferences preferences; + rc = preferences.begin("wifiSettings", false); + if (rc) + rc = preferences.clear(); + preferences.end(); + return rc; +} + diff --git a/src/SettingsManager.h b/src/SettingsManager.h index dfe1444..cdf6815 100644 --- a/src/SettingsManager.h +++ b/src/SettingsManager.h @@ -38,6 +38,9 @@ class SettingsManager { bool isWifiConfigured(); + bool deleteAppSettings(); + bool deleteWifiSettings(); + }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0f2817f..4dd0470 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include "SettingsManager.h" #include "global.h" -enum class Mode { scan, enroll, wificonfig }; +enum class Mode { scan, enroll, wificonfig, maintenance }; const char* VersionInfo = "0.1"; @@ -40,6 +40,7 @@ Mode currentMode = Mode::scan; FingerprintManager fingerManager; SettingsManager settingsManager; +bool needMaintenanceMode = false; const byte DNS_PORT = 53; DNSServer dnsServer; @@ -85,6 +86,20 @@ String getTimestampString(){ return datetime; } +/* wait for maintenance mode or timeout 5s */ +bool waitForMaintenanceMode() { + needMaintenanceMode = true; + unsigned long startMillis = millis(); + while (currentMode != Mode::maintenance) { + if ((millis() - startMillis) >= 5000ul) { + needMaintenanceMode = false; + return false; + } + delay(50); + } + needMaintenanceMode = false; + return true; +} // Replaces placeholder in HTML pages String processor(const String& var){ @@ -214,7 +229,7 @@ void startWebserver(){ webServer.onNotFound([](AsyncWebServerRequest *request){ AsyncResponseStream *response = request->beginResponseStream("text/html"); - response->print("FingerprintDoorbell"); + response->printf("FingerprintDoorbell", WiFi.softAPIP().toString().c_str()); response->printf("

Please configure your WiFi settings here to connect FingerprintDoorbell to your home network.

", WiFi.softAPIP().toString().c_str()); response->print(""); request->send(response); @@ -258,7 +273,9 @@ void startWebserver(){ if(request->hasArg("btnDelete")) { int id = request->arg("selectedFingerprint").toInt(); + waitForMaintenanceMode(); fingerManager.deleteFinger(id); + currentMode = Mode::scan; } else if (request->hasArg("btnRename")) { @@ -292,9 +309,19 @@ void startWebserver(){ webServer.on("/factoryReset", HTTP_GET, [](AsyncWebServerRequest *request){ if(request->hasArg("btnFactoryReset")) { - notifyClients("Factory reset is not implemented yet!"); + notifyClients("Factory reset initiated..."); + + if (!fingerManager.deleteAll()) + notifyClients("Finger database could not be deleted."); + + if (!settingsManager.deleteAppSettings()) + notifyClients("App settings could not be deleted."); + + if (!settingsManager.deleteWifiSettings()) + notifyClients("Wifi settings could not be deleted."); + request->redirect("/"); - //shouldReboot = true; + shouldReboot = true; } else { request->send(SPIFFS, "/settings.html", String(), false, processor); } @@ -451,6 +478,19 @@ void doEnroll() } } +void reboot() +{ + notifyClients("System is rebooting now..."); + delay(1000); + + mqttClient.disconnect(); + espClient.stop(); + dnsServer.stop(); + webServer.end(); + WiFi.disconnect(); + ESP.restart(); +} + void setup() { @@ -518,15 +558,7 @@ void loop() { // shouldReboot flag for supporting reboot through webui if (shouldReboot) { - notifyClients("System is rebooting now..."); - delay(1000); - - mqttClient.disconnect(); - espClient.stop(); - dnsServer.stop(); - webServer.end(); - WiFi.disconnect(); - ESP.restart(); + reboot(); } @@ -569,8 +601,16 @@ void loop() case Mode::wificonfig: dnsServer.processNextRequest(); // used for captive portal redirect break; + + case Mode::maintenance: + // do nothing, give webserver exclusive access to sensor (not thread-safe for concurrent calls) + break; + } - + + // enter maintenance mode (no continous scanning) if requested + if (needMaintenanceMode) + currentMode = Mode::maintenance; }