forked from pvtex/esp32-rfid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog.esp
249 lines (221 loc) · 6.76 KB
/
log.esp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
void extern mqttPublishEvent(JsonDocument *root);
void writeEvent(String type, String src, String desc, String data)
{
JsonDocument root;
root["type"] = type;
root["src"] = src;
root["desc"] = desc;
root["data"] = data;
root["time"] = epoch;
if (config.mqttEvents && config.mqttEnabled) // log to MQTT
{
root["cmd"] = "event";
root["hostname"] = config.deviceHostname;
mqttPublishEvent(&root);
}
else // log to file
{
File eventlog = LittleFS.open("/eventlog.json", "a");
serializeJson(root, eventlog);
eventlog.print("\n");
eventlog.close();
}
#ifdef DEBUG
Serial.println("[ " + type + " ] " + src + " | " + desc + " | " + data);
#endif
}
void writeLatest(String uid, String username, int acctype, int access = ACCESS_GRANTED)
{
JsonDocument root;
root["uid"] = uid;
root["username"] = username;
root["acctype"] = acctype;
root["access"] = access;
root["timestamp"] = epoch;
File latestlog = LittleFS.open("/latestlog.json", "a");
serializeJson(root, latestlog);
latestlog.print("\n");
latestlog.close();
}
size_t lastPos; // position counter for fast seek
#define LOGTYPE_LATESTLOG 0
#define LOGTYPE_EVENTLOG 1
#define ITEMS_PER_PAGE 10
#define FILES_PER_PAGE 10.0
#define MIN_LITTLEFS_BYTES 4096
void sendLogFile(int page, String fileName, int logFileType, AsyncWebSocketClient *client)
{
// if we are reading the first page then we reset
// the position counter
if (page == 1)
lastPos = 0;
float pages;
JsonDocument root;
if (logFileType == LOGTYPE_EVENTLOG)
root["command"] = "eventlist";
if (logFileType == LOGTYPE_LATESTLOG)
root["command"] = "latestlist";
root["page"] = page;
JsonArray items = root["list"].to<JsonArray>();
File logFile;
if (!LittleFS.exists(fileName))
{
logFile = LittleFS.open(fileName, "w");
logFile.close();
}
logFile = LittleFS.open(fileName, "r");
// move the file pointer to the last known position
logFile.seek(lastPos);
int numLines = 0;
// read in 10 lines or until EOF whatever happens first
while (logFile.available() && (numLines < ITEMS_PER_PAGE))
{
String item = String();
item = logFile.readStringUntil('\n');
items.add(item);
numLines++;
}
// remember the last position
lastPos = logFile.position();
// calculate the number of remaining pages
if (logFile.available()) // tell bootstrap footable on the client side that there are more pages to come
{
float bytesPerPageRoughly = (lastPos / page);
float totalPagesRoughly = logFile.size() / bytesPerPageRoughly;
pages = totalPagesRoughly <= page ? page + 1 : totalPagesRoughly;
}
else
pages = page; // this was the last page
logFile.close();
root["haspages"] = ceil(pages);
size_t len = measureJson(root);
AsyncWebSocketMessageBuffer *buffer = ws.makeBuffer(len);
if (buffer)
{
serializeJson(root, (char *)buffer->get(), len);
client->text(buffer);
if (logFileType == LOGTYPE_EVENTLOG)
client->text("{\"command\":\"result\",\"resultof\":\"eventlist\",\"result\": true}");
if (logFileType == LOGTYPE_LATESTLOG)
client->text("{\"command\":\"result\",\"resultof\":\"latestlist\",\"result\": true}");
}
}
void logMaintenance(String action, String filename, AsyncWebSocketClient *client)
{
#ifdef DEBUG
Serial.printf("[DEBUG] Log Maintenance Action: %s on %s\n", action.c_str(), filename.c_str());
#endif
filename = "/" + filename;
// delete a file
if (action == "delete")
{
LittleFS.remove(filename);
}
// rollover a file, i.e. rename
if (action == "rollover")
{
size_t rolloverExtension = 1;
while (LittleFS.exists(filename + "." + rolloverExtension))
rolloverExtension++;
LittleFS.rename(filename, filename + "." + rolloverExtension);
}
// split a file, i.e. create two new files of roughly the same size
// or at least as big as LittleFS free space allows
if (action == "split")
{
size_t rolloverExtension1 = 1;
while (LittleFS.exists(filename + ".split." + rolloverExtension1))
rolloverExtension1++;
size_t rolloverExtension2 = rolloverExtension1 + 1;
while (LittleFS.exists(filename + ".split." + rolloverExtension2))
rolloverExtension2++;
File logFile = LittleFS.open(filename, "r");
File newFile1 = LittleFS.open(filename + ".split." + rolloverExtension1, "w");
File newFile2 = LittleFS.open(filename + ".split." + rolloverExtension2, "w");
size_t truncatePosition = logFile.size() / 2;
logFile.seek(truncatePosition);
logFile.readStringUntil('\n');
truncatePosition = logFile.position();
logFile.seek(0);
// check if we have enough space for the split operation
if ((LittleFS.totalBytes() - LittleFS.usedBytes()) < (logFile.size() + MIN_LITTLEFS_BYTES))
{
if (client)
{
client->text("{\"command\":\"result\",\"resultof\":\"logfileMaintenance\",\"result\": false,\"message\":\"Not enough space on LittleFS Filesystem\"}");
}
}
else
{
while (logFile.available() && logFile.position() < truncatePosition)
{
String item = String();
item = logFile.readStringUntil('\n');
newFile1.println(item);
}
// read the rest
while (logFile.available())
{
String item = String();
item = logFile.readStringUntil('\n');
newFile2.println(item);
}
logFile.close();
newFile1.close();
newFile2.close();
}
}
if (client)
{
client->text("{\"command\":\"result\",\"resultof\":\"logfileMaintenance\",\"result\": true}");
}
}
void sendFileList(int page, AsyncWebSocketClient *client)
{
JsonDocument root;
root["command"] = "listfiles";
root["page"] = page;
JsonArray items = root["list"].to<JsonArray>();
size_t first = (page - 1) * FILES_PER_PAGE;
size_t last = page * FILES_PER_PAGE;
size_t numFiles = 0;
File dir = LittleFS.open("/");
File file = dir.openNextFile();
while (file)
{
String thisFileName = file.name();
if ((thisFileName.indexOf("latestlog") >= 0) || (thisFileName.indexOf("eventlog") >= 0)) // for the time being we just check filenames
{
if (numFiles >= first && numFiles < last)
{
JsonObject item = items.add<JsonObject>();
item["filename"] = thisFileName;
item["filesize"] = file.size();
} // first, last
numFiles++;
} // isFile
file = dir.openNextFile();
}
float pages = numFiles / FILES_PER_PAGE;
root["haspages"] = ceil(pages);
size_t len = measureJson(root);
AsyncWebSocketMessageBuffer *buffer = ws.makeBuffer(len);
if (buffer)
{
serializeJson(root, (char *)buffer->get(), len);
client->text(buffer);
client->text("{\"command\":\"result\",\"resultof\":\"listfiles\",\"result\": true}");
}
}
void sendEventLog(int page, String fileName, AsyncWebSocketClient *client)
{
if (fileName.length() == 0)
fileName = "/eventlog.json";
sendLogFile(page, fileName, LOGTYPE_EVENTLOG, client);
}
void sendLatestLog(int page, String fileName, AsyncWebSocketClient *client)
{
if (fileName.length() == 0)
fileName = "/latestlog.json";
sendLogFile(page, fileName, LOGTYPE_LATESTLOG, client);
}