diff --git a/FingerprintDoorbell/src/SettingsManager.cpp b/FingerprintDoorbell/src/SettingsManager.cpp index 7f9177f..f4bea0c 100644 --- a/FingerprintDoorbell/src/SettingsManager.cpp +++ b/FingerprintDoorbell/src/SettingsManager.cpp @@ -25,6 +25,7 @@ bool SettingsManager::loadAppSettings() { appSettings.sensorPin = preferences.getString("sensorPin", "00000000"); appSettings.sensorPairingCode = preferences.getString("pairingCode", ""); appSettings.sensorPairingValid = preferences.getBool("pairingValid", false); + appSettings.chosenPin = preferences.getString("chosenPin", "123456"); preferences.end(); return true; } else { @@ -52,6 +53,7 @@ void SettingsManager::saveAppSettings() { preferences.putString("sensorPin", appSettings.sensorPin); preferences.putString("pairingCode", appSettings.sensorPairingCode); preferences.putBool("pairingValid", appSettings.sensorPairingValid); + preferences.putString("chosenPin", appSettings.chosenPin); preferences.end(); } diff --git a/FingerprintDoorbell/src/SettingsManager.h b/FingerprintDoorbell/src/SettingsManager.h index 17952f1..dd69c2e 100644 --- a/FingerprintDoorbell/src/SettingsManager.h +++ b/FingerprintDoorbell/src/SettingsManager.h @@ -18,6 +18,7 @@ struct AppSettings { String ntpServer = "pool.ntp.org"; String sensorPin = "00000000"; String sensorPairingCode = ""; + String chosenPin = "123456"; bool sensorPairingValid = false; }; diff --git a/FingerprintDoorbell/src/main.cpp b/FingerprintDoorbell/src/main.cpp index 3d0becb..bb533ac 100644 --- a/FingerprintDoorbell/src/main.cpp +++ b/FingerprintDoorbell/src/main.cpp @@ -1,7 +1,7 @@ /*************************************************** Main of FingerprintDoorbell ****************************************************/ - +#define MQTT_SOCKET_TIMEOUT 2 #include #include #include @@ -12,8 +12,9 @@ #include "FingerprintManager.h" #include "SettingsManager.h" #include "global.h" +#include "Ticker.h" -enum class Mode { scan, enroll, wificonfig, maintenance }; +enum class Mode { scan, enroll, wificonfig, maintenance, cooldown }; const char* VersionInfo = "0.4"; @@ -27,7 +28,10 @@ IPAddress WifiConfigIp(192, 168, 4, 1); // IP of access point in wifi config m const long gmtOffset_sec = 0; // UTC Time const int daylightOffset_sec = 0; // UTC Time const int doorbellOutputPin = 5; // pin connected to the doorbell (when using hardware connection instead of mqtt to ring the bell) -const int doorOpenerOutputPin = 6; // pin connected to the door opener (when using hardware connection instead of mqtt to open the door) +const int doorOpenerOutputPin = 8; //USE 6 HERE pin connected to the door opener (when using hardware connection instead of mqtt to open the door) +const int KeyboardPin = 4; //pin connected to an analog keyboard (see voltage ranges for the nubers in seperate array) +const int KEY_POLLING_MS = 25; +const uint8_t NUM_PIN_DIGITS = {6}; #ifdef CUSTOM_GPIOS const int customOutput1 = 18; // not used internally, but can be set over MQTT const int customOutput2 = 26; // not used internally, but can be set over MQTT @@ -51,6 +55,11 @@ FingerprintManager fingerManager; SettingsManager settingsManager; bool needMaintenanceMode = false; +Ticker keyboardTick; +Ticker openDoorTick; +Ticker ringBellTick; +Ticker cooldownTick; + const byte DNS_PORT = 53; DNSServer dnsServer; AsyncWebServer webServer(80); // AsyncWebServer on port 80 @@ -66,6 +75,9 @@ bool mqttConfigValid = true; Match lastMatch; +void timeDoorOpener(uint8_t _state = HIGH); +void timeBellRing(uint8_t _state= HIGH); + void addLogMessage(const String& message) { // shift all messages in array by 1, oldest message will die for (int i=logMessagesCount-1; i>0; i--) @@ -555,6 +567,45 @@ void connectMqttClient() { } } +void timeDoorOpener(uint8_t _state){ + digitalWrite(doorOpenerOutputPin, _state); + openDoorTick.once(1,timeDoorOpener,(uint8_t) LOW); //switch back off after one second +} + +void timeBellRing(uint8_t _state){ + digitalWrite(doorbellOutputPin, _state); + ringBellTick.once(1,timeBellRing,(uint8_t) LOW); //switch back off after one second +} + +void openDoor(Match _match){ + String mqttRootTopic = settingsManager.getAppSettings().mqttRootTopic; + timeDoorOpener(); + mqttClient.publish((String(mqttRootTopic) + "/ring").c_str(), "off"); + mqttClient.publish((String(mqttRootTopic) + "/matchId").c_str(), String(_match.matchId).c_str()); + mqttClient.publish((String(mqttRootTopic) + "/matchName").c_str(), _match.matchName.c_str()); + mqttClient.publish((String(mqttRootTopic) + "/matchConfidence").c_str(), String(_match.matchConfidence).c_str()); + Serial.println("MQTT message sent: Open the door!"); +} + +void ringBell(void){ + String mqttRootTopic = settingsManager.getAppSettings().mqttRootTopic; + timeBellRing(); + mqttClient.publish((String(mqttRootTopic) + "/ring").c_str(), "on"); + mqttClient.publish((String(mqttRootTopic) + "/matchId").c_str(), "-1"); + mqttClient.publish((String(mqttRootTopic) + "/matchName").c_str(), ""); + mqttClient.publish((String(mqttRootTopic) + "/matchConfidence").c_str(), "-1"); + Serial.println("MQTT message sent: ring the bell!"); +} + +void continueScanMode(void){ + currentMode = Mode::scan; +} + +void setCooldown(uint16_t time){ + currentMode = Mode::cooldown; + cooldownTick.once_ms(time,continueScanMode); +} + void doScan() { @@ -566,43 +617,31 @@ void doScan() // standard case, occurs every iteration when no finger touchs the sensor if (match.scanResult != lastMatch.scanResult) { Serial.println("no finger"); - mqttClient.publish((String(mqttRootTopic) + "/ring").c_str(), "off"); - mqttClient.publish((String(mqttRootTopic) + "/matchId").c_str(), "-1"); - mqttClient.publish((String(mqttRootTopic) + "/matchName").c_str(), ""); - mqttClient.publish((String(mqttRootTopic) + "/matchConfidence").c_str(), "-1"); + if(mqttClient.connected()){ + mqttClient.publish((String(mqttRootTopic) + "/ring").c_str(), "off"); + mqttClient.publish((String(mqttRootTopic) + "/matchId").c_str(), "-1"); + mqttClient.publish((String(mqttRootTopic) + "/matchName").c_str(), ""); + mqttClient.publish((String(mqttRootTopic) + "/matchConfidence").c_str(), "-1"); + } } break; case ScanResult::matchFound: notifyClients( String("Match Found: ") + match.matchId + " - " + match.matchName + " with confidence of " + match.matchConfidence ); if (match.scanResult != lastMatch.scanResult) { if (checkPairingValid()) { - digitalWrite(doorOpenerOutputPin, HIGH); - mqttClient.publish((String(mqttRootTopic) + "/ring").c_str(), "off"); - mqttClient.publish((String(mqttRootTopic) + "/matchId").c_str(), String(match.matchId).c_str()); - mqttClient.publish((String(mqttRootTopic) + "/matchName").c_str(), match.matchName.c_str()); - mqttClient.publish((String(mqttRootTopic) + "/matchConfidence").c_str(), String(match.matchConfidence).c_str()); - Serial.println("MQTT message sent: Open the door!"); - delay(1000); - digitalWrite(doorOpenerOutputPin, LOW); + openDoor(match); } else { notifyClients("Security issue! Match was not sent by MQTT because of invalid sensor pairing! This could potentially be an attack! If the sensor is new or has been replaced by you do a (re)pairing in settings page."); } } - delay(3000); // wait some time before next scan to let the LED blink + setCooldown(4000); break; case ScanResult::noMatchFound: notifyClients(String("No Match Found (Code ") + match.returnCode + ")"); if (match.scanResult != lastMatch.scanResult) { - digitalWrite(doorbellOutputPin, HIGH); - mqttClient.publish((String(mqttRootTopic) + "/ring").c_str(), "on"); - mqttClient.publish((String(mqttRootTopic) + "/matchId").c_str(), "-1"); - mqttClient.publish((String(mqttRootTopic) + "/matchName").c_str(), ""); - mqttClient.publish((String(mqttRootTopic) + "/matchConfidence").c_str(), "-1"); - Serial.println("MQTT message sent: ring the bell!"); - delay(1000); - digitalWrite(doorbellOutputPin, LOW); + ringBell(); } else { - delay(1000); // wait some time before next scan to let the LED blink + setCooldown(4000); // wait some time before next scan to let the LED blink } break; case ScanResult::error: @@ -634,6 +673,7 @@ void doEnroll() void reboot() { + digitalWrite(doorOpenerOutputPin, LOW); notifyClients("System is rebooting now..."); delay(1000); @@ -645,10 +685,83 @@ void reboot() ESP.restart(); } +void keyboardPoller(void){ + uint8_t key = 99; + static uint8_t lastKey = 99, lastlastKey = 99, pinpos = 0, resetTimer = 0; + static uint8_t pin[NUM_PIN_DIGITS] = {0}; + bool pinOK = true; + uint16_t keyVal = analogRead(KeyboardPin); + if(keyVal < 15) + key = 3; + else if(keyVal < 55) + key = 6; + else if(keyVal < 110) + key = 9; + else if(keyVal < 200) + key = 10; + else if(keyVal < 300) + key = 2; + else if(keyVal < 400) + key = 5; + else if(keyVal < 500) + key = 8; + else if(keyVal < 700) + key = 0; + else if(keyVal < 900) + key = 1; + else if(keyVal < 1300) + key = 4; + else if(keyVal < 1800) + key = 7; + else if(keyVal < 2600) + key = 11; + + if(key == 99 && lastKey != key && lastlastKey == lastKey){ //take the second last pressed value that was read before keyboard was released. + Serial.print("Keyboard: "); + Serial.println(lastKey); + resetTimer = 0; + pin[pinpos++] = lastKey; + } + if(pinpos){ + resetTimer++; + if(resetTimer > 4000/KEY_POLLING_MS){ + resetTimer = 0; + pinpos = 0; + Serial.println("RESET"); + } + if(pinpos == NUM_PIN_DIGITS){ + pinpos = 0; + resetTimer = 0; + String PinStr = settingsManager.getAppSettings().chosenPin; + uint8_t chosenPin[NUM_PIN_DIGITS]; + + for(uint8_t i=0;i< NUM_PIN_DIGITS;i++){ + uint8_t coosenPinDigit = PinStr.charAt(i)-0x30; + if(pin[i] != coosenPinDigit){ + pinOK= false; + } + } + if(pinOK){ + Serial.println("OPEN!!"); + Match match; + match.matchName = "KEYPAD"; + openDoor(match); + }else{ + Serial.println("WRONG"); + } + } + } + lastlastKey = lastKey; + lastKey = key; +} + void setup() { + keyboardTick.attach_ms(KEY_POLLING_MS,keyboardPoller); // open serial monitor for debug infos + pinMode(4,ANALOG); + pinMode(doorOpenerOutputPin,OUTPUT); Serial.begin(115200); //while (!Serial); // For Yun/Leo/Micro/Zero/... //delay(2000); @@ -709,7 +822,7 @@ void setup() fingerManager.setLedRingError(); } else { fingerManager.setLedRingError(); - shouldReboot = true; + //shouldReboot = true; } } @@ -724,6 +837,7 @@ void loop() reboot(); } + // Reconnect handling if (currentMode != Mode::wificonfig) { @@ -750,6 +864,9 @@ void loop() // do the actual loop work switch (currentMode) { + case Mode::cooldown: + + break; case Mode::scan: if (fingerManager.connected) doScan();