From b63d163432cdf18c88cba570db3b61ff1d66a2bc Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Thu, 25 Aug 2022 00:45:17 +0200 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data_svelte/scenario.txt | 0 include/Const.h | 2 ++ include/Global.h | 2 ++ include/MqttClient.h | 3 ++ include/utils/FileUtils.h | 2 ++ src/Global.cpp | 2 ++ src/MqttClient.cpp | 49 +++++++++++++++++++++++++ src/NTP.cpp | 1 + src/classes/IoTScenario.cpp | 9 +++-- src/modules/virtual/Logging/Loging.cpp | 50 ++++++++++++++++++++++---- src/utils/FileUtils.cpp | 31 ++++++++++++++++ 11 files changed, 140 insertions(+), 11 deletions(-) delete mode 100644 data_svelte/scenario.txt diff --git a/data_svelte/scenario.txt b/data_svelte/scenario.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/include/Const.h b/include/Const.h index ab437408..913b6635 100644 --- a/include/Const.h +++ b/include/Const.h @@ -35,6 +35,8 @@ #define USE_LITTLEFS false #endif +#define START_DATETIME 1640995200 // 01.01.2022 00:00:00 константа для сокрацения unix time + #define MIN_DATETIME 1575158400 #define LEAP_YEAR(Y) (((1970 + Y) > 0) && !((1970 + Y) % 4) && (((1970 + Y) % 100) || !((1970 + Y) % 400))) diff --git a/include/Global.h b/include/Global.h index 6eecf0f8..6c873eb6 100644 --- a/include/Global.h +++ b/include/Global.h @@ -130,6 +130,8 @@ struct Time_t { }; extern unsigned long unixTime; +extern unsigned long unixTimeShort; + extern bool isTimeSynch; extern Time_t _time_local; extern Time_t _time_utc; diff --git a/include/MqttClient.h b/include/MqttClient.h index df8c6119..7009a6db 100644 --- a/include/MqttClient.h +++ b/include/MqttClient.h @@ -31,6 +31,9 @@ void publishState(); void mqttCallback(char* topic, uint8_t* payload, size_t length); void handleMqttStatus(bool send); void handleMqttStatus(bool send, int state); +void sendAllFilesToMQTT(); +void sendLogData(String file, String topic); + const String getStateStr(int e); void mqttUptimeCalc(); diff --git a/include/utils/FileUtils.h b/include/utils/FileUtils.h index 6d51ad15..2d719c3b 100644 --- a/include/utils/FileUtils.h +++ b/include/utils/FileUtils.h @@ -10,4 +10,6 @@ extern const String addFileLn(const String& filename, const String& str); extern const String readFile(const String& filename, size_t max_size); extern const String filepath(const String& filename); extern bool cutFile(const String& src, const String& dst); +extern size_t countLines(const String filename); +void removeFile(const String& filename); extern void onFlashWrite(); \ No newline at end of file diff --git a/src/Global.cpp b/src/Global.cpp index 931123f2..f1ec01b7 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -66,6 +66,8 @@ String mqttRootDevice = ""; // Time unsigned long unixTime = 0; +unsigned long unixTimeShort = 0; + bool isTimeSynch = false; Time_t _time_local; Time_t _time_utc; diff --git a/src/MqttClient.cpp b/src/MqttClient.cpp index 13dfd9fd..02697985 100644 --- a/src/MqttClient.cpp +++ b/src/MqttClient.cpp @@ -133,6 +133,9 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) { SerialPrint("i", F("MQTT"), F("Full update")); publishWidgets(); publishState(); + + sendAllFilesToMQTT(); + #ifdef GATE_MODE publishTimes(); #endif @@ -308,6 +311,52 @@ void handleMqttStatus(bool send, int state) { if (!send) standWebSocket.broadcastTXT(errorsHeapJson); } +// log-20384820.txt +void sendAllFilesToMQTT() { + String directory = "logs"; + SerialPrint("I", "Loging", "in directory '" + directory + "' files:"); + auto dir = FileFS.openDir(directory); + while (dir.next()) { + String fname = dir.fileName(); + String id = selectToMarker(fname, "-"); + SerialPrint("I", "Loging", fname); + sendLogData("/logs/" + fname, id); + } +} + +void sendLogData(String file, String topic) { + File configFile = FileFS.open(file, "r"); + if (!configFile) { + return; + } + configFile.seek(0, SeekSet); + int i = 0; + String buf = "{}"; + String json_array; + String unix_time; + String value; + unsigned int psn; + unsigned int sz = configFile.size(); + do { + 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 != "") { + json_array += buf + ","; + } + } while (psn < sz); + + configFile.close(); + + json_array = "{\"status\":[" + json_array + "]}"; + json_array.replace("},]}", "}]}"); + publishChart(topic, json_array); +} + const String getStateStr(int e) { switch (e) { case -4: //Нет ответа от сервера diff --git a/src/NTP.cpp b/src/NTP.cpp index 296f2b2e..02cea48e 100644 --- a/src/NTP.cpp +++ b/src/NTP.cpp @@ -9,6 +9,7 @@ void ntpInit() { ts.add( TIME, 1000, [&](void*) { unixTime = getSystemTime(); + unixTimeShort = unixTime - START_DATETIME; if (unixTime < MIN_DATETIME) { isTimeSynch = false; // SerialPrint("E", "NTP", "Time not synched"); diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index 33eb84e0..29e9161a 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -930,15 +930,15 @@ void IoTScenario::loadScenario(String fileName) { // посимвольно с File myfile = seekFile(fileName); if (myfile.available()) { strFromFile = new String(""); - + String strFromF = myfile.readString(); Serial.println(strFromF); jsonRead(strFromF, "scen", *strFromFile, true); myfile.close(); - //Serial.println(*strFromFile); + // Serial.println(*strFromFile); - if (strFromFile->length()) { + if (strFromFile->length()) { getNextToken(); while (strIterator < strFromFile->length() - 1) { // Serial.printf("-%c", LastChar); @@ -957,7 +957,6 @@ void IoTScenario::loadScenario(String fileName) { // посимвольно с } } - delete strFromFile; strIterator = 0; } else { @@ -968,7 +967,7 @@ void IoTScenario::loadScenario(String fileName) { // посимвольно с void IoTScenario::ExecScenario(String eventIdName) { // запускаем поочереди все корневые элементы выражений в сценарии, ожидаемо - это IFы // eventIdName - ID элемента для которого выполняем сценарий, т.е. игнорируем любые проверки, если нет такого ID в условиях isIotScenException = false; - Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size()); + // Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size()); for (unsigned int i = 0; i < ScenarioElements.size(); i++) { if (ScenarioElements[i] && ScenarioElements[i]->hasEventIdName(eventIdName)) ScenarioElements[i]->exec(); // else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str()); diff --git a/src/modules/virtual/Logging/Loging.cpp b/src/modules/virtual/Logging/Loging.cpp index daeee73b..cdddffc9 100644 --- a/src/modules/virtual/Logging/Loging.cpp +++ b/src/modules/virtual/Logging/Loging.cpp @@ -4,29 +4,67 @@ class Loging : public IoTItem { private: String logval; + String id; + String fileName = ""; public: Loging(String parameters) : IoTItem(parameters) { jsonRead(parameters, F("logid"), logval); + jsonRead(parameters, F("id"), id); } void doByInterval() { String value = getItemValue(logval); + size_t lines = 0; + //если задано не правильное logid величины для логгирования if (value == "") { - SerialPrint("E", F("Logging"), F("no value set")); + SerialPrint("E", F("Loging"), F("no value set")); } else { + //если время было получено из интернета if (isTimeSynch) { - regEvent(value, "Logging"); - String logData = String(unixTime) + " " + value; - addFileLn("/log.txt", logData); + regEvent(value, "Loging"); + String logData = String(unixTimeShort) + " " + value; + + static bool firstTime = true; + //если зашли сюда первый раз то создаем файл с именем id-timestamp + if (firstTime) { + firstTime = false; + createFileWithIdDatatimeName(logData); + //если 2 ой раз и последующие разы + } else { + lines = countLines(fileName); + if (lines <= 255) { + addFileLn(fileName, logData); + } else { + createFileWithIdDatatimeName(logData); + } + } + SerialPrint("i", F("Loging"), "loging in file (" + String(lines) + ") http://" + WiFi.localIP().toString() + fileName); + } else { - SerialPrint("E", F("Logging"), F("cant logging - no time Synch")); + SerialPrint("E", F("Loging"), F("Сant loging - time not synchronized")); } } } + + void createFileWithIdDatatimeName(String &logData) { + fileName = "/logs/" + id + "-" + String(unixTimeShort) + ".txt"; + addFileLn(fileName, logData); + SerialPrint("i", F("Loging"), "file created http://" + WiFi.localIP().toString() + fileName); + } + + void cleanLog() { + String directory = "logs/" + id; + auto dir = FileFS.openDir(directory); + while (dir.next()) { + String fname = dir.fileName(); + removeFile(directory + "/" + fname); + SerialPrint("I", "Loging", fname + " deleted"); + } + } }; -void* getAPI_Loging(String subtype, String param) { +void *getAPI_Loging(String subtype, String param) { if (subtype == F("Loging")) { return new Loging(param); } else { diff --git a/src/utils/FileUtils.cpp b/src/utils/FileUtils.cpp index e5a13450..3c73d4ac 100644 --- a/src/utils/FileUtils.cpp +++ b/src/utils/FileUtils.cpp @@ -158,8 +158,39 @@ bool cutFile(const String& src, const String& dst) { return true; } +//функция считает количество строк в файле +size_t countLines(const String filename) { + size_t cnt = -1; + String path = filepath(filename); + auto file = FileFS.open(path, "r"); + if (!file) { + return cnt; + } + file.seek(0, SeekSet); + size_t size = file.size(); + size_t psn; + do { + cnt++; + file.readStringUntil('\n'); + psn = file.position(); + } while (psn < size); + file.close(); + return cnt; +} +//удаляем файл +void removeFile(const String& filename) { + String path = filepath(filename); + if (FileFS.exists(path)) { + if (!FileFS.remove(path)) { + SerialPrint("I", "Files", "remove " + path); + } + } else { + SerialPrint("E", "Files", "not exist" + path); + } +} +//счетчик количества записей на флешь за сеанс void onFlashWrite() { flashWriteNumber++; SerialPrint(F("->"), F("FS"), F("write data on flash"));