2023-06-12 17:17:28 +00:00
|
|
|
#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
|
2023-06-12 19:50:32 +00:00
|
|
|
unsigned int maxReaderWaitTime = 9000; // Variable to timeout reader after too long of no data.
|
2023-06-13 18:01:13 +00:00
|
|
|
Settings settings;
|
2023-06-13 18:33:44 +00:00
|
|
|
AsyncWebServer server(80);
|
2023-06-12 17:17:28 +00:00
|
|
|
|
|
|
|
#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
|
|
|
|
String outputState(int output){
|
|
|
|
if(digitalRead(output)){
|
|
|
|
return "checked";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replaces placeholder with button section in your web page
|
|
|
|
String processor(const String& var){
|
|
|
|
//Serial.println(var);
|
|
|
|
if(var == "BUTTONPLACEHOLDER"){
|
|
|
|
String buttons = "";
|
|
|
|
|
|
|
|
#ifdef RELAY1
|
2023-06-13 14:15:42 +00:00
|
|
|
buttons += "<h4>Output - Relay 1 </h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"relay1\" " + outputState(RELAY1_PIN) + "><span class=\"slider\"></span></label>";
|
2023-06-12 17:17:28 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return buttons;
|
|
|
|
}
|
|
|
|
return String();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef LOCAL_ACL
|
|
|
|
#ifdef LOCAL_ACL_API
|
|
|
|
// Handler for the '/users' endpoint to list all users
|
|
|
|
void handleListUsers(AsyncWebServerRequest* request) {
|
|
|
|
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
// Create a JSON array to store the users
|
|
|
|
StaticJsonDocument<512> jsonDoc;
|
|
|
|
JsonArray usersArray = jsonDoc.to<JsonArray>();
|
|
|
|
|
|
|
|
// 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++) {
|
|
|
|
JsonObject user = usersArray.createNestedObject();
|
|
|
|
user["cardId"] = aclData[i].cardId;
|
|
|
|
user["desc"] = aclData[i].desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the JSON array to a string
|
|
|
|
String response;
|
|
|
|
serializeJson(usersArray, response);
|
|
|
|
|
|
|
|
// Set the response content type to JSON
|
|
|
|
request->send(200, "application/json", response);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void handleCreateUser(AsyncWebServerRequest* request) {
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
|
|
|
|
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
|
|
|
|
else {
|
2023-06-13 10:57:40 +00:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(request->hasParam("desc", true)) {} //This is important, otherwise the sketch will crash if there is no body
|
|
|
|
else {
|
2023-06-13 10:57:40 +00:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No desc\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
|
|
|
|
String cardId = String(request->arg("cardId"));
|
|
|
|
String desc = String(request->arg("desc"));
|
|
|
|
|
|
|
|
if (acl.validateAccess(String(cardId))) {
|
2023-06-13 10:57:40 +00:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"Duplicate ACL\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
request->send(response);
|
|
|
|
} else {
|
|
|
|
acl.addUser(cardId, desc);
|
|
|
|
acl.saveToEEPROM();
|
|
|
|
request->send(201); // Create
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handler for the '/users/update' endpoint to remove a user
|
|
|
|
void handleUpdateUser(AsyncWebServerRequest* request) {
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
|
|
|
|
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
|
|
|
|
else {
|
2023-06-13 10:57:40 +00:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(request->hasParam("newCardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
|
|
|
|
else {
|
2023-06-13 10:57:40 +00:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "\"msg\":\"No newCardId\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(request->hasParam("desc", true)) {} //This is important, otherwise the sketch will crash if there is no body
|
|
|
|
else {
|
2023-06-13 10:57:40 +00:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No desc\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
String cardId = String(request->arg("cardId"));
|
|
|
|
String newCardId = String(request->arg("newCardId"));
|
|
|
|
String desc = String(request->arg("desc"));
|
|
|
|
acl.updateUser(cardId, newCardId, desc);
|
|
|
|
acl.saveToEEPROM();
|
|
|
|
request->send(201); // Created
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handler for the '/users/remove' endpoint to remove a user
|
|
|
|
void handleRemoveUser(AsyncWebServerRequest* request) {
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
|
|
|
|
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
|
|
|
|
else {
|
2023-06-13 10:57:40 +00:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
String cardId = String(request->arg("cardId"));
|
|
|
|
acl.removeUser(cardId);
|
|
|
|
acl.saveToEEPROM();
|
|
|
|
request->send(201); // Created
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
2023-06-13 18:01:13 +00:00
|
|
|
|
|
|
|
settings.loadFromEEPROM();
|
|
|
|
|
2023-06-12 17:17:28 +00:00
|
|
|
// 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);
|
|
|
|
|
2023-06-12 17:57:43 +00:00
|
|
|
#ifdef LEDCTL_PIN
|
|
|
|
pinMode(LEDCTL_PIN, OUTPUT);
|
|
|
|
#endif
|
|
|
|
|
2023-06-12 17:17:28 +00:00
|
|
|
#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);
|
|
|
|
// Do not set to low or it will constantly beep.
|
|
|
|
digitalWrite(ALARM_PIN, HIGH);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WEB_SERVER
|
|
|
|
// Route for root / web page
|
|
|
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
request->send(SPIFFS, "/index.html", String(), false, processor);
|
|
|
|
});
|
|
|
|
|
|
|
|
server.onNotFound([](AsyncWebServerRequest *request){
|
2023-06-13 10:57:40 +00:00
|
|
|
request->send(200, "application/json", "{\"msg\":\"The content you are looking for was not found\"}");
|
2023-06-12 17:17:28 +00:00
|
|
|
});
|
|
|
|
|
2023-06-13 15:09:48 +00:00
|
|
|
|
|
|
|
#ifdef RELAY1
|
|
|
|
server.on("/state/relay1", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"state\":\""+stateDoor()+"\"}");
|
|
|
|
request->send(response);
|
|
|
|
});
|
|
|
|
#endif
|
|
|
|
|
2023-06-13 18:01:13 +00:00
|
|
|
server.on("/settings/get/DoorDisabled", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"value\":\""+String(settings.DoorDisabled())+"\"}");
|
|
|
|
request->send(response);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send a GET request to <ESP_IP>/gpio?output=<paramOutput>&state=<paramState>
|
|
|
|
server.on("/settings/set/DoorDisabled", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
|
|
|
String value;
|
|
|
|
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
|
|
|
|
if (request->hasParam("value")) {
|
|
|
|
value = request->getParam("value")->value();
|
|
|
|
if (value == "0") {
|
|
|
|
settings.setDisableDoor(0);
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"value set to 0\"}");
|
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
else if (value =="1") {
|
|
|
|
settings.setDisableDoor(1);
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"value set to 1\"}");
|
|
|
|
request->send(response);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"value should be 0 or 1\"}");
|
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"Missing 'value' param.\"}");
|
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-06-13 14:15:42 +00:00
|
|
|
// Send a GET request to <ESP_IP>/gpio?output=<paramOutput>&state=<paramState>
|
2023-06-12 17:17:28 +00:00
|
|
|
server.on("/gpio", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
2023-06-13 14:15:42 +00:00
|
|
|
String paramOutput;
|
|
|
|
String paramState;
|
2023-06-12 17:17:28 +00:00
|
|
|
|
|
|
|
if(!request->authenticate(http_username, http_password))
|
|
|
|
return request->requestAuthentication();
|
|
|
|
|
2023-06-13 14:15:42 +00:00
|
|
|
// GET input1 value on <ESP_IP>/gpio?output=<paramOutput>&state=<paramState>
|
2023-06-12 17:17:28 +00:00
|
|
|
if (request->hasParam("output") && request->hasParam("state")) {
|
2023-06-13 14:15:42 +00:00
|
|
|
paramOutput = request->getParam("output")->value();
|
|
|
|
paramState = request->getParam("state")->value();
|
2023-06-12 17:17:28 +00:00
|
|
|
|
2023-06-13 14:15:42 +00:00
|
|
|
#ifdef RELAY1
|
|
|
|
if (paramOutput == "relay1") {
|
|
|
|
if (paramState == String(0)){
|
|
|
|
unlockDoor(false);
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Door Unlocked.\"}");
|
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
else if (paramState == String(1)) {
|
|
|
|
lockDoor();
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Door Locked.\"}");
|
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Incorect state provide 0 to unlock and 1 to lock.\"}");
|
|
|
|
request->send(response);
|
|
|
|
}
|
|
|
|
}
|
2023-06-12 17:17:28 +00:00
|
|
|
|
2023-06-13 14:15:42 +00:00
|
|
|
|
2023-06-12 17:17:28 +00:00
|
|
|
#endif
|
2023-06-13 14:15:42 +00:00
|
|
|
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"Error with request, incorrect GPIO pin number.\"}");
|
|
|
|
request->send(response);
|
|
|
|
|
|
|
|
}
|
2023-06-12 17:17:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef LOCAL_ACL
|
|
|
|
#ifdef LOCAL_ACL_API
|
|
|
|
server.on("/users", HTTP_GET, handleListUsers);
|
|
|
|
server.on("/users/create", HTTP_POST, handleCreateUser);
|
|
|
|
server.on("/users/update", HTTP_POST, handleUpdateUser);
|
|
|
|
server.on("/users/remove", HTTP_POST, handleRemoveUser);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
server.begin();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void loop() {
|
|
|
|
|
|
|
|
if (newDataAvailable) {
|
|
|
|
newDataAvailable = false;
|
|
|
|
lastDataTime = millis(); // Reset the time of last received data
|
|
|
|
}
|
|
|
|
|
2023-06-12 19:50:32 +00:00
|
|
|
if (millis() - lastDataTime >= displayDelay && cardData != 0) {
|
|
|
|
|
2023-06-12 17:17:28 +00:00
|
|
|
|
|
|
|
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
|
2023-06-13 18:01:13 +00:00
|
|
|
if (!settings.DoorDisabled()) {
|
|
|
|
unlockDoor(false);
|
|
|
|
delay(RELAY_DELAY);
|
|
|
|
lockDoor();
|
|
|
|
}
|
2023-06-12 17:17:28 +00:00
|
|
|
#endif
|
|
|
|
#ifdef TOGGLE_DOOR
|
2023-06-13 18:01:13 +00:00
|
|
|
if (!settings.DoorDisabled()) {
|
|
|
|
toggleDoor();
|
|
|
|
delay(RELAY_DELAY);
|
|
|
|
}
|
2023-06-12 17:17:28 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifdef SERIAL_DEBUG
|
|
|
|
Serial.println("LOCAL_AUTH: Access denied!");
|
|
|
|
#endif
|
|
|
|
// Perform actions for denied access
|
|
|
|
#ifdef BUZZER
|
|
|
|
denied_beep();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
2023-06-12 19:50:32 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
}
|
2023-06-12 17:17:28 +00:00
|
|
|
}
|