779 lines
No EOL
22 KiB
C++
779 lines
No EOL
22 KiB
C++
#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.
|
|
HTTPClient http;
|
|
|
|
#ifdef LOCAL_ACL
|
|
void localAcl(String cardID) {
|
|
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(false);
|
|
}
|
|
#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
|
|
|
|
|
|
#ifdef WEB_SERVER
|
|
AsyncWebServer server(80);
|
|
#endif
|
|
|
|
#ifdef WIFI
|
|
String getESP32ChipID() {
|
|
uint64_t chipId = ESP.getEfuseMac(); // Get the ESP32 chip ID
|
|
return String(chipId, HEX);
|
|
}
|
|
|
|
void connectToWiFi(String ssid, String password) {
|
|
String hostname = "MX-" + getESP32ChipID() + "-RDR";
|
|
WiFi.hostname(hostname.c_str());
|
|
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Connecting to WiFi...");
|
|
#endif
|
|
|
|
WiFi.begin(ssid.c_str(), password.c_str());
|
|
|
|
int attempts = 0;
|
|
while (WiFi.status() != WL_CONNECTED && attempts < 30) {
|
|
delay(1000);
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.print(".");
|
|
#endif
|
|
attempts++;
|
|
}
|
|
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("\nConnected to WiFi");
|
|
Serial.print("IP Address: ");
|
|
Serial.println(WiFi.localIP());
|
|
#endif
|
|
} else {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("\nFailed to connect to WiFi. Rebooting...");
|
|
#endif
|
|
delay(1000);
|
|
ESP.restart();
|
|
}
|
|
}
|
|
|
|
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(ssid, password);
|
|
}
|
|
|
|
void WiFiStationConnected(WiFiEvent_t event, WiFiEventInfo_t info){
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Connected to AP successfully!");
|
|
#endif
|
|
#ifdef NET_FAIL_SAFE
|
|
lockDoor(true);
|
|
#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) {
|
|
if (bitCount < 34) {
|
|
cardData <<= 1;
|
|
cardData |= bitValue;
|
|
newDataAvailable = true;
|
|
bitCount++; // Increment the bit count
|
|
}
|
|
}
|
|
|
|
if (bitCount <= 34) {
|
|
lastInterruptTime = interruptTime;
|
|
lastDataTime = millis(); // Update the time of last received data
|
|
}
|
|
}
|
|
void handleData0Interrupt() {
|
|
handleInterrupt(0);
|
|
}
|
|
|
|
void handleData1Interrupt() {
|
|
handleInterrupt(1);
|
|
}
|
|
|
|
#ifdef TINANCE2_BACKEND
|
|
class Tinance2HttpClient {
|
|
public:
|
|
Tinance2HttpClient() {}
|
|
|
|
std::pair<String, int> sendHttpRequest(String url, String method, String payload) {
|
|
|
|
if (!http.begin(url)) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Failed to begin HTTP request");
|
|
#endif
|
|
http.end();
|
|
return std::make_pair("", -1);
|
|
}
|
|
|
|
// Set the headers
|
|
http.addHeader("Content-Type", "application/json");
|
|
http.addHeader("X-Identifier", tinance2_reader_identifer);
|
|
http.addHeader("X-Access-Key", tinance2_reader_key);
|
|
|
|
// Set the HTTP timeout to 5 seconds
|
|
http.setTimeout(5000);
|
|
|
|
// Send the POST request
|
|
int httpResponseCode;
|
|
if (method == "POST") {
|
|
httpResponseCode = http.POST(payload);
|
|
} else if (method == "GET") {
|
|
httpResponseCode = http.GET();
|
|
} else {
|
|
// Handle invalid method
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Invalid HTTP method");
|
|
#endif
|
|
http.end();
|
|
return std::make_pair("", -1);
|
|
}
|
|
|
|
if (httpResponseCode <= 0) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Request Failed (response less than 0)");
|
|
#endif
|
|
http.end();
|
|
return std::make_pair("", httpResponseCode);
|
|
}
|
|
|
|
String responseBody = http.getString();
|
|
|
|
// Cleanup
|
|
http.end();
|
|
|
|
return std::make_pair(responseBody, httpResponseCode);
|
|
}
|
|
|
|
// Function to decode JSON response
|
|
DynamicJsonDocument decodeJsonResponse(const String& json) {
|
|
DynamicJsonDocument doc(1024); // Adjust the size as per your JSON data
|
|
|
|
DeserializationError error = deserializeJson(doc, json);
|
|
|
|
if (error) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.print("Failed to parse JSON: ");
|
|
Serial.println(error.c_str());
|
|
#endif
|
|
}
|
|
|
|
return doc;
|
|
}
|
|
};
|
|
|
|
// Function to send the authentication request to Tinance2
|
|
void tinance2authrequest(String fullCardID, String cardID) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("WIFI Status: " + String(WiFi.status()));
|
|
#endif
|
|
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Sending Request to Tinance2 for card: " + fullCardID);
|
|
#endif
|
|
|
|
// Create the JSON payload
|
|
String payload = "{\"full_card_id\":\"" + String(fullCardID) + "\"}";
|
|
// Send the HTTP request and get the response
|
|
Tinance2HttpClient httpClient;
|
|
std::pair<String, int> responsePair = httpClient.sendHttpRequest(tinance2_url_validatecard, "POST", payload);
|
|
String response = responsePair.first;
|
|
int httpResponseCode = responsePair.second;
|
|
|
|
#ifdef SERIAL_DEBUG
|
|
// Print the response
|
|
Serial.println("HTTP Response: " + response);
|
|
#endif
|
|
|
|
// Process the response
|
|
if (httpResponseCode != 200 && httpResponseCode != 401 && httpResponseCode != 402 && httpResponseCode != 403) {
|
|
#ifdef LOCAL_ACL
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Got unexpected http response using offline auth.");
|
|
#endif
|
|
localAcl(String(cardID));
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
// Check the response code
|
|
if (httpResponseCode == 200) {
|
|
Serial.println("Tinance2 Door Access Granted");
|
|
#ifdef LATCH_DOOR
|
|
if (!settings.DoorDisabled()) {
|
|
unlockDoor(false);
|
|
delay(RELAY_DELAY);
|
|
lockDoor(false);
|
|
}
|
|
#endif
|
|
#ifdef TOGGLE_DOOR
|
|
if (!settings.DoorDisabled()) {
|
|
toggleDoor();
|
|
delay(RELAY_DELAY);
|
|
}
|
|
#endif
|
|
} else if (httpResponseCode == 400 || httpResponseCode == 401 || httpResponseCode == 402 || httpResponseCode == 403) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Tinance2 Door Access Denied");
|
|
#endif
|
|
#ifdef BUZZER
|
|
denied_beep();
|
|
#endif
|
|
}
|
|
} else {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Tinance2 Wifi Disconnected using offline processes.");
|
|
#endif
|
|
#ifdef LOCAL_ACL
|
|
localAcl(String(cardID));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef TINANCE2_BACKEND_SYNC
|
|
#include <freertos/FreeRTOS.h>
|
|
#include <freertos/task.h>
|
|
|
|
void tinance2SyncTaskFunction(void *parameter) {
|
|
while (true) {
|
|
// Your code here
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Syncing Tinance2");
|
|
#endif
|
|
vTaskDelay(pdMS_TO_TICKS(15000)); // Delay for 15 seconds
|
|
|
|
Tinance2HttpClient httpClient;
|
|
std::pair<String, int> responsePair = httpClient.sendHttpRequest(tinance2_url_readerinfo, "GET", "");
|
|
String response = responsePair.first;
|
|
int httpResponseCode = responsePair.second;
|
|
|
|
#ifdef SERIAL_DEBUG
|
|
// Print the response
|
|
Serial.println("HTTP Response: " + response);
|
|
Serial.println("HTTP Response Code: " + String(httpResponseCode));
|
|
#endif
|
|
|
|
// Process the response
|
|
DynamicJsonDocument json = httpClient.decodeJsonResponse(response);
|
|
|
|
if (json.containsKey("enabled")) {
|
|
bool DisableDoor = json["enabled"].as<bool>();
|
|
settings.setDisableDoor(!DisableDoor);
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("JSON Reader Enabled: " + json["enabled"].as<String>());
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
void setup() {
|
|
// allow reuse (if server supports it)
|
|
http.setReuse(true);
|
|
|
|
#if defined SERIAL_DEBUG || defined SERIAL_ACL
|
|
Serial.begin(9600);
|
|
#endif
|
|
|
|
#ifdef WEB_SERVER
|
|
WiFi.disconnect(true);
|
|
#endif
|
|
|
|
#ifdef TINANCE2_BACKEND_SYNC
|
|
xTaskCreatePinnedToCore(tinance2SyncTaskFunction, "Task", 10000, NULL, 1, NULL, 1);
|
|
#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 BIT_MODE_WG34
|
|
pinMode(BIT_MODE_WG34_PIN, OUTPUT);
|
|
digitalWrite(BIT_MODE_WG34_PIN, HIGH);
|
|
#endif
|
|
|
|
#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(ssid, password);
|
|
#endif
|
|
|
|
#ifdef RELAY1
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Enabling Relay: Locking Door");
|
|
#endif
|
|
lockDoor(true);
|
|
#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
|
|
|
|
}
|
|
|
|
|
|
#ifdef LOCAL_ACL
|
|
#ifdef SERIAL_ACL
|
|
|
|
struct WordList {
|
|
char** words;
|
|
int length;
|
|
};
|
|
|
|
WordList splitString(const char* inputString, const char* delimiter = " ") {
|
|
WordList result;
|
|
result.words = NULL;
|
|
result.length = 0;
|
|
|
|
// Create a temporary copy of the input string since strtok modifies the string
|
|
char* inputCopy = strdup(inputString);
|
|
|
|
// Get the first word
|
|
char* word = strtok(inputCopy, delimiter);
|
|
|
|
// Split the string and store each word in the dynamic list
|
|
while (word != NULL) {
|
|
result.length++;
|
|
|
|
// Reallocate memory for the dynamic list
|
|
result.words = (char**)realloc(result.words, (result.length + 1) * sizeof(char*));
|
|
|
|
// Allocate memory for the current word and copy it into the list
|
|
result.words[result.length - 1] = (char*)malloc(strlen(word) + 1);
|
|
strcpy(result.words[result.length - 1], word);
|
|
|
|
// Set the next element in the list to NULL for termination
|
|
result.words[result.length] = NULL;
|
|
|
|
// Get the next word
|
|
word = strtok(NULL, delimiter);
|
|
}
|
|
|
|
// Free the temporary copy of the input string
|
|
free(inputCopy);
|
|
|
|
return result;
|
|
}
|
|
|
|
void freeWordList(char** wordList) {
|
|
for (int i = 0; wordList[i] != NULL; i++) {
|
|
free(wordList[i]);
|
|
}
|
|
free(wordList);
|
|
}
|
|
void checkSerialCommand() {
|
|
if (Serial.available() > 0) {
|
|
String command = Serial.readStringUntil('\n'); // Read the incoming command until a newline character is received
|
|
Serial.println("Received command: " + command); // Echo back the received command
|
|
command.trim(); // Remove any leading or trailing whitespaces
|
|
|
|
if (command.length() == 0) {
|
|
Serial.println("Invalid command"); // If the command is not recognized
|
|
}
|
|
else {
|
|
WordList wordData = splitString(command.c_str());
|
|
char** wordList = wordData.words;
|
|
int wordCount = wordData.length;
|
|
|
|
String prefix = wordList[0];
|
|
|
|
// Command Validate Access
|
|
if (prefix.equals("validateAccess")) {
|
|
if (wordCount == 2) {
|
|
bool result = acl.validateAccess(String(wordList[1]));
|
|
|
|
if (result) {
|
|
Serial.println("Access granted!");
|
|
}
|
|
else {
|
|
Serial.println("Access denied!");
|
|
}
|
|
}
|
|
else {
|
|
Serial.println("validateAccess requires exactly 1 arguments (cardId)");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Command Add User
|
|
if (prefix.equals("addUser")) {
|
|
if (wordCount == 3) {
|
|
acl.addUser(wordList[1], wordList[2]);
|
|
acl.saveToEEPROM();
|
|
Serial.println("User Added!");
|
|
}
|
|
else {
|
|
Serial.println("addUser requires exactly 2 arguments (cardId, Description)");
|
|
return;
|
|
}
|
|
}
|
|
// Command Update User
|
|
if (prefix.equals("updateUser")) {
|
|
if (wordCount == 4) {
|
|
acl.updateUser(wordList[1], wordList[2], wordList[3]);
|
|
acl.saveToEEPROM();
|
|
Serial.println("User Updated!");
|
|
}
|
|
else {
|
|
Serial.println("userUser requires exactly 2 arguments (cardId, newCardId, newDescription)");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
// Command Remove User
|
|
if (prefix.equals("removeUser")) {
|
|
if (wordCount == 2) {
|
|
acl.removeUser(wordList[1]);
|
|
acl.saveToEEPROM();
|
|
Serial.println("User Removed!!");
|
|
}
|
|
else {
|
|
Serial.println("removeUser requires exactly 1 argument (cardId)");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
// Command List Uses
|
|
if (prefix.equals("listUsers")) {
|
|
if (wordCount == 1) {
|
|
// Retrieve the ACL data using the getter function
|
|
const User* aclData = acl.getACL();
|
|
|
|
// Iterate over each user in the ACL and add it to the JSON array
|
|
for (int i = 0; i < acl.getACLSize(); i++) {
|
|
Serial.print(aclData[i].cardId);
|
|
Serial.print(" : ");
|
|
Serial.println(aclData[i].desc);
|
|
}
|
|
}
|
|
else {
|
|
Serial.println("removeUser requires exactly 0 arguments");
|
|
return;
|
|
}
|
|
}
|
|
|
|
freeWordList(wordList);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifdef TINANCE2_BACKEND
|
|
bool previousDoorDisabled = false; // Declare the missing variable
|
|
bool isFirstRun = true; // Declare the missing variable
|
|
|
|
void updateDoorStatus() {
|
|
|
|
|
|
bool previousDoorDisabled = false; // Declare the missing variable
|
|
bool isFirstRun = true; // Declare the missing variable
|
|
|
|
if (settings.DoorDisabled() != previousDoorDisabled && !isFirstRun) {
|
|
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.print("DoorDisabled setting changed to: ");
|
|
Serial.println(settings.DoorDisabled());
|
|
Serial.print("Previous DoorDisabled setting: ");
|
|
Serial.println(previousDoorDisabled);
|
|
Serial.print("isFirstRun: ");
|
|
Serial.println(isFirstRun);
|
|
#endif
|
|
|
|
if (settings.DoorDisabled()) {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Disabling Door due to DoorDisabled setting");
|
|
#endif
|
|
unlockDoor(false); // Provide the required argument
|
|
} else {
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("Enabling Door due to DoorDisabled setting");
|
|
#endif
|
|
lockDoor(false);
|
|
}
|
|
}
|
|
|
|
// Update the previousDoorDisabled variable
|
|
previousDoorDisabled = settings.DoorDisabled();
|
|
isFirstRun = false;
|
|
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief The main loop function that runs repeatedly in the program.
|
|
*
|
|
* This function is responsible for processing the card reader data and performing necessary actions based on the received data.
|
|
* It checks for new data availability, validates the data, and performs actions accordingly.
|
|
* If valid card data is received, it extracts the facility ID and card ID, and prints them to the Serial or WebSerial (if enabled).
|
|
* It then calls the appropriate functions based on the defined macros to handle the card data.
|
|
* If no valid card data is received within the specified time, it resets the card data and bit count.
|
|
*
|
|
* @note This function assumes the availability of certain macros like TINANCE2_BACKEND, LOCAL_ACL, SERIAL_ACL, SERIAL_DEBUG, and WEB_SERIAL_DEBUG.
|
|
*
|
|
* @note This function assumes the availability of certain variables like newDataAvailable, lastDataTime, displayDelay, cardData, bitCount, and maxReaderWaitTime.
|
|
*
|
|
* @note This function assumes the availability of certain functions like updateDoorStatus, checkSerialCommand, tinance2authrequest, and localAcl.
|
|
*/
|
|
void loop() {
|
|
#ifdef TINANCE2_BACKEND
|
|
updateDoorStatus();
|
|
#endif
|
|
|
|
#ifdef LOCAL_ACL
|
|
#ifdef SERIAL_ACL
|
|
checkSerialCommand();
|
|
#endif
|
|
#endif
|
|
|
|
if (newDataAvailable) {
|
|
newDataAvailable = false;
|
|
lastDataTime = millis(); // Reset the time of last received data
|
|
}
|
|
|
|
if (millis() - lastDataTime >= displayDelay && cardData != 0 && (bitCount == 26 || bitCount == 34)) {
|
|
|
|
uint64_t facilityID = (cardData >> 17) & 0xFFFF;
|
|
uint64_t cardID = (cardData >> 1) & 0xFFFF;
|
|
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("--- Reader Input Processed ---");
|
|
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
|
|
|
|
#ifdef TINANCE2_BACKEND
|
|
tinance2authrequest(String(fullCardID), String(cardID));
|
|
#endif
|
|
|
|
#ifdef LOCAL_ACL
|
|
#ifndef TINANCE2_BACKEND
|
|
localAcl(String(cardID));
|
|
#endif
|
|
#endif
|
|
|
|
cardData = 0; // Reset the card data
|
|
lastDataTime = millis(); // Reset the time of last received data
|
|
bitCount = 0; // Reset the bit count
|
|
|
|
}
|
|
else if (millis() - lastDataTime >= maxReaderWaitTime && cardData != 0) {
|
|
uint64_t facilityID = (cardData >> 17) & 0xFFFF;
|
|
uint64_t cardID = (cardData >> 1) & 0xFFFF;
|
|
|
|
#ifdef SERIAL_DEBUG
|
|
Serial.println("--- Reader Input Error ---");
|
|
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
|
|
|
|
cardData = 0; // Reset the card data
|
|
lastDataTime = millis(); // Reset the time of last received data
|
|
bitCount = 0; // Reset the bit count
|
|
|
|
}
|
|
} |