| 2 |
raymond |
1 |
#pragma once
|
|
|
2 |
#include <Arduino.h>
|
|
|
3 |
#include <ArduinoJson.h>
|
|
|
4 |
#include <FS.h>
|
|
|
5 |
#include <LittleFS.h>
|
|
|
6 |
|
|
|
7 |
class TableManager {
|
|
|
8 |
public:
|
|
|
9 |
TableManager(const char* filename) : filename(filename) {
|
|
|
10 |
// Initialize as empty JSON array (will store our records)
|
|
|
11 |
document.to<JsonArray>();
|
|
|
12 |
}
|
|
|
13 |
|
|
|
14 |
// Loads JSON data from LittleFS file into memory
|
|
|
15 |
bool loadTable() {
|
|
|
16 |
File file = LittleFS.open(filename, FILE_READ);
|
|
|
17 |
if (!file) {
|
|
|
18 |
// File doesn't exist - initialize empty table (not an error)
|
|
|
19 |
document.to<JsonArray>();
|
|
|
20 |
return true;
|
|
|
21 |
}
|
|
|
22 |
|
|
|
23 |
document.clear();
|
|
|
24 |
DeserializationError error = deserializeJson(document, file);
|
|
|
25 |
file.close();
|
|
|
26 |
|
|
|
27 |
if (error) {
|
|
|
28 |
Serial.print(F("deserializeJson() failed: "));
|
|
|
29 |
Serial.println(error.f_str());
|
|
|
30 |
return false;
|
|
|
31 |
}
|
|
|
32 |
return true;
|
|
|
33 |
}
|
|
|
34 |
|
|
|
35 |
// Checks if a record with same uniqueKey value already exists
|
|
|
36 |
bool isDuplicate(JsonObject& newRecord, const char* uniqueKey) {
|
|
|
37 |
JsonArray table = document.as<JsonArray>();
|
|
|
38 |
if (newRecord[uniqueKey].is<const char*>()) {
|
|
|
39 |
const char* idValue = newRecord[uniqueKey];
|
|
|
40 |
for (JsonObject record : table) {
|
|
|
41 |
if (record[uniqueKey].is<const char*>() &&
|
|
|
42 |
strcmp(record[uniqueKey].as<const char*>(), idValue) == 0) {
|
|
|
43 |
return true;
|
|
|
44 |
}
|
|
|
45 |
}
|
|
|
46 |
}
|
|
|
47 |
return false;
|
|
|
48 |
}
|
|
|
49 |
|
|
|
50 |
// Adds new record to the table with optional duplicate check
|
|
|
51 |
bool addRecord(JsonObject newRecord, const char* uniqueKey = nullptr) {
|
|
|
52 |
JsonArray table = document.as<JsonArray>();
|
|
|
53 |
|
|
|
54 |
// Skip duplicate check if uniqueKey not provided
|
|
|
55 |
if (uniqueKey && isDuplicate(newRecord, uniqueKey)) {
|
|
|
56 |
return false;
|
|
|
57 |
}
|
|
|
58 |
|
|
|
59 |
if (table.add(newRecord))
|
|
|
60 |
return saveTable();
|
|
|
61 |
return false;
|
|
|
62 |
}
|
|
|
63 |
|
|
|
64 |
// Version that checks multiple unique keys
|
|
|
65 |
bool addRecord(JsonObject newRecord, const char* uniqueKeys[], int numUniqueKeys) {
|
|
|
66 |
JsonArray table = document.as<JsonArray>();
|
|
|
67 |
|
|
|
68 |
// Check all specified unique keys for duplicates
|
|
|
69 |
for (int i = 0; i < numUniqueKeys; i++) {
|
|
|
70 |
if (isDuplicate(newRecord, uniqueKeys[i]))
|
|
|
71 |
return false;
|
|
|
72 |
}
|
|
|
73 |
|
|
|
74 |
if (table.add(newRecord))
|
|
|
75 |
return saveTable();
|
|
|
76 |
return false;
|
|
|
77 |
}
|
|
|
78 |
|
|
|
79 |
// Delete existing record matching key-value pair
|
|
|
80 |
bool deleteRecord(const char* key, const char* value) {
|
|
|
81 |
JsonArray table = document.as<JsonArray>();
|
|
|
82 |
|
|
|
83 |
// Iterate through the array to find the matching record
|
|
|
84 |
for (size_t i = 0; i < table.size(); i++) {
|
|
|
85 |
JsonObject record = table[i].as<JsonObject>();
|
|
|
86 |
if (record[key] == value) {
|
|
|
87 |
table.remove(i);
|
|
|
88 |
return saveTable();
|
|
|
89 |
}
|
|
|
90 |
}
|
|
|
91 |
return false; // Record not found
|
|
|
92 |
}
|
|
|
93 |
|
|
|
94 |
// Finds first record matching key-value pair
|
|
|
95 |
JsonObject findRecord(const char* key, const char* value) {
|
|
|
96 |
JsonArray table = document.as<JsonArray>();
|
|
|
97 |
for (JsonObject record : table) {
|
|
|
98 |
if (strcmp(record[key].as<const char*>(), value) == 0) {
|
|
|
99 |
return record;
|
|
|
100 |
}
|
|
|
101 |
}
|
|
|
102 |
return JsonObject();
|
|
|
103 |
}
|
|
|
104 |
|
|
|
105 |
JsonArray getUsers() {
|
|
|
106 |
loadTable();
|
|
|
107 |
return document.as<JsonArray>();
|
|
|
108 |
}
|
|
|
109 |
|
|
|
110 |
// Persists current in-memory table to LittleFS
|
|
|
111 |
bool saveTable() {
|
|
|
112 |
File file = LittleFS.open(filename, FILE_WRITE);
|
|
|
113 |
if (!file) return false;
|
|
|
114 |
|
|
|
115 |
bool success = serializeJsonPretty(document, file) > 0;
|
|
|
116 |
file.close();
|
|
|
117 |
return success;
|
|
|
118 |
}
|
|
|
119 |
|
|
|
120 |
// Debug helper - prints current table to Serial
|
|
|
121 |
void printTable() {
|
|
|
122 |
serializeJsonPretty(document, Serial);
|
|
|
123 |
Serial.println();
|
|
|
124 |
}
|
|
|
125 |
|
|
|
126 |
private:
|
|
|
127 |
const char* filename; // LittleFS filename for persistence
|
|
|
128 |
JsonDocument document; // In-memory JSON data storage
|
|
|
129 |
};
|