|
2 | 2 | * webserver.cpp |
3 | 3 | * Web server for control and configuration |
4 | 4 | * |
5 | | - * TallyCCU Pro V3.6 |
| 5 | + * TallyCCU Pro V3.7 |
6 | 6 | */ |
7 | 7 |
|
8 | 8 | #include "WebServer.h" |
9 | 9 | #include "CCUBroadcast.h" |
| 10 | +#include "SafeMode.h" |
10 | 11 | #include <SdFat.h> |
11 | 12 | #include <avr/wdt.h> |
12 | 13 |
|
@@ -199,6 +200,12 @@ void WebServer::processRequests() { |
199 | 200 | void WebServer::processPOSTRequest(const char* reqLine, EthernetClient &client) { |
200 | 201 | Serial.println(F("[POST] Received")); |
201 | 202 |
|
| 203 | + // Safe mode exit |
| 204 | + if (strstr(reqLine, "POST /safemode-exit") != NULL) { |
| 205 | + handleSafeModeExit(client); |
| 206 | + return; |
| 207 | + } |
| 208 | + |
202 | 209 | // Check if savePreset |
203 | 210 | if (strstr(reqLine, "POST /savePreset") != NULL) { |
204 | 211 | handleSavePresetPOST(client); |
@@ -552,6 +559,30 @@ void WebServer::sendJSONResponse(EthernetClient &client, bool success, const cha |
552 | 559 |
|
553 | 560 | void WebServer::processGETRequest(const char* reqLine, EthernetClient &client) { |
554 | 561 |
|
| 562 | + // ============================================================ |
| 563 | + // SAFE MODE HANDLING - CHECK FIRST |
| 564 | + // ============================================================ |
| 565 | + |
| 566 | + // Safe mode status API (always available) |
| 567 | + if (strncmp(reqLine, "GET /safemode-status", 20) == 0) { |
| 568 | + handleSafeModeStatus(client); |
| 569 | + return; |
| 570 | + } |
| 571 | + |
| 572 | + // In safe mode, redirect main pages to diagnostic page |
| 573 | + if (SafeMode::isActive()) { |
| 574 | + if (strncmp(reqLine, "GET / ", 6) == 0 || |
| 575 | + strncmp(reqLine, "GET /index", 10) == 0 || |
| 576 | + strncmp(reqLine, "GET /ccu", 8) == 0) { |
| 577 | + SdUtils::serveFile(client, "safemode.html"); |
| 578 | + return; |
| 579 | + } |
| 580 | + } |
| 581 | + |
| 582 | + // ============================================================ |
| 583 | + // NORMAL REQUEST HANDLING |
| 584 | + // ============================================================ |
| 585 | + |
555 | 586 | // Reboot |
556 | 587 | if (strncmp(reqLine, "GET /reboot", 11) == 0) { |
557 | 588 | Serial.println(F("Reboot requested")); |
@@ -1042,7 +1073,8 @@ void WebServer::handleListFiles(EthernetClient &client) { |
1042 | 1073 | // Hide system files |
1043 | 1074 | if (strcmp(fileName, "index.html") == 0 || |
1044 | 1075 | strcmp(fileName, "tally.html") == 0 || |
1045 | | - strcmp(fileName, "sdcard.html") == 0) { |
| 1076 | + strcmp(fileName, "sdcard.html") == 0 || |
| 1077 | + strcmp(fileName, "safemode.html") == 0) { |
1046 | 1078 | entry.close(); |
1047 | 1079 | continue; |
1048 | 1080 | } |
@@ -1105,7 +1137,8 @@ void WebServer::handleDeleteFile(EthernetClient &client, const char* filename) { |
1105 | 1137 | // Protect system files |
1106 | 1138 | if (strcmp(filename, "index.html") == 0 || |
1107 | 1139 | strcmp(filename, "tally.html") == 0 || |
1108 | | - strcmp(filename, "sdcard.html") == 0) { |
| 1140 | + strcmp(filename, "sdcard.html") == 0 || |
| 1141 | + strcmp(filename, "safemode.html") == 0) { |
1109 | 1142 | client.println(F("{\"success\":false,\"error\":\"protected\"}")); |
1110 | 1143 | return; |
1111 | 1144 | } |
@@ -1296,6 +1329,62 @@ void WebServer::handleUploadFile(EthernetClient &client) { |
1296 | 1329 | sendJSONResponse(client, filename[0] != '\0', filename[0] != '\0' ? filename : "No file"); |
1297 | 1330 | } |
1298 | 1331 |
|
| 1332 | +// ============================================================ |
| 1333 | +// SAFE MODE HANDLERS |
| 1334 | +// ============================================================ |
| 1335 | + |
| 1336 | +void WebServer::handleSafeModeStatus(EthernetClient &client) { |
| 1337 | + // Send headers |
| 1338 | + client.println(F("HTTP/1.1 200 OK")); |
| 1339 | + client.println(F("Content-Type: application/json")); |
| 1340 | + client.println(F("Cache-Control: no-cache")); |
| 1341 | + client.println(F("Access-Control-Allow-Origin: *")); |
| 1342 | + client.println(F("Connection: close")); |
| 1343 | + client.println(); |
| 1344 | + |
| 1345 | + // Calculate free RAM |
| 1346 | + extern int __heap_start, *__brkval; |
| 1347 | + int v; |
| 1348 | + int freeRam = (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval); |
| 1349 | + |
| 1350 | + // Build JSON response |
| 1351 | + client.print(F("{")); |
| 1352 | + client.print(F("\"safeMode\":")); |
| 1353 | + client.print(SafeMode::isActive() ? F("true") : F("false")); |
| 1354 | + client.print(F(",\"resetCount\":")); |
| 1355 | + client.print(SafeMode::getResetCount()); |
| 1356 | + client.print(F(",\"resetReason\":\"")); |
| 1357 | + client.print(SafeMode::getResetReasonString()); |
| 1358 | + client.print(F("\",\"uptime\":")); |
| 1359 | + client.print(SafeMode::getUptime()); |
| 1360 | + client.print(F(",\"freeRam\":")); |
| 1361 | + client.print(freeRam); |
| 1362 | + client.print(F(",\"ip\":\"")); |
| 1363 | + client.print(NetworkManager::getLocalIP()); |
| 1364 | + client.println(F("\"}")); |
| 1365 | +} |
| 1366 | + |
| 1367 | +void WebServer::handleSafeModeExit(EthernetClient &client) { |
| 1368 | + // Send response first |
| 1369 | + client.println(F("HTTP/1.1 200 OK")); |
| 1370 | + client.println(F("Content-Type: application/json")); |
| 1371 | + client.println(F("Access-Control-Allow-Origin: *")); |
| 1372 | + client.println(F("Connection: close")); |
| 1373 | + client.println(); |
| 1374 | + client.println(F("{\"success\":true,\"message\":\"Restarting...\"}")); |
| 1375 | + |
| 1376 | + // Close connection |
| 1377 | + delay(100); |
| 1378 | + client.flush(); |
| 1379 | + client.stop(); |
| 1380 | + |
| 1381 | + // Small delay to ensure response is sent |
| 1382 | + delay(200); |
| 1383 | + |
| 1384 | + // Exit safe mode (this triggers a restart) |
| 1385 | + SafeMode::exitSafeMode(); |
| 1386 | +} |
| 1387 | + |
1299 | 1388 | // ============================================================ |
1300 | 1389 | // SSE (SERVER-SENT EVENTS) HANDLING |
1301 | 1390 | // ============================================================ |
|
0 commit comments