Files
IoTManager/src/modules/virtual/Logging/Loging.cpp
Dmitry Borisenko 9c5624eddf печатаем id
2022-09-11 10:39:51 +02:00

329 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Global.h"
#include "classes/IoTItem.h"
#include "ESPConfiguration.h"
#include "NTP.h"
void *getAPI_Date(String params);
String date;
class Loging : public IoTItem {
private:
String logid;
String id;
String filesList = "";
int points;
int keepdays;
IoTItem *dateIoTItem;
unsigned long interval;
public:
Loging(String parameters) : IoTItem(parameters) {
jsonRead(parameters, F("logid"), logid);
jsonRead(parameters, F("id"), id);
jsonRead(parameters, F("points"), points);
if (points > 300) {
points = 300;
SerialPrint("E", F("Loging"), "'" + id + "' user set more points than allowed, value reset to 300");
}
jsonRead(parameters, F("int"), interval);
interval = interval * 1000 * 60; //приводим к милисекундам
jsonRead(parameters, F("keepdays"), keepdays);
//создадим экземпляр класса даты
dateIoTItem = (IoTItem *)getAPI_Date("{\"id\": \"" + id + "-date\",\"int\":\"20\"}");
IoTItems.push_back(dateIoTItem);
SerialPrint("E", F("Loging"), "created date instance " + id);
}
void doByInterval() {
//если объект логгирования не был создан
if (!isItemExist(logid)) {
SerialPrint("E", F("Loging"), "'" + id + "' loging object not exist");
return;
}
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;
}
regEvent(value, F("Loging"));
String logData = String(unixTimeShort) + " " + value;
//прочитаем путь к файлу последнего сохранения
String filePath = readDataDB(id);
//если данные о файле отсутствуют, создадим новый
if (filePath == "failed" || filePath == "") {
SerialPrint("E", F("Loging"), "'" + id + "' file path not found");
createNewFileWithData(logData);
return;
} else {
// SerialPrint("i", F("Loging"), "'" + id + "' file path found " + filePath);
}
//считаем количество строк
int lines = countLines(filePath);
SerialPrint("i", F("Loging"), "'" + id + "' " + String(lines) + " lines found in file");
//если количество строк до заданной величины
if (lines <= points) {
//просто добавим в существующий файл новые данные
addNewDataToExistingFile(filePath, logData);
//если больше создадим следующий файл
} else {
createNewFileWithData(logData);
}
}
void createNewFileWithData(String &logData) {
String path = "/lg/" + id + "/" + String(unixTimeShort) + ".txt"; //создадим путь вида /lg/id/133256622333.txt
addFileLn(path, logData); //запишем файл и данные в него
saveDataDB(id, path); //запишем путь к файлу в базу данных
SerialPrint("i", F("Loging"), "'" + id + "' file created http://" + WiFi.localIP().toString() + path);
}
void addNewDataToExistingFile(String &path, String &logData) {
addFileLn(path, logData);
SerialPrint("i", F("Loging"), "'" + id + "' loging in file http://" + WiFi.localIP().toString() + path);
}
#if defined(ESP8266)
void getFilesList8266() {
filesList = "";
String directory = "lg/" + id;
auto dir = FileFS.openDir(directory);
while (dir.next()) {
String fname = dir.fileName();
if (fname != "") filesList += directory + "/" + fname + ";";
}
}
#endif
#if defined(ESP32)
void getFilesList32() {
filesList = "";
String directory = "/lg/" + id;
File root = FileFS.open(directory);
directory = String();
if (root.isDirectory()) {
File file = root.openNextFile();
while (file) {
String fname = file.name();
if (fname != "") filesList += fname + ";";
file = root.openNextFile();
}
}
}
#endif
void getFilesList() {
#if defined(ESP8266)
getFilesList8266();
#endif
#if defined(ESP32)
getFilesList32();
#endif
}
void sendChart(int type) {
getFilesList();
int f = 0;
bool noData = true;
while (filesList.length()) {
String buf = selectToMarker(filesList, ";");
f++;
int i = 0;
unsigned long fileUnixTimeGMT = selectToMarkerLast(deleteToMarkerLast(buf, "."), "/").toInt() + START_DATETIME;
unsigned long fileUnixTimeLocal = gmtTimeToLocal(fileUnixTimeGMT);
//удаление старых файлов
// if ((fileUnixTimeLocal + (points * (interval / 1000))) < (unixTime - (keepdays * 86400))) {
// SerialPrint("i", F("Loging"), "file '" + buf + "' too old, deleted");
// removeFile(buf);
//} else {
unsigned long reqUnixTime = strDateToUnix(date);
if (fileUnixTimeLocal > reqUnixTime && fileUnixTimeLocal < reqUnixTime + 86400) {
noData = false;
createJson(buf, i, type);
SerialPrint("i", F("Loging"), String(f) + ")" + buf + ", " + String(i) + ", " + getDateTimeDotFormatedFromUnix(fileUnixTimeLocal) + ", sent");
} else {
SerialPrint("i", F("Loging"), String(f) + ")" + buf + ", " + String(i) + ", " + getDateTimeDotFormatedFromUnix(fileUnixTimeLocal) + ", skipped");
}
//}
filesList = deleteBeforeDelimiter(filesList, ";");
}
//если данных нет отправляем пустой грфик
if (noData) {
SerialPrint("i", F("Loging"), "clear chart");
String cleanJson = createEmtyJson();
publishJson(cleanJson, type);
}
}
void cleanData() {
getFilesList();
int i = 0;
while (filesList.length()) {
String buf = selectToMarker(filesList, ";");
i++;
removeFile(buf);
SerialPrint("i", "Files", String(i) + ") " + buf + " => deleted");
filesList = deleteBeforeDelimiter(filesList, ";");
}
}
void createJson(String file, int &i, int type) {
File configFile = FileFS.open(file, "r");
if (!configFile) {
SerialPrint("E", F("Loging"), "'" + id + "' open file error");
return;
}
configFile.seek(0, SeekSet);
String buf = "{}";
String oneSingleJson;
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 != "") {
oneSingleJson += buf + ",";
}
} while (psn < sz);
configFile.close();
String topic = mqttRootDevice + "/" + id;
oneSingleJson = "{\"maxCount\":" + String(calculateMaxCount()) + ",\"topic\":\"" + topic + "\",\"status\":[" + oneSingleJson + "]}";
oneSingleJson.replace("},]}", "}]}");
publishJson(oneSingleJson, type);
}
void publishJson(String &oneSingleJson, int type) {
if (type == 1) {
publishChart(id, oneSingleJson);
} else if (type == 2) {
publishStatusWsJson(oneSingleJson);
} else if (type == 3) {
publishChart(id, oneSingleJson);
publishStatusWsJson(oneSingleJson);
}
}
String getValue() {
return "";
}
void loop() {
if (enableDoByInt) {
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= interval) {
prevMillis = millis();
this->doByInterval();
}
}
}
void regEvent(String value, String consoleInfo = "") {
generateEvent(_id, value);
publishStatusMqtt(_id, value);
String json = createSingleJson(_id, value);
publishStatusWsJson(json);
SerialPrint("i", "Sensor " + consoleInfo, "'" + _id + "' data: " + value + "'");
}
String createSingleJson(String id, String value) {
String topic = mqttRootDevice + "/" + _id;
return "{\"topic\":\"" + topic + "\",\"status\":[{\"x\":" + String(unixTime) + ",\"y1\":" + value + "}]}";
}
String createEmtyJson() {
String topic = mqttRootDevice + "/" + _id;
return "{\"topic\":\"" + topic + "\",\"status\":[],\"maxCount\":\"0\"}";
}
//просто максимальное количество точек
int calculateMaxCount() {
return 86400;
}
};
void *getAPI_Loging(String subtype, String param) {
if (subtype == F("Loging")) {
return new Loging(param);
} else {
return nullptr;
}
}
class Date : public IoTItem {
private:
bool firstTime = true;
public:
String id;
Date(String parameters) : IoTItem(parameters) {
jsonRead(parameters, F("id"), id);
value.isDecimal = false;
}
void setValue(String valStr) {
value.valS = valStr;
date = valStr;
setValue(value);
}
void setValue(IoTValue Value) {
value = Value;
regEvent(value.valS, "");
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
if ((*it)->getSubtype() == "Loging") {
(*it)->sendChart(3);
}
}
}
void doByInterval() {
if (isTimeSynch) {
if (firstTime) {
setValue(getDateDotFormated());
SerialPrint("E", F("Loging"), "today date set " + getDateDotFormated());
firstTime = false;
}
}
}
};
void *getAPI_Date(String param) {
return new Date(param);
}