From caf684682657c87b5fbd4b3f4bb2112d1099c835 Mon Sep 17 00:00:00 2001 From: Matthew Frost Date: Mon, 15 Apr 2024 20:28:30 +0200 Subject: [PATCH] better settings on the way --- data/index.html | 160 +++++++++++++++++++++++++++++++----- include/aclwebserver.h | 4 +- include/mainwebserver.h | 80 ++++++++++-------- include/settings.h | 21 +++-- src/main.cpp | 176 +++++++++++++++++++++++++++++++++++----- src/settings.cpp | 71 ++++++++++++---- src/tinance2.cpp | 4 +- 7 files changed, 412 insertions(+), 104 deletions(-) diff --git a/data/index.html b/data/index.html index e129d3a..f49be04 100644 --- a/data/index.html +++ b/data/index.html @@ -1,30 +1,150 @@ - + + ESP Web Server -

ESP Web Server

- %BUTTONPLACEHOLDER% - + +

Card Web Server & API

+ +
+

Latest News

+

Added API docs and Serial Interface docs. To access the API docs, click on "docs" in the navbar. For the Serial docs, just type "help" on the serial CLI.

+
+ + + + \ No newline at end of file diff --git a/include/aclwebserver.h b/include/aclwebserver.h index e04edd2..4201e33 100644 --- a/include/aclwebserver.h +++ b/include/aclwebserver.h @@ -1,5 +1,5 @@ -#ifndef aclwebserver_h -#define aclwebserver_h +#ifndef ACLWEBSERVER_H +#define ACLWEBSERVER_H #include "Arduino.h" #include "stdlib_noniso.h" diff --git a/include/mainwebserver.h b/include/mainwebserver.h index 76a2e33..7e88b68 100644 --- a/include/mainwebserver.h +++ b/include/mainwebserver.h @@ -1,5 +1,5 @@ -#ifndef mainwebserver_h -#define mainwebserver_h +#ifndef MAINWEBSERVER_H +#define MAINWEBSERVER_H #include "Arduino.h" #include "stdlib_noniso.h" @@ -37,7 +37,7 @@ class MainWebServerClass{ } } - request->send(SPIFFS, "/index.html", String(), false, processor); + request->send(SPIFFS, "/index.html", String(), false); }); _server->on("/version", HTTP_GET, [&](AsyncWebServerRequest *request){ @@ -46,7 +46,7 @@ class MainWebServerClass{ return request->requestAuthentication(); } } - request->send(200, "application/json", "{\"version\":\"3.2.4\"}"); + request->send(200, "application/json", "{\"version\":\"3.2.5\"}"); }); _server->onNotFound([&](AsyncWebServerRequest *request){ @@ -161,7 +161,7 @@ class MainWebServerClass{ return request->requestAuthentication(); } } - AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"identifier\":\""+String(settings.getTinance2ReaderIdentifier())+"\", \"key\":\""+String(settings.getTinance2ReaderKey())+"\"}"); + AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"identifier\":\""+settings.tinance2ReaderIdentifier+"\", \"key\":\""+settings.tinance2ReaderKey+"\"}"); request->send(response); }); @@ -185,13 +185,53 @@ class MainWebServerClass{ } String key = String(request->arg("key")); - settings.setTinance2ReaderIdentifier(identifier); - settings.setTinance2ReaderKey(key); + settings.tinance2ReaderIdentifier = identifier; + settings.tinance2ReaderKey = key; + + settings.saveSetting("t2", "ri", settings.tinance2ReaderIdentifier, "string"); + settings.saveSetting("t2", "rk", settings.tinance2ReaderKey, "string"); + AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Tinance credentials updated\"}"); request->send(response); }); + + + _server->on("/settings/validatecardurl", HTTP_POST, [&] (AsyncWebServerRequest *request) { + if(_authRequired){ + if(!request->authenticate(_username.c_str(), _password.c_str())){ + return request->requestAuthentication(); + } + } + if(request->hasParam("url", true)) {} //This is important, otherwise the sketch will crash if there is no body + else { + AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No url\"}"); + request->send(response); + } + String url = String(request->arg("url")); + + settings.tinance2_url_validatecard = url; + settings.saveSetting("t2", "vcurl", settings.tinance2_url_validatecard, "string"); + + AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Tinance URL updated\"}"); + request->send(response); + + }); + + + _server->on("/settings/validatecardurl", HTTP_GET, [&] (AsyncWebServerRequest *request) { + if(_authRequired){ + if(!request->authenticate(_username.c_str(), _password.c_str())){ + return request->requestAuthentication(); + } + } + AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"value\":\""+settings.tinance2_url_validatecard+"\"}"); + request->send(response); + }); + + + } // deprecated, keeping for backward compatibility @@ -203,32 +243,6 @@ class MainWebServerClass{ String _username = ""; String _password = ""; bool _authRequired = false; - - static String outputState(int output){ - if(digitalRead(output)){ - return "checked"; - } - else { - return ""; - } - } - - // Replaces placeholder with button section in your web page - static String processor(const String& var){ - //Serial.println(var); - if(var == "BUTTONPLACEHOLDER"){ - String buttons = ""; - - #ifdef RELAY1 - buttons += "

Output - Relay 1

"; - #endif - - return buttons; - } - return String(); - } - - }; MainWebServerClass MainWebServer; diff --git a/include/settings.h b/include/settings.h index 02c68f1..07e078b 100644 --- a/include/settings.h +++ b/include/settings.h @@ -14,14 +14,23 @@ class Settings { private: bool disableDoor; String doorMode; - String tinance2ReaderIdentifier; - String tinance2ReaderKey; - public: Settings(); + String tinance2_url_validatecard; + String tinance2_url_readerinfo; + String tinance2_url_acls; + String tinance2_url_log; + String tinance2ReaderIdentifier; + String tinance2ReaderKey; + bool webhookLockEnabled; + String webhookLockHook; + bool webhookUnlockEnabled; + String webhookUnlockHook; + void loadFromEEPROM(); void saveToEEPROM(); + void saveSetting(const String& namespaceStr, const String& key, const String& value, const String& typeStr); void saveStringToEEPROM(String string, String value); void saveBoolToEEPROM(String string, String value); @@ -30,12 +39,6 @@ public: void setDoorMode(String value); String getDoorMode(); - - void setTinance2ReaderIdentifier(String value); - String getTinance2ReaderIdentifier(); - - void setTinance2ReaderKey(String value); - String getTinance2ReaderKey(); }; extern Settings settings; diff --git a/src/main.cpp b/src/main.cpp index 8a7f514..3b9bd5b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -141,7 +141,7 @@ void handleData1Interrupt() { void setup() { - #if defined SERIAL_DEBUG || defined SERIAL_ACL + #if defined SERIAL_DEBUG || defined SERIAL_CLI Serial.begin(9600); #endif @@ -263,7 +263,7 @@ void setup() { #ifdef LOCAL_ACL - #ifdef SERIAL_ACL + #ifdef SERIAL_CLI struct WordList { char** words; @@ -326,27 +326,163 @@ void setup() { int wordCount = wordData.length; String prefix = wordList[0]; + if (prefix.equals("help")) { + Serial.println("Available prefixes:"); + Serial.println("tinance2.identifier.get - No arguments"); + Serial.println("tinance2.identifier.set - 1 argument: new identifier"); + Serial.println("tinance2.key.get - No arguments"); + Serial.println("tinance2.key.set - 1 argument: new key"); + Serial.println("acl.local.validate - 1 argument: card ID"); + Serial.println("acl.local.add - 2 arguments: card ID, description"); + Serial.println("acl.local.update - 3 arguments: card ID, new card ID, new description"); + Serial.println("acl.local.remove - 1 argument: card ID"); + Serial.println("acl.local.list - No arguments"); + } + + if (prefix.equals("tinance2.identifier.get")) { + // Retrieves the Tinance2 reader identifier from the settings + Serial.println("Tinance2 Identifier: " + settings.tinance2ReaderIdentifier); + } + + if (prefix.equals("tinance2.identifier.set")) { + if (wordCount == 2) { + // Sets the Tinance2 reader identifier in the settings + settings.tinance2ReaderIdentifier = wordList[1]; + settings.saveSetting("t2", "ri", wordList[1], "string"); + } + } + + if (prefix.equals("tinance2.key.get")) { + // Retrieves the Tinance2 reader key from the settings + Serial.println("Tinance2 Key: " + settings.tinance2ReaderKey); + } + + if (prefix.equals("tinance2.key.set")) { + if (wordCount == 2) { + // Sets the Tinance2 reader key in the settings + settings.tinance2ReaderKey = wordList[1]; + settings.saveSetting("t2", "rk", wordList[1], "string"); + } + } + + if (prefix.equals("tinance2.validatecardurl.get")) { + // Retrieves the Tinance2 reader key from the settings + Serial.println("Tinance2 Key: " + settings.tinance2_url_validatecard); + } + + if (prefix.equals("tinance2.validatecardurl.set")) { + if (wordCount == 2) { + // Sets the Tinance2 reader key in the settings + settings.saveSetting("t2", "vcurl", wordList[1], "string"); + Serial.println("Tinance2 Key: " + settings.tinance2_url_validatecard); + + } + } + + if (prefix.equals("tinance2.readerinfourl.get")) { + // Retrieves the Tinance2 reader key from the settings + Serial.println("Tinance2 Key: " + settings.tinance2_url_readerinfo); + } + + if (prefix.equals("tinance2.readerinfourl.set")) { + if (wordCount == 2) { + // Sets the Tinance2 reader key in the settings + settings.saveSetting("t2", "riurl", wordList[1], "string"); + Serial.println("Tinance2 Key: " + settings.tinance2_url_readerinfo); + + } + } + + if (prefix.equals("tinance2.aclsurl.get")) { + // Retrieves the Tinance2 reader key from the settings + Serial.println("Tinance2 Key: " + settings.tinance2_url_acls); + } + + if (prefix.equals("tinance2.aclsurl.set")) { + if (wordCount == 2) { + // Sets the Tinance2 reader key in the settings + settings.saveSetting("t2", "aclurl", wordList[1], "string"); + Serial.println("Tinance2 Key: " + settings.tinance2_url_acls); + + } + } + + if (prefix.equals("tinance2.readerlogurl.get")) { + // Retrieves the Tinance2 reader key from the settings + Serial.println("Tinance2 Key: " + settings.tinance2_url_log); + } + + if (prefix.equals("tinance2.readerlogurl.set")) { + if (wordCount == 2) { + // Sets the Tinance2 reader key in the settings + settings.saveSetting("t2", "rluri", wordList[1], "string"); + Serial.println("Tinance2 Key: " + settings.tinance2_url_log); + + } + } + + + if(prefix.equals("webhook.lock.url.get")) { + Serial.println("Webhook Lock URL: " + settings.webhookLockHook); + } + + if(prefix.equals("webhook.lock.url.set")) { + if (wordCount == 2) { + settings.saveSetting("wh", "lockurl", wordList[1], "string"); + Serial.println("Webhook Lock URL: " + settings.webhookLockHook); + } + } + + if(prefix.equals("webhook.lock.enable.get")) { + Serial.println("Webhook Lock Enabled: " + settings.webhookLockEnabled); + } + + if(prefix.equals("webhook.lock.enable.set")) { + if (wordCount == 2) { + settings.saveSetting("wh", "lockena", wordList[1], "bool"); + Serial.println("Webhook Lock Enabled: " + settings.webhookLockEnabled); + } + } + + if(prefix.equals("webhook.unlock.url.get")) { + Serial.println("Webhook Unlock URL: " + settings.webhookUnlockHook); + } + + if(prefix.equals("webhook.unlock.url.set")) { + if (wordCount == 2) { + settings.saveSetting("wh", "unlockurl", wordList[1], "string"); + Serial.println("Webhook Unlock URL: " + settings.webhookUnlockHook); + } + } + + if(prefix.equals("webhook.unlock.enable.get")) { + Serial.println("Webhook Unlock Enabled: " + settings.webhookUnlockEnabled); + } + + if(prefix.equals("webhook.unlock.enable.set")) { + if (wordCount == 2) { + settings.saveSetting("wh", "unlockena", wordList[1], "bool"); + Serial.println("Webhook Unlock Enabled: " + settings.webhookUnlockEnabled); + } + } // Command Validate Access - if (prefix.equals("validateAccess")) { - if (wordCount == 2) { - bool result = acl.validateAccess(String(wordList[1])); + if (prefix.equals("acl.local.validate")) { + if (wordCount == 2) { + // Validates access for a given card ID using the local ACL + bool result = acl.validateAccess(String(wordList[1])); - if (result) { - Serial.println("Access granted!"); - } - else { - Serial.println("Access denied!"); - } + if (result) { + Serial.println("Access granted!"); } - else { - Serial.println("validateAccess requires exactly 1 arguments (cardId)"); - return; + else { + Serial.println("Access denied!"); } + } } // Command Add User - if (prefix.equals("addUser")) { + if (prefix.equals("acl.local.add")) { if (wordCount == 3) { acl.addUser(wordList[1], wordList[2]); acl.saveToEEPROM(); @@ -358,7 +494,7 @@ void setup() { } } // Command Update User - if (prefix.equals("updateUser")) { + if (prefix.equals("acl.local.update")) { if (wordCount == 4) { acl.updateUser(wordList[1], wordList[2], wordList[3]); acl.saveToEEPROM(); @@ -372,7 +508,7 @@ void setup() { // Command Remove User - if (prefix.equals("removeUser")) { + if (prefix.equals("acl.local.remove")) { if (wordCount == 2) { acl.removeUser(wordList[1]); acl.saveToEEPROM(); @@ -386,7 +522,7 @@ void setup() { // Command List Uses - if (prefix.equals("listUsers")) { + if (prefix.equals("acl.local.list")) { if (wordCount == 1) { // Retrieve the ACL data using the getter function const User* aclData = acl.getACL(); @@ -457,7 +593,7 @@ void setup() { * 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 and SERIAL_DEBUG. + * @note This function assumes the availability of certain macros like TINANCE2_BACKEND, LOCAL_ACL, SERIAL_CLI and SERIAL_DEBUG. * * @note This function assumes the availability of certain variables like newDataAvailable, lastDataTime, displayDelay, cardData, bitCount, and maxReaderWaitTime. * @@ -520,7 +656,7 @@ void loop() { #endif #ifdef LOCAL_ACL - #ifdef SERIAL_ACL + #ifdef SERIAL_CLI checkSerialCommand(); #endif #endif diff --git a/src/settings.cpp b/src/settings.cpp index 597b2aa..f7e72a7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -14,9 +14,62 @@ void Settings::loadFromEEPROM() { settings_preferences.begin("t2", false); tinance2ReaderIdentifier = settings_preferences.getString("ri", "default"); tinance2ReaderKey = settings_preferences.getString("rk", "default"); + tinance2_url_validatecard = settings_preferences.getString("vcurl","https://tinance2.board.techinc.nl/accesscontrol/api/check-card-id"); + tinance2_url_readerinfo = settings_preferences.getString("riurl","https://tinance2.board.techinc.nl/accesscontrol/api/readerinfo"); + tinance2_url_acls = settings_preferences.getString("aclurl","https://tinance2.board.techinc.nl/accesscontrol/api/acls"); + tinance2_url_log = settings_preferences.getString("rluri","https://tinance2.board.techinc.nl/accesscontrol/api/readerlog"); + + + settings_preferences.end(); + + settings_preferences.begin("wh", false); + webhookLockEnabled = settings_preferences.getBool("lockena", false); + webhookLockHook = settings_preferences.getString("lockurl", ""); + webhookUnlockEnabled = settings_preferences.getBool("unlockena", false); + webhookUnlockHook = settings_preferences.getString("unlockurl", ""); settings_preferences.end(); } +void Settings::saveSetting(const String& namespaceStr, const String& key, const String& value, const String& typeStr) { + + if (typeStr == "bool") { + bool currentValue = settings_preferences.getBool(key.c_str()); + bool newValue = (value == "true"); + if (currentValue != newValue) { + settings_preferences.begin(namespaceStr.c_str(), false); + settings_preferences.putBool(key.c_str(), newValue); + settings_preferences.end(); + } + } else if (typeStr == "int") { + int currentValue = settings_preferences.getInt(key.c_str()); + int newValue = atoi(value.c_str()); + if (currentValue != newValue) { + settings_preferences.begin(namespaceStr.c_str(), false); + settings_preferences.putInt(key.c_str(), newValue); + settings_preferences.end(); + } + } else if (typeStr == "float") { + float currentValue = settings_preferences.getFloat(key.c_str()); + float newValue = atof(value.c_str()); + if (currentValue != newValue) { + settings_preferences.begin(namespaceStr.c_str(), false); + settings_preferences.putFloat(key.c_str(), newValue); + settings_preferences.end(); + } + } else if (typeStr == "string") { + String currentValue = settings_preferences.getString(key.c_str()); + if (currentValue != value) { + settings_preferences.begin(namespaceStr.c_str(), false); + settings_preferences.putString(key.c_str(), value); + settings_preferences.end(); + } + } else { + // Handle other types here if needed + } + +} + + void Settings::saveToEEPROM() { settings_preferences.begin("settings", false); settings_preferences.putBool("disableDoor", disableDoor); @@ -78,22 +131,4 @@ String Settings::getDoorMode() { return doorMode; } -void Settings::setTinance2ReaderIdentifier(String value) { - tinance2ReaderIdentifier = value; - saveToEEPROM(); - -} -String Settings::getTinance2ReaderIdentifier() { - return tinance2ReaderIdentifier; -} - -void Settings::setTinance2ReaderKey(String value){ - tinance2ReaderKey = value; - saveToEEPROM(); - -} -String Settings::getTinance2ReaderKey(){ - return tinance2ReaderKey; -} - Settings settings; \ No newline at end of file diff --git a/src/tinance2.cpp b/src/tinance2.cpp index fe70010..d69d945 100644 --- a/src/tinance2.cpp +++ b/src/tinance2.cpp @@ -17,8 +17,8 @@ HTTPClient tinance2_http; // Set the headers tinance2_http.addHeader("Content-Type", "application/json"); - tinance2_http.addHeader("X-Identifier", settings.getTinance2ReaderIdentifier()); - tinance2_http.addHeader("X-Access-Key", settings.getTinance2ReaderKey()); + tinance2_http.addHeader("X-Identifier", settings.tinance2ReaderIdentifier); + tinance2_http.addHeader("X-Access-Key", settings.tinance2ReaderKey); // Set the HTTP timeout to 5 seconds tinance2_http.setTimeout(5000);