diff --git a/include/utils/FileUtils.h b/include/utils/FileUtils.h index 6ae0545e..1c4e8918 100644 --- a/include/utils/FileUtils.h +++ b/include/utils/FileUtils.h @@ -13,4 +13,6 @@ extern bool cutFile(const String& src, const String& dst); extern size_t countLines(const String filename); void removeFile(const String& filename); void cleanDirectory(String path); +void saveDataDB(String id, String data); +String readDataDB(String id); extern void onFlashWrite(); \ No newline at end of file diff --git a/src/StandWebServer.cpp b/src/StandWebServer.cpp index a6afcf8e..b1abe6ea 100644 --- a/src/StandWebServer.cpp +++ b/src/StandWebServer.cpp @@ -43,10 +43,6 @@ void standWebServerInit() { HTTP.send(200, "text/plain", "ok"); }); - HTTP.on("/log.txt", HTTP_GET, []() { - HTTP.send(200, "text/plain", readFile(F("log.txt"), 20000)); - }); - // Добавляем функцию Update для перезаписи прошивки по WiFi при 1М(256K FileFS) и выше // httpUpdater.setup(&HTTP); // Запускаем HTTP сервер @@ -130,6 +126,8 @@ String getContentType(String filename) { return "text/html"; else if (filename.endsWith(".html")) return "text/html"; + else if (filename.endsWith(".txt")) + return "text/plain"; else if (filename.endsWith(".json")) return "application/json"; else if (filename.endsWith(".css")) diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 409241cb..64616b44 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -135,7 +135,8 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) } //команда очистки всех логов esp// if (headerStr == "/clean|") { - cleanDirectory("logs"); + cleanDirectory("lg"); + cleanDirectory("db"); } //Прием сообщений cotrol ============================================================================== diff --git a/src/modules/virtual/Logging/Loging.cpp b/src/modules/virtual/Logging/Loging.cpp index bf34f1ce..8245ab24 100644 --- a/src/modules/virtual/Logging/Loging.cpp +++ b/src/modules/virtual/Logging/Loging.cpp @@ -2,15 +2,12 @@ #include "classes/IoTItem.h" #include "NTP.h" -//раскомментировать если нужна цельная выгрузка графиков -#define SOLID_UPLOADING - class Loging : public IoTItem { private: String logid; String id; int points; - String fileName = ""; + int interval; bool firstTime = true; @@ -27,58 +24,76 @@ class Loging : public IoTItem { } void doByInterval() { + //если объект логгирования не был создан if (!isItemExist(logid)) { - SerialPrint("E", "Loging " + id, F("logging value not exist")); + SerialPrint("E", F("Loging"), "'" + id + "' loging object not exist"); return; } - String value = getItemValue(logid); - int lines = 0; - //если задано не правильное logid величины для логгирования - if (value == "") { - SerialPrint("E", "Loging " + id, F("logging value empty")); - return; - } else { - //если время было получено из интернета - if (isTimeSynch) { - // regEvent(value, "Loging"); - String logData = String(unixTimeShort) + " " + value; - //если зашли сюда первый раз то создаем файл с именем id-timestamp - if (firstTime) { - firstTime = false; - createFileWithIdDatatimeName(logData); - //если 2 ой раз и последующие разы - } else { - lines = countLines(fileName); - if (lines <= points) { - addFileLn(fileName, logData); - } else { - createFileWithIdDatatimeName(logData); - } - } - SerialPrint("i", "Loging " + id, "loging in file (" + String(lines) + ") http://" + WiFi.localIP().toString() + fileName); - } else { - SerialPrint("E", "Loging " + id, F("Сant loging - time not synchronized")); - } + String value = getItemValue(logid); + //если значение логгирования пустое + if (value == "") { + SerialPrint("E", F("Loging"), "'" + id + "' loging value is empty"); + return; + } + + //если время не было получено из интернета + if (!isTimeSynch) { + SerialPrint("E", F("Loging"), "'" + id + "' Сant loging - time not synchronized"); + return; + } + + int lines = 0; + String filePath = ""; + + // regEvent(value, F("Loging")); + + String logData = String(unixTimeShort) + " " + value; + + //прочитаем путь к файлу последнего сохранения + filePath = readDataDB(id); + //если данные о файле отсутствуют, создадим новый + if (filePath == "failed") { + SerialPrint("E", F("Loging"), "'" + id + "' file path not found"); + createNewFileWithData(logData); + return; + } + + //считаем количество строк + lines = countLines(filePath); + SerialPrint("i", F("Loging"), "'" + id + "' " + String(lines) + " lines found in file"); + + //если количество строк до заданной величины + if (lines <= points) { + //просто добавим в существующий файл новые данные + addNewDataToExistingFile(filePath, logData); + //если больше создадим следующий файл + } else { + createNewFileWithData(logData); } } - void createFileWithIdDatatimeName(String &logData) { - fileName = "/logs/" + id + "-" + String(unixTimeShort) + ".txt"; - addFileLn(fileName, logData); - SerialPrint("i", "Loging " + id, "file created http://" + WiFi.localIP().toString() + fileName); + void createNewFileWithData(String &logData) { + String filePath = "/lg/" + id + "-" + String(unixTimeShort) + ".txt"; //создадим путь + addFileLn(filePath, logData); //запишем файл и данные в него + saveDataDB(id, filePath); //запишем путь к файлу в базу данных + SerialPrint("i", F("Loging"), "'" + id + "' file created http://" + WiFi.localIP().toString() + filePath); + } + + void addNewDataToExistingFile(String &filePath, String &logData) { + addFileLn(filePath, logData); + SerialPrint("i", F("Loging"), "'" + id + "' loging in file http://" + WiFi.localIP().toString() + filePath); } void sendChart() { - SerialPrint("I", "Loging " + id, "----------------------------"); + SerialPrint("i", F("Loging"), "'" + id + "'----------------------------"); String reqUnixTimeStr = "26.08.2022"; //нужно получить эту дату из окна ввода под графиком. unsigned long reqUnixTime = strDateToUnix(reqUnixTimeStr); - String directory = "logs"; - SerialPrint("I", "Loging " + id, "in directory '" + directory + "' files:"); + String directory = "lg"; + SerialPrint("i", F("Loging"), "'" + id + "' in directory '" + directory + "' files:"); auto dir = FileFS.openDir(directory); String oneSingleJson; - int maxCount = 0; int i = 0; while (dir.next()) { @@ -90,54 +105,17 @@ class Loging : public IoTItem { if (idInFileName == id) { //выбираем только те файлы которые входят в выбранные пользователем сутки if (fileUnixTime > reqUnixTime && fileUnixTime < reqUnixTime + 86400) { - SerialPrint("I", "Loging " + id, "matching file found '" + fname + "'"); -#ifdef SOLID_UPLOADING - //если активированна выгрузка целеком - createOneSingleJson(oneSingleJson, "/logs/" + fname, maxCount, i); -#else + SerialPrint("i", F("Loging"), "'" + id + "' matching file found '" + fname + "'"); //выгрузка по частям, по одному файлу - publishJsonPartly("/logs/" + fname, calculateMaxCount(), i); -#endif + publishJsonPartly("/lg/" + fname, calculateMaxCount(), i); } } } else { - SerialPrint("i", "Loging " + id, "file '" + fname + "' not used, deleted"); + SerialPrint("i", F("Loging"), "'" + id + "' file '" + fname + "' not used, deleted"); removeFile(directory + "/" + fname); } } -#ifdef SOLID_UPLOADING - publishJson(oneSingleJson, maxCount); -#endif - SerialPrint("I", "Loging " + id, "--------------'" + String(i) + "'--------------"); - } - - void createOneSingleJson(String &oneSingleJson, String file, int &maxCount, int &i) { - File configFile = FileFS.open(file, "r"); - if (!configFile) { - return; - } - configFile.seek(0, SeekSet); - String buf = "{}"; - String unix_time; - String value; - unsigned int psn; - unsigned int sz = configFile.size(); - do { - maxCount++; - i++; - psn = configFile.position(); - String line = configFile.readStringUntil('\n'); - unix_time = selectToMarker(line, " "); - jsonWriteInt(buf, "x", unix_time.toInt() + START_DATETIME); - value = deleteBeforeDelimiter(line, " "); - jsonWriteFloat(buf, "y1", value.toFloat()); - if (unix_time != "" || value != "") { - oneSingleJson += buf + ","; - } - - } while (psn < sz); - - configFile.close(); + SerialPrint("i", F("Loging"), "'" + id + "'--------------'" + String(i) + "'--------------"); } void publishJsonPartly(String file, int maxCount, int &i) { @@ -166,17 +144,16 @@ class Loging : public IoTItem { } while (psn < sz); configFile.close(); - publishJson(dividedJson, maxCount); } void publishJson(String &oneSingleJson, int &maxCount) { oneSingleJson = "{\"maxCount\":" + String(maxCount) + ",\"status\":[" + oneSingleJson + "]}"; oneSingleJson.replace("},]}", "}]}"); - // SerialPrint("i", "Loging " + id, "publish chart, maxCount: '" + String(maxCount) + "'"); publishChart(id, oneSingleJson); } + //примерный подсчет максимального количества точек int calculateMaxCount() { return 86400 / interval; } @@ -189,3 +166,33 @@ void *getAPI_Loging(String subtype, String param) { return nullptr; } } + +//то что не пригодилось но пригодится потом может быть +// void createOneSingleJson(String &oneSingleJson, String file, int &maxCount, int &i) { +// File configFile = FileFS.open(file, "r"); +// if (!configFile) { +// return; +// } +// configFile.seek(0, SeekSet); +// String buf = "{}"; +// String unix_time; +// String value; +// unsigned int psn; +// unsigned int sz = configFile.size(); +// do { +// maxCount++; +// i++; +// psn = configFile.position(); +// String line = configFile.readStringUntil('\n'); +// unix_time = selectToMarker(line, " "); +// jsonWriteInt(buf, "x", unix_time.toInt() + START_DATETIME); +// value = deleteBeforeDelimiter(line, " "); +// jsonWriteFloat(buf, "y1", value.toFloat()); +// if (unix_time != "" || value != "") { +// oneSingleJson += buf + ","; +// } +// +// } while (psn < sz); +// +// configFile.close(); +// } diff --git a/src/utils/FileUtils.cpp b/src/utils/FileUtils.cpp index e91b31f8..e9c8b3b0 100644 --- a/src/utils/FileUtils.cpp +++ b/src/utils/FileUtils.cpp @@ -201,8 +201,19 @@ void cleanDirectory(String path) { onFlashWrite(); } +void saveDataDB(String id, String data) { + String path = "/db/" + id + ".txt"; + removeFile(path); + addFileLn(path, data); +} + +String readDataDB(String id) { + String path = "/db/" + id + ".txt"; + return readFile(path, 2000); +} + //счетчик количества записей на флешь за сеанс void onFlashWrite() { flashWriteNumber++; - SerialPrint(F("->"), F("FS"), F("write data on flash")); + // SerialPrint(F("->"), F("FS"), F("write data on flash")); } \ No newline at end of file diff --git a/src/utils/SerialPrint.cpp b/src/utils/SerialPrint.cpp index 071ecead..1c196e8a 100644 --- a/src/utils/SerialPrint.cpp +++ b/src/utils/SerialPrint.cpp @@ -6,6 +6,7 @@ void SerialPrint(String errorLevel, String module, String msg) { tosend = prettyMillis(millis()); + // if (module == "Loging") { tosend = tosend + " [" + errorLevel + "] [" + module + "] " + msg; Serial.println(tosend); @@ -14,4 +15,5 @@ void SerialPrint(String errorLevel, String module, String msg) { standWebSocket.broadcastTXT("/log|" + tosend); } } + //} } \ No newline at end of file