From 31b83e8380fb1588bf35421d3c42fa0a88c683c2 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Sun, 2 Oct 2022 01:06:25 +0200 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=B1=D0=B0=D0=B3=20=D0=B3=D1=80=D0=B0=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D0=BE=D0=B2,=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=B5=D1=82=20=D1=80=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data_svelte/build/bundle.css.gz | Bin 5492 -> 5492 bytes data_svelte/build/bundle.js.gz | Bin 47635 -> 47654 bytes data_svelte/index.html | 6 +- data_svelte/items.json | 3 +- include/Const.h | 2 +- include/MqttClient.h | 1 + include/UpgradeFirm.h | 1 + include/WsServer.h | 1 + include/utils/FileUtils.h | 2 + src/Main.cpp | 43 ++++++----- src/MqttClient.cpp | 16 ++++ src/UpgradeFirm.cpp | 2 + src/WsServer.cpp | 43 +++++++++++ src/modules/virtual/Loging/Loging.cpp | 63 +--------------- .../virtual/LogingDaily/LogingDaily.cpp | 70 +++--------------- src/modules/virtual/LogingDaily/modinfo.json | 6 +- src/utils/FileUtils.cpp | 27 +++++++ 17 files changed, 137 insertions(+), 149 deletions(-) diff --git a/data_svelte/build/bundle.css.gz b/data_svelte/build/bundle.css.gz index c75258277910bb03847a6491bc23c27ff1246b0c..54bc75e4deb475a7eea828df842ae7efa27f855e 100644 GIT binary patch delta 16 XcmeyO^+k(azMF%?@VLcB_FPc_Gr$FC delta 16 XcmeyO^+k(azMF%?Bh`E(d#)$|G7tqE diff --git a/data_svelte/build/bundle.js.gz b/data_svelte/build/bundle.js.gz index 4baeb77d209e55eed769483351783b7ef51dd93d..271fc7959866aac673e324edc02854e7c631c83a 100644 GIT binary patch delta 15050 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 diff --git a/data_svelte/index.html b/data_svelte/index.html index 3366770d..b4164705 100644 --- a/data_svelte/index.html +++ b/data_svelte/index.html @@ -4,12 +4,12 @@ - IoT Manager 4.3.9 + IoT Manager 4.4.0 - + - + diff --git a/data_svelte/items.json b/data_svelte/items.json index dfc47a9c..9ac762bd 100644 --- a/data_svelte/items.json +++ b/data_svelte/items.json @@ -30,7 +30,8 @@ "num": 2, "int": 1, "logid": "t", - "points": 365 + "points": 365, + "test": 0 }, { "name": "3. Таймер", diff --git a/include/Const.h b/include/Const.h index ff961eba..bb82f3e8 100644 --- a/include/Const.h +++ b/include/Const.h @@ -1,7 +1,7 @@ #pragma once //Версия прошивки -#define FIRMWARE_VERSION 429 +#define FIRMWARE_VERSION 430 #ifdef esp8266_4mb #define FIRMWARE_NAME "esp8266_4mb" diff --git a/include/MqttClient.h b/include/MqttClient.h index 707fd4f0..02dce50e 100644 --- a/include/MqttClient.h +++ b/include/MqttClient.h @@ -24,6 +24,7 @@ boolean publishStatusMqtt(const String& topic, const String& data); boolean publishEvent(const String& topic, const String& data); boolean publishInfo(const String& topic, const String& data); boolean publishAnyJsonKey(const String& topic, const String& key, const String& data); +bool publishChartFileToMqtt(String path, String id, int maxCount); void publishWidgets(); void publishState(); diff --git a/include/UpgradeFirm.h b/include/UpgradeFirm.h index 25dd2140..0e669984 100644 --- a/include/UpgradeFirm.h +++ b/include/UpgradeFirm.h @@ -12,6 +12,7 @@ struct updateFirm { String configJson; String layoutJson; String scenarioTxt; + String chartsData; }; extern void upgradeInit(); diff --git a/include/WsServer.h b/include/WsServer.h index d09f671b..cc4116ef 100644 --- a/include/WsServer.h +++ b/include/WsServer.h @@ -18,6 +18,7 @@ void publishStatusWs(const String& topic, const String& data); void publishChartWs(int num, String& path); void periodicWsSend(); void sendStringToWs(const String& msg, uint8_t num, String name); +void publishChartToWs(String filename, int num, size_t frameSize, int maxCount, String id); // void sendMark(const char* filename, const char* mark, uint8_t num); // void sendFileToWs3(const String& filename, uint8_t num); diff --git a/include/utils/FileUtils.h b/include/utils/FileUtils.h index 24c203af..335e4e2c 100644 --- a/include/utils/FileUtils.h +++ b/include/utils/FileUtils.h @@ -24,6 +24,8 @@ extern void onFlashWrite(); String getFilesList8266(String& directory); String getFilesList32(String& directory); String getFilesList(String& directory); +String createDataBaseSting(); +void writeDataBaseSting(String input); struct IoTFSInfo { size_t totalBytes; diff --git a/src/Main.cpp b/src/Main.cpp index 6a24c9a1..8d4dede3 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -80,28 +80,6 @@ void setup() { // test Serial.println("-------test start--------"); - - // File dir = FileFS.open("/", "r"); - // String out; - // printDirectory(dir, out); - // Serial.println(out); - - //=======проверка очереди из структур================= - - // myDB = new IoTDB; - // QueueItems myItem; - // myItem.myword = "word1"; - // myDB->push(myItem); - // myItem.myword = "word2"; - // myDB->push(myItem); - // myItem.myword = "word3"; - // myDB->push(myItem); - // Serial.println(myDB->front().myword); - // Serial.println(myDB->front().myword); - // Serial.println(myDB->front().myword); - - // Serial.println(FileList("lg")); - Serial.println("--------test end---------"); // симуляция добавления внешних событий @@ -191,3 +169,24 @@ void loop() { // } //} } + +// File dir = FileFS.open("/", "r"); +// String out; +// printDirectory(dir, out); +// Serial.println(out); + +//=======проверка очереди из структур================= + +// myDB = new IoTDB; +// QueueItems myItem; +// myItem.myword = "word1"; +// myDB->push(myItem); +// myItem.myword = "word2"; +// myDB->push(myItem); +// myItem.myword = "word3"; +// myDB->push(myItem); +// Serial.println(myDB->front().myword); +// Serial.println(myDB->front().myword); +// Serial.println(myDB->front().myword); + +// Serial.println(FileList("lg")); diff --git a/src/MqttClient.cpp b/src/MqttClient.cpp index 8d9bfa88..89a2ba7e 100644 --- a/src/MqttClient.cpp +++ b/src/MqttClient.cpp @@ -305,6 +305,22 @@ void publishState() { } } +bool publishChartFileToMqtt(String path, String id, int maxCount) { + File configFile = FileFS.open(path, FILE_READ); + if (!configFile) { + SerialPrint("E", F("Loging"), path + " file reading error, json not created, return"); + return false; + } + String oneSingleJson = configFile.readString(); + configFile.close(); + String topic = mqttRootDevice + "/" + id; + oneSingleJson = "{\"maxCount\":" + String(maxCount) + ",\"topic\":\"" + topic + "\",\"status\":[" + oneSingleJson + "]}"; + oneSingleJson.replace("},]}", "}]}"); + SerialPrint("i", "Loging", "json size: " + String(oneSingleJson.length())); + publishChartMqtt(id, oneSingleJson); + return true; +} + void handleMqttStatus(bool send) { String stateStr = getStateStr(mqtt.state()); // Serial.println(stateStr); diff --git a/src/UpgradeFirm.cpp b/src/UpgradeFirm.cpp index 62ffc482..ec953ba7 100644 --- a/src/UpgradeFirm.cpp +++ b/src/UpgradeFirm.cpp @@ -119,6 +119,7 @@ void putUserDataToRam() { update.settingsFlashJson = readFile("settings.json", 4096); update.layoutJson = readFile("layout.json", 4096); update.scenarioTxt = readFile("scenario.txt", 4096); + update.chartsData = createDataBaseSting(); } void saveUserDataToFlash() { @@ -126,6 +127,7 @@ void saveUserDataToFlash() { writeFile("/settings.json", update.settingsFlashJson); writeFile("/layout.json", update.layoutJson); writeFile("/scenario.txt", update.scenarioTxt); + writeDataBaseSting(update.chartsData); } void handleUpdateStatus(bool send, int state) { diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 7eafc283..79611e91 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -101,6 +101,10 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) standWebSocket.sendTXT(num, settingsFlashJson); } + //отправляем все графики в веб для экспорта + if (headerStr == "/expcharts|") { + } + //обработка кнопки сохранить if (headerStr == "/gifnoc|") { writeFileUint8tByFrames("config.json", payload, length, headerLenth, 256); @@ -353,6 +357,45 @@ void sendStringToWs(const String& msg, uint8_t num, String name) { standWebSocket.sendTXT(num, end); } +//особая функция отправки графиков в веб +void publishChartToWs(String filename, int num, size_t frameSize, int maxCount, String id) { + String json; + jsonWriteStr(json, "topic", mqttRootDevice + "/" + id); + jsonWriteInt(json, "maxCount", maxCount); + + String st = "/st/chart.json|" + json; + if (num == -1) { + standWebSocket.broadcastTXT(st); + } else { + standWebSocket.sendTXT(num, st); + } + String path = filepath(filename); + auto file = FileFS.open(path, "r"); + if (!file) { + SerialPrint(F("E"), F("FS"), F("reed file error")); + return; + } + size_t fileSize = file.size(); + SerialPrint(F("i"), F("FS"), "Send file '" + String(filename) + "', file size: " + String(fileSize)); + uint8_t payload[frameSize]; + int countRead = file.read(payload, sizeof(payload)); + while (countRead > 0) { + if (num == -1) { + standWebSocket.broadcastBIN(payload, countRead); + } else { + standWebSocket.sendBIN(num, payload, countRead); + } + countRead = file.read(payload, sizeof(payload)); + } + file.close(); + String end = "/end/chart.json|" + json; + if (num == -1) { + standWebSocket.broadcastTXT(end); + } else { + standWebSocket.sendTXT(num, end); + } +} + // void sendMark(const char* filename, const char* mark, uint8_t num) { // char outChar[strlen(filename) + strlen(mark) + 1]; // strcpy(outChar, mark); diff --git a/src/modules/virtual/Loging/Loging.cpp b/src/modules/virtual/Loging/Loging.cpp index ae048d25..d7649e1f 100644 --- a/src/modules/virtual/Loging/Loging.cpp +++ b/src/modules/virtual/Loging/Loging.cpp @@ -177,12 +177,12 @@ class Loging : public IoTItem { if (fileUnixTimeLocal > reqUnixTime && fileUnixTimeLocal < reqUnixTime + 86400) { noData = false; if (_publishType == TO_MQTT) { - publishChartFileToMqtt(path); + publishChartFileToMqtt(path, id, calculateMaxCount()); } else if (_publishType == TO_WS) { - publishChartToWs(path, _wsNum, 1000); + publishChartToWs(path, _wsNum, 1000, calculateMaxCount(), id); } else if (_publishType == TO_MQTT_WS) { - publishChartFileToMqtt(path); - publishChartToWs(path, _wsNum, 1000); + publishChartFileToMqtt(path, id, calculateMaxCount()); + publishChartToWs(path, _wsNum, 1000, calculateMaxCount(), id); } SerialPrint("i", F("Loging"), String(f) + ") " + path + ", " + getDateTimeDotFormatedFromUnix(fileUnixTimeLocal) + ", sent"); } else { @@ -224,61 +224,6 @@ class Loging : public IoTItem { } } - bool publishChartFileToMqtt(String path) { - File configFile = FileFS.open(path, FILE_READ); - if (!configFile) { - SerialPrint("E", F("Loging"), path + " file reading error, json not created, return"); - return false; - } - String oneSingleJson = configFile.readString(); - configFile.close(); - String topic = mqttRootDevice + "/" + id; - oneSingleJson = "{\"maxCount\":" + String(calculateMaxCount()) + ",\"topic\":\"" + topic + "\",\"status\":[" + oneSingleJson + "]}"; - oneSingleJson.replace("},]}", "}]}"); - SerialPrint("i", "Loging", "json size: " + String(oneSingleJson.length())); - publishChartMqtt(id, oneSingleJson); - return true; - } - - //особая функция отправки графиков в веб - void publishChartToWs(String filename, int num, size_t frameSize) { - String json; - jsonWriteStr(json, "topic", mqttRootDevice + "/" + id); - jsonWriteInt(json, "maxCount", calculateMaxCount()); - - String st = "/st/chart.json|"; - if (num == -1) { - standWebSocket.broadcastTXT(st); - } else { - standWebSocket.sendTXT(num, st); - } - String path = filepath(filename); - auto file = FileFS.open(path, "r"); - if (!file) { - SerialPrint(F("E"), F("FS"), F("reed file error")); - return; - } - size_t fileSize = file.size(); - SerialPrint(F("i"), F("FS"), "Send file '" + String(filename) + "', file size: " + String(fileSize)); - uint8_t payload[frameSize]; - int countRead = file.read(payload, sizeof(payload)); - while (countRead > 0) { - if (num == -1) { - standWebSocket.broadcastBIN(payload, countRead); - } else { - standWebSocket.sendBIN(num, payload, countRead); - } - countRead = file.read(payload, sizeof(payload)); - } - file.close(); - String end = "/end/chart.json|" + json; - if (num == -1) { - standWebSocket.broadcastTXT(end); - } else { - standWebSocket.sendTXT(num, end); - } - } - void clearValue() { String topic = mqttRootDevice + "/" + id; String json = "{\"maxCount\":0,\"topic\":\"" + topic + "\",\"status\":[]}"; diff --git a/src/modules/virtual/LogingDaily/LogingDaily.cpp b/src/modules/virtual/LogingDaily/LogingDaily.cpp index 62e82e0d..fa4d5f59 100644 --- a/src/modules/virtual/LogingDaily/LogingDaily.cpp +++ b/src/modules/virtual/LogingDaily/LogingDaily.cpp @@ -14,6 +14,8 @@ class LogingDaily : public IoTItem { int points; + int testMode; + IoTItem *dateIoTItem; String prevDate = ""; @@ -26,6 +28,7 @@ class LogingDaily : public IoTItem { jsonRead(parameters, F("logid"), logid); jsonRead(parameters, F("id"), id); jsonRead(parameters, F("points"), points); + jsonRead(parameters, F("test"), testMode); if (points > 365) { points = 365; @@ -36,7 +39,7 @@ class LogingDaily : public IoTItem { } void doByInterval() { - if (hasDayChanged()) { + if (hasDayChanged() || testMode == 1) { execute(); } } @@ -72,7 +75,7 @@ class LogingDaily : public IoTItem { float difference = currentValue - prevValue; - jsonWriteInt(logData, "x", unixTime); + jsonWriteInt(logData, "x", unixTime - 120); jsonWriteFloat(logData, "y1", difference); //прочитаем путь к файлу последнего сохранения @@ -167,12 +170,12 @@ class LogingDaily : public IoTItem { f++; if (_publishType == TO_MQTT) { - publishChartFileToMqtt(path); + publishChartFileToMqtt(path, id, calculateMaxCount()); } else if (_publishType == TO_WS) { - publishChartToWs(path, _wsNum, 1000); + publishChartToWs(path, _wsNum, 1000, calculateMaxCount(), id); } else if (_publishType == TO_MQTT_WS) { - publishChartFileToMqtt(path); - publishChartToWs(path, _wsNum, 1000); + publishChartFileToMqtt(path, id, calculateMaxCount()); + publishChartToWs(path, _wsNum, 1000, calculateMaxCount(), id); } SerialPrint("i", F("LogingDaily"), String(f) + ") " + path + ", sent"); @@ -185,61 +188,6 @@ class LogingDaily : public IoTItem { cleanDirectory(dir); } - bool publishChartFileToMqtt(String path) { - File configFile = FileFS.open(path, FILE_READ); - if (!configFile) { - SerialPrint("E", F("LogingDaily"), path + " file reading error, json not created, return"); - return false; - } - String oneSingleJson = configFile.readString(); - configFile.close(); - String topic = mqttRootDevice + "/" + id; - oneSingleJson = "{\"maxCount\":" + String(calculateMaxCount()) + ",\"topic\":\"" + topic + "\",\"status\":[" + oneSingleJson + "]}"; - oneSingleJson.replace("},]}", "}]}"); - SerialPrint("i", "LogingDaily", "json size: " + String(oneSingleJson.length())); - publishChartMqtt(id, oneSingleJson); - return true; - } - - //особая функция отправки графиков в веб - void publishChartToWs(String filename, int num, size_t frameSize) { - String json; - jsonWriteStr(json, "topic", mqttRootDevice + "/" + id); - jsonWriteInt(json, "maxCount", calculateMaxCount()); - - String st = "/st/chart.json|"; - if (num == -1) { - standWebSocket.broadcastTXT(st); - } else { - standWebSocket.sendTXT(num, st); - } - String path = filepath(filename); - auto file = FileFS.open(path, "r"); - if (!file) { - SerialPrint(F("E"), F("FS"), F("reed file error")); - return; - } - size_t fileSize = file.size(); - SerialPrint(F("i"), F("FS"), "Send file '" + String(filename) + "', file size: " + String(fileSize)); - uint8_t payload[frameSize]; - int countRead = file.read(payload, sizeof(payload)); - while (countRead > 0) { - if (num == -1) { - standWebSocket.broadcastBIN(payload, countRead); - } else { - standWebSocket.sendBIN(num, payload, countRead); - } - countRead = file.read(payload, sizeof(payload)); - } - file.close(); - String end = "/end/chart.json|" + json; - if (num == -1) { - standWebSocket.broadcastTXT(end); - } else { - standWebSocket.sendTXT(num, end); - } - } - void publishChartToWsSinglePoint(String value) { String topic = mqttRootDevice + "/" + id; String json = "{\"maxCount\":" + String(calculateMaxCount()) + ",\"topic\":\"" + topic + "\",\"status\":[{\"x\":" + String(unixTime) + ",\"y1\":" + value + "}]}"; diff --git a/src/modules/virtual/LogingDaily/modinfo.json b/src/modules/virtual/LogingDaily/modinfo.json index ed6fe3c3..f335c474 100644 --- a/src/modules/virtual/LogingDaily/modinfo.json +++ b/src/modules/virtual/LogingDaily/modinfo.json @@ -12,7 +12,8 @@ "num": 1, "int": 1, "logid": "t", - "points": 365 + "points": 365, + "test": 0 } ], "about": { @@ -28,7 +29,8 @@ "propInfo": { "int": "Интервал логирования в мнутах, частота проверки смены суток в минутах. Не рекомендуется менять", "logid": "ID накопительной величины которую будем логировать", - "points": "Максимальное количество точек" + "points": "Максимальное количество точек", + "test": "Режим тестирования - график будет обновляться не раз в сутки, а кадый заданный в int интервал" } }, "defActive": true, diff --git a/src/utils/FileUtils.cpp b/src/utils/FileUtils.cpp index 7602abc0..f6c128db 100644 --- a/src/utils/FileUtils.cpp +++ b/src/utils/FileUtils.cpp @@ -323,3 +323,30 @@ IoTFSInfo getFSInfo() { return myFSInfo; } #endif + +String createDataBaseSting() { + String out; + for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { + if ((*it)->getSubtype() == "LogingDaily") { + String id = (*it)->getID(); + id = "/lgd/" + id + "/" + id + ".txt"; + String fileContent = readFile(id, 10000); + if (fileContent == "failed") { + SerialPrint("i", "Export", "file not exist " + id); + } else { + out += "=>" + fileContent + "\r\n"; + } + } + } + return out; +} + +void writeDataBaseSting(String input) { + while (input.length()) { + String line = selectToMarker(input, "\r\n"); + String path = selectToMarker(line, "=>"); + String content = deleteBeforeDelimiter(line, "=>"); + writeFile(path, content); + input = deleteBeforeDelimiter(input, "\r\n"); + } +}