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);