#include "main.h" volatile uint64_t cardData = 0; volatile bool newDataAvailable = false; unsigned long lastDataTime = 0; const unsigned long displayDelay = 1000; // Delay in milliseconds after which the data is displayed const unsigned long wifiRebootTimeout = 20000; // Delay before reboot after disconnect unsigned int bitCount = 0; // Variable to keep track of the bit count unsigned int maxReaderWaitTime = 9000; // Variable to timeout reader after too long of no data. #ifdef WEB_SERVER AsyncWebServer server(80); #endif #ifdef WIFI void connectToWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); #ifdef SERIAL_DEBUG Serial.print("Connecting to WiFi .."); #endif unsigned long startTime = millis(); // Record the start time of connection while (WiFi.status() != WL_CONNECTED) { delay(500); #ifdef SERIAL_DEBUG Serial.print("."); #endif // Check if it's time to reboot if (millis() - startTime >= wifiRebootTimeout) { // Reboot after 20 seconds #ifdef SERIAL_DEBUG Serial.println("\nFailed to connect. Rebooting..."); #endif ESP.restart(); // Reboot the Arduino board } } #ifdef SERIAL_DEBUG Serial.println("WiFi connected"); #endif } void GetWifiInfo(){ if(WiFi.status() == WL_CONNECTED) { #ifdef SERIAL_DEBUG Serial.print("[*] Network information for "); Serial.println(ssid); Serial.println("[+] BSSID : " + WiFi.BSSIDstr()); Serial.print("[+] Gateway IP : "); Serial.println(WiFi.gatewayIP()); Serial.print("[+] Subnet Mask : "); Serial.println(WiFi.subnetMask()); Serial.println((String)"[+] RSSI : " + WiFi.RSSI() + " dB"); Serial.print("[+] ESP32 IP : "); Serial.println(WiFi.localIP()); #endif } } void WiFiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info){ #ifdef NET_FAIL_SAFE unlockDoor(true); #endif #ifdef SERIAL_DEBUG Serial.println("Disconnected from WiFi access point"); Serial.print("WiFi lost connection. Reason: "); Serial.println(info.wifi_sta_disconnected.reason); Serial.println("Trying to Reconnect"); #endif connectToWiFi(); } void WiFiStationConnected(WiFiEvent_t event, WiFiEventInfo_t info){ #ifdef SERIAL_DEBUG Serial.println("Connected to AP successfully!"); #endif #ifdef NET_FAIL_SAFE lockDoor(); #endif } void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info){ #ifdef SERIAL_DEBUG #ifdef WIFI GetWifiInfo(); #endif #endif } #endif #ifdef WEB_SERVER #endif void handleInterrupt(int bitValue) { static unsigned long lastInterruptTime = 0; unsigned long interruptTime = micros(); if (interruptTime - lastInterruptTime > 200) { cardData <<= 1; cardData |= bitValue; newDataAvailable = true; bitCount++; // Increment the bit count } lastInterruptTime = interruptTime; lastDataTime = millis(); // Update the time of last received data } void handleData0Interrupt() { handleInterrupt(0); } void handleData1Interrupt() { handleInterrupt(1); } void setup() { #ifdef SERIAL_DEBUG Serial.begin(9600); #endif #ifdef WEB_SERVER WiFi.disconnect(true); #endif #ifdef LOCAL_ACL acl.loadFromEEPROM(); #endif settings.loadFromEEPROM(); // Initialize SPIFFS #ifdef WEB_SERVER if(!SPIFFS.begin(true)){ #ifdef SERIAL_DEBUG Serial.println("An Error has occurred while mounting SPIFFS"); #endif return; } #ifdef WEB_OTA_UPDATE AsyncElegantOTA.begin(&server, http_username, http_password); #endif #ifdef WEB_SERIAL_DEBUG WebSerial.begin(&server); #endif #endif pinMode(DATA0_PIN, INPUT_PULLUP); pinMode(DATA1_PIN, INPUT_PULLUP); #ifdef LEDCTL_PIN pinMode(LEDCTL_PIN, OUTPUT); #endif #ifdef RELAY1 pinMode(RELAY1_PIN, OUTPUT); #endif attachInterrupt(digitalPinToInterrupt(DATA0_PIN), handleData0Interrupt, FALLING); attachInterrupt(digitalPinToInterrupt(DATA1_PIN), handleData1Interrupt, FALLING); #ifdef WIFI WiFi.onEvent(WiFiStationConnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED); WiFi.onEvent(WiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP); WiFi.onEvent(WiFiStationDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED); connectToWiFi(); #endif #ifdef RELAY1 #ifdef SERIAL_DEBUG Serial.println("Enabling Relay: Locking Door"); #endif lockDoor(); #endif #ifdef RELAY2 pinMode(RELAY2_PIN, OUTPUT); #endif #ifdef BUZZER pinMode(ALARM_PIN, OUTPUT); digitalWrite(ALARM_PIN, HIGH); // Do not set to low or it will constantly beep. #endif #ifdef WEB_SERVER MainWebServer.begin(&server, http_username, http_password); #ifdef LOCAL_ACL #ifdef LOCAL_ACL_API ACLWebServer.begin(&server, http_username, http_password); #endif #endif server.begin(); #endif } void loop() { if (newDataAvailable) { newDataAvailable = false; lastDataTime = millis(); // Reset the time of last received data } if (millis() - lastDataTime >= displayDelay && cardData != 0) { uint64_t facilityID = (cardData >> 17) & 0xFFFF; uint64_t cardID = (cardData >> 1) & 0xFFFF; #ifdef SERIAL_DEBUG Serial.print("Facility ID (Decimal): "); Serial.println(facilityID); Serial.print("Facility ID (Binary): "); Serial.println(facilityID, BIN); Serial.print("Card ID (Decimal): "); Serial.println(cardID); Serial.print("Card ID (Binary): "); Serial.println(cardID, BIN); Serial.print("Card Data (Binary): "); Serial.println(cardData, BIN); Serial.print("Total Bits Received: "); Serial.println(bitCount); #endif #ifdef WEB_SERIAL_DEBUG WebSerial.print("Facility ID (Decimal): "); WebSerial.println(facilityID); WebSerial.print("Facility ID (Binary): "); WebSerial.println(facilityID, BIN); WebSerial.print("Card ID (Decimal): "); WebSerial.println(cardID); WebSerial.print("Card ID (Binary): "); WebSerial.println(cardID, BIN); WebSerial.print("Card Data (Binary): "); WebSerial.println(cardData, BIN); WebSerial.print("Total Bits Received: "); WebSerial.println(bitCount); #endif String fullCardID = String(facilityID)+":"+String(cardID); #ifdef SERIAL_DEBUG Serial.print("Full Card (Tinance2): "); Serial.println(fullCardID); #endif #ifdef WEB_SERIAL_DEBUG WebSerial.print("Full Card (Tinance2): "); WebSerial.println(fullCardID); #endif cardData = 0; // Reset the card data lastDataTime = millis(); // Reset the time of last received data bitCount = 0; // Reset the bit count #ifdef LOCAL_ACL if (acl.validateAccess(String(cardID))) { #ifdef SERIAL_DEBUG Serial.println("LOCAL_AUTH: Access granted!"); #endif // Perform actions for authorized access #ifdef LATCH_DOOR if (!settings.DoorDisabled()) { unlockDoor(false); delay(RELAY_DELAY); lockDoor(); } #endif #ifdef TOGGLE_DOOR if (!settings.DoorDisabled()) { toggleDoor(); delay(RELAY_DELAY); } #endif } else { #ifdef SERIAL_DEBUG Serial.println("LOCAL_AUTH: Access denied!"); #endif // Perform actions for denied access #ifdef BUZZER denied_beep(); #endif } #endif } else if (millis() - lastDataTime >= maxReaderWaitTime) { cardData = 0; // Reset the card data lastDataTime = millis(); // Reset the time of last received data bitCount = 0; // Reset the bit count } }